Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8780

styled-componentsで条件付きmixinをする方法

$
0
0
はじめに styled-componentsで条件付きレンダリングをする場合、以下のように、項目ごとに場合分けをする例をよく見ます 基本はこれで問題ないのですが、場合分けの種類が増えて来ると、管理が面倒になります。 この場合、場合分けの条件ごとにclassのようにスタイリングをまとめたいと思うのが自然だと思います。 そこで、複数の項目をclassの有無のように一気に設定した場合についてわからなかったので、調べました。 const Wrapper = styled.div.attrs((props) => ({ ...props, }))` background: ${(props) => (props.hoge ? '#fff' : '#000')}; ` やりたいこと 以下のようにpropsの条件一つでスタイリングが大きく変わる場合を想定します。 上の場合と下の場合で、個別にcssを管理することを目標とします。 まずはデフォルトの状態を準備 まずは、props.typeに何も指定していない、アニメーションのない状態を実装します。 import React, { VFC } from "react"; import styled from "styled-components"; export type ButtonProps = { className?: string; type?: "bgleft" | "bgright"; }; const Button: VFC<ButtonProps> = ({ className, type }: ButtonProps) => { return ( <WrapperButton className={className} type={type}> <span>ボタン</span> </WrapperButton> ); }; const WrapperButton = styled.a.attrs((props) => ({ ...props }))` /* default */ position: relative; overflow: hidden; text-decoration: none; display: inline-block; border: 1px solid #555; padding: 10px 30px; text-align: center; outline: none; transition: ease 0.2s; span { position: relative; z-index: 3; color: #333; } :hover { span { color: #fff; } } `; export default Button; MixInの定義 次に左右から動作するアニメーションをMixInで定義します。 最初に、styled-componenstからcssをインポートします。 import React, { VFC } from "react"; import styled, { css } from "styled-components"; //ここ 次にMixInを定義します。 それぞれ、左右から動作する部分のcssです。 const MixInBgLeft = css` &:before { content: ""; position: absolute; top: 0; left: 0; z-index: 2; background-color: #333; width: 100%; height: 100%; transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s; transform: scale(0, 1); transform-origin: right top; } &:hover:before { transform-origin: left top; transform: scale(1, 1); } `; const MixInBgRight = css` &:before { content: ""; position: absolute; top: 0; left: 0; z-index: 2; background-color: #333; width: 100%; height: 100%; transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s; transform: scale(0, 1); transform-origin: left top; } &:hover:before { transform-origin: right top; transform: scale(1, 1); } `; 条件付きでレンダリング 最後にstyledの中にMixInを条件付きで追加します。 const WrapperButton = styled.a.attrs((props) => ({ ...props }))` //....省略 /* typeにbgleftを選択した場合 */ ${(props) => props.type === "bgleft" && MixInBgLeft} /* typeにbgrightを選択した場合 */ ${(props) => props.type === "bgright" && MixInBgRight} `; このbuttonを使う側は以下のようにして使います。 import Button from '***' <Button type="bgleft" /> // or <Button type="bgright" /> 最後に 今回の例だと、最初に紹介した、項目ごとに場合分けする場合でもよかったかも知れませんが、props.typeが増える場合を考えると、このような方ほでの実装も悪くはないかも知れません。 もっと良い方法があればぜひ共有してください。 最後に全部まとめたコードを貼ります。 import React, { VFC } from "react"; import styled, { css } from "styled-components"; export type ButtonProps = { className?: string; type?: "bgleft" | "bgright"; }; const Button: VFC<ButtonProps> = ({ className, type }: ButtonProps) => { return ( <WrapperButton className={className} type={type}> <span>ボタン</span> </WrapperButton> ); }; const MixInBgLeft = css` &:before { content: ""; position: absolute; top: 0; left: 0; z-index: 2; background-color: #333; width: 100%; height: 100%; transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s; transform: scale(0, 1); transform-origin: right top; } &:hover:before { transform-origin: left top; transform: scale(1, 1); } `; const MixInBgRight = css` &:before { content: ""; position: absolute; top: 0; left: 0; z-index: 2; background-color: #333; width: 100%; height: 100%; transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s; transform: scale(0, 1); transform-origin: left top; } &:hover:before { transform-origin: right top; transform: scale(1, 1); } `; const WrapperButton = styled.a.attrs((props) => ({ ...props }))` /* default */ position: relative; overflow: hidden; text-decoration: none; display: inline-block; border: 1px solid #555; padding: 10px 30px; text-align: center; outline: none; transition: ease 0.2s; span { position: relative; z-index: 3; color: #333; } :hover { span { color: #fff; } } /* typeにbgleftを選択した場合 */ ${(props) => props.type === "bgleft" && MixInBgLeft} /* typeにbgrightを選択した場合 */ ${(props) => props.type === "bgright" && MixInBgRight} `; export default Button;

Viewing all articles
Browse latest Browse all 8780

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>