- 投稿日:2019-09-29T23:15:08+09:00
コーディングによるビジュアル加工
CSSフィルタ
画像以外にも有効です。
SVGにも有効です。(直書きもimgタグも、背景画像にも、objectで読み込んでも)
※複数適用はカンマ無しの半角スペース
フィルタ名 範囲 初期値 効果 blur 0px~ 0px ぼかし効果 grayscale 0%~100% 0% モノクロ効果 sepia 0%~100% 0% セピア効果 saturate 0%~ 100% 彩度変更 hue-rotate 0deg~360deg 0deg 色相回転 invert 0%~100% 0% 階調反転 opacity 0%~100% 100% 不当明度変更 brightness 0%~ 100% 明度変更 contrast 0%~ 100% コントラスト変更 drop-shadow CSS3のdrop-shadowと同様 - 影効果 url() - - 指定したSVGフィルター適用 Brightness
0%にすると黒、100%でオリジナルと同じ明度です。・
100%以上の値を指定すると、画像を明るくできます。cssimg { filter: brightness(300%); }Hue-rotate
0deg/360degでオリジナルと同じです。
180degで色が反転します。cssimg { filter: hue-rotate(90deg); }Saturate
0%にすると彩度がなくなり、100%でオリジナルと同じになります。
100%以上の値を指定すると、画像を鮮やかにできます。cssimg { filter: saturate(0%); } img { filter: saturate(1000%); }Invert
0%でオリジナル画像が表示され、100%で完全に反転します。
値を50%にすると、灰色1色になります。cssimg { filter: invert(100%); }Contrast
値を0%にすると灰色1色になります。
100%でオリジナルの画像と同じになります。cssimg { filter: contrast(50%); }Grayscale
モノクロ写真を再現
0%でオリジナル画像が表示され、100%で完全にグレーになります。
sturate(0%)はgrayscale(100%)と同じです。cssimg { filter: grayscale(100%); }Sepia
0%でオリジナル画像が表示され、100%で完全にセピアになります。
cssimg { filter: sepia(100%); }Blur
0pxでオリジナル画像が表示され、値が大きくなるほどぼかしの度合いが強くなります。
img { filter: blur(5px); }Opacity
100%で完全に不透明、0%で完全に透明です。
(opacityプロパティと同じ)cssimg { filter: opacity(75%); }Drop Shadow
影
shadowの種類 内容 box-shadow 要素全体 filter: drop-shadow 画像内の透明部分 cssimg { /* filter: drop-shadow(水平方向 垂直方向 影の広がり 色の指定); */ filter: drop-shadow(5px 5px 10px #666); }url()メソッド
独自に作成したSVGフィルターを適用することができます。
そのデータのidを指定します。cssfilter: url(#id);フィルタの重ねがけ
CSSフィルタは複数利用することができます。
適用したいフィルターを続けて入力するだけで重ねがけ可能です。
モノクロでぼかされた画像なども作成できます。cssimg { filter: contrast(175%) brightness(3%); }ジェネレータ
SVGフィルタ
SVGにはCSSより多くのフィルタ効果があり、CSSより複雑な効果が使えます。
効果をかける対象はSVG要素に限らず、DOM要素ならなんでも効果の対象にできます。divにフィルタをかける場合
html<svg class="svgfilter"> <defs> <filter id="GaussianBlur" width="200%" height="200%" filterUnits="userSpaceOnUse"> <feGaussianBlur stdDeviation="10" /> </filter> </defs> </svg> <div class="filter"><img src="image1.jpg" alt=""></div>css.svgfilter { width: 0; height: 0; } .filter { filter: url(#GaussianBlur); }filter要素のfilterUnits属性
x、y、width、height の座標系を定義します。
値 内容 objectBoundingBox(デフォルト) filter要素を使用している要素の比率で設定 userSpaceOnUse filter要素を使用している要素に対する座標が基準 SVGにフィルタをかける場合
svg<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400" > <filter id="mergeTest" x="-100" y="-100" width="500" height="500"> <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" /> </filter> <rect x="50" y="50" width="200" height="200" style="stroke: #333333; fill: #2980b9; filter: url(#mergeTest);" /> </svg>SVGフィルターの種類
フィルタ名 特別な属性 feBlend in,in2,mode feColorMatrix in,type,values feComponentTransfer in feComposite in,in2,operator,k1,k2,k3,k4 feConvolveMatrix in,order,kernelMatrix,divisor,bias,targetX,targetY,edgeMode,kernelUnitLength,preserveAlpha feDiffuseLighting in,surfaceScale,diffuseConstant,kernelUnitLength feDisplacementMap in,in2,scale,xChannelSelector,yChannelSelector feDropShadow dx,dy,stdDeviation feFlood flood-color,flood-opacity feGaussianBlur in,stdDeviation,edgeMode feImage preserveAspectRatio,xlink:href feMorphology in,operator,radius feOffset in,dx,dy feSpecularLighting in,surfaceScale,specularConstant,specularExponent,kernelUnitLength feTile in feTurbulence baseFrequency,numOctaves,seed,stitchTiles,type feMerge
複数フィルタ
子要素として記述したfeMergeNodeタグのin属性で指定された出力画像を、上から順番に重ねます。
描画結果では、先に書いたfeMergeNodeタグの画像が奥になります。svg<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400" > <filter id="mergeTest" x="-100" y="-100" width="500" height="500"> <feOffset in="SourceGraphic" dx="100" dy="100" result="move"/> <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" /> <feMerge> <feMergeNode in="blur" /> <feMergeNode in="move" /> </feMerge> </filter> <rect x="50" y="50" width="200" height="200" style="stroke: #333333; fill: #2980b9; filter: url(#mergeTest);" /> </svg>この場合、SourceGraphicはrect要素で、「ぼかし」と「移動」したものが出力されます。
属性 内容 dx 要素またはそのコンテンツの位置のX軸に沿った移動 dy 要素またはそのコンテンツの位置のX軸に沿った移動 (feColorMatrix要素の)type translate/scale/rotate/skewX/skewY (feTurbulence要素の)type fractalNoise/turbulence in属性,in2属性
フィルタの入力元を指定する属性で、result属性で定義した名前か以下のいずれかになる
値 内容 SourceGraphic フィルタを適用する図形の画像 SourceAlpha アルファチャンネルのみのSourceGraphic(カラーチャンネルはすべて黒になる) BackgroundImage フィルタの効果範囲の背景(適用対象の図形よりも後ろの画像) BackgroundAlpha アルファチャンネルのみのBackgraundAlpha FillPaint 対象図形のfill属性に設定された色で塗り潰した画像を入力とする StrokePaint 対象図形のstroke属性に設定された色で塗り潰した画像を入力とする mode属性
値 内容 normal feMergeと同じ multiply inとin2を乗算する screen 加算合成した値から乗算合成の値を減算する overlay 下の色が暗い場合は乗算、下の色が明るい場合はスクリーン darken inとin2の暗い方を採用 lighten inとin2の明るい方を採用 color-dodge 下の色を上の色の逆数で割った結果(前景が黒い場合変化無し、背景の逆色の前景は完全に明るい色) color-burn 下の色を反転、値を上の色で除算し、その値を反転 hard-light 上の色が暗い場合は乗算、上の色が明るい場合はスクリーン soft-light hard-lightよりソフト difference 明るい色から暗い色を差し引く(黒いレイヤーは効果無し、白いレイヤーは他のレイヤーの色を反転) exclusion differenceとの違いは、コントラストが低くなる hue 上の色の色相、下の色の彩度と明度を使用 saturation 上の色の彩度、下の色の色相と明度を使用(灰色の背景は効果なし) color 上の色の色相と彩度、下の色の明度を使用(グレーレベルを保持) luminosity 上の色の明度、下の色の色相と彩度を使用 operator属性
値 内容 over feMergeと同じ in inの画像のうち、in2と共通の領域のみを出力する out inの画像から、in2と共通の領域を除いたものを出力する atop in2の画像の上にoperator="in"の合成結果を重ねるて出力する xor inとin2を重ねた画像から、inとin2の共通の領域を除いたものを出力する arithmetic k1、k2、k3、k4の各属性値を係数として計算した結果を出力する 光源
feDiffuseLighting
布やゴムなどの表現に適します。
feGaussianBlurは、feDiffuseLightingの入力となるハイトマップを生成します。
輪郭をぼかしたシルエット画像をハイトマップとして使います。
属性 内容 surfaceScale ハイトマップの高さ diffuseConstant 光源の光の強さ lighting-color 光源の色 ライトの情報は、feDiffuseLightingタグの子要素として記述
光源の種類 内容 feDistantLight 平行光源 fePointLight 点光源 feSpotLight スポットライト operator
feCompositeのoperator="arithmetic"で元の画像と合成します。
合成方法がarithmeticの場合、feCompositeタグにはk1~k4の4つの属性を指定できます。
feCompositeの属性 内容 k1 物体の色とライティング結果は乗算にするので1 k2 不要なので0 k3 環境光をエミュレートするためにk3に適当な値を指定 k4 不要なので0 svg<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400" > <filter id="lighting"> <feGaussianBlur stdDeviation="8" in="SourceAlpha" /> <feDiffuseLighting surfaceScale="10" diffuseConstant="1" lighting-color="#fff" result="diffuse"> <fePointLight x="50" y="50" z="50" /> </feDiffuseLighting> <feComposite operator="arithmetic" in="diffuse" in2="SourceGraphic" k1="1" k2="0" k3="0.5" k4="0" /> </filter> <circle cx="100" cy="100" r="50" fill="#1e90ff" filter="url(#lighting)"/> </svg>※feGaussianBlurは、feDiffuseLightingで使うハイトマップを生成
feSpecularLighting]
プラスチックや金属のような鏡面反射光の表現に適します。
属性 内容 specularConstant ライトの強さ specularExponent 値を大きくすると金属的な鋭いハイライトになる ※他の属性、ライトの指定方法はfeDiffuseLightingと同じです。
operator
feCompositeのoperator="arithmetic"で元の画像と合成します。
合成方法がarithmeticの場合、feCompositeタグにはk1~k4の4つの属性を指定でます。
feCompositeの属性 内容 k1 合成方法を加算にするので1 k2 不要なので0 k3 合成方法を加算にするので1 k4 不要なので0 svg<filter id="lighting"> <feGaussianBlur stdDeviation="8" in="SourceAlpha" /> <feSpecularLighting surfaceScale="10" specularConstant="1" specularExponent="10" lighting-color="#fff" result="specular"> <fePointLight x="250" y="-50" z="100" /> </feSpecularLighting> <feComposite operator="arithmetic" in="specular" in2="SourceGraphic" k1="0" k2="1" k3="1" k4="0" /> </filter> <circle cx="100" cy="100" r="50" fill="#1e90ff" filter="url(#lighting)"/> </svg>※feGaussianBlurは、feDiffuseLightingで使うハイトマップを生成
学習ツール
SVG Filters
SVGフィルターをスライダーで操作して、結果を確認しながら学習できます。mix-blend-mode
※IEとEdgeでは使えません。
cssmix-blend-mode: overlay;
値 意味 内容 darken 比較(暗) 上下の画像を比較して暗いピクセルが表示される lighten 比較(明) 上下の画像を比較して明るいピクセルが表示される multiply 乗算 暗い表現を作るときに使う描画モード color-burn 焼きこみ 乗算よりもより暗くなる描画モード screen スクリーン 明るい表現を作るときに使う color-dodge 覆い焼き スクリーンよりもより明るくなる overlay オーバーレイ 乗算とスクリーンの両方に近い効果 soft-light ソフトライト 明るい部分はさらに明るく、暗い部分はさらに暗くする hard-light ハードライト ソフトライトよりも強い効果が得られる difference 差の絶対値 二枚の画像の違いを可視化 exclusion 除外 差の絶対値よりも弱い効果が得られる hue 色相 下レイヤーの輝度と彩度、上レイヤーの色相 saturation 彩度 下レイヤーの輝度と色相、上位レイヤー彩度 color カラー 下レイヤーの輝度、上位レイヤーの彩度と色相 輝度 luminosity HSL色空間で合成 下レイヤーの彩度と色相、上位レイヤーの輝度 html<div class="image1"><img src="image1.jpg" alt=""></div> <div class="image2"><img src="image2.jpg" alt=""></div>css.image1 { position: absolute; z-index: 0; } .image2 { position: absolute; z-index: 1; mix-blend-mode: luminosity; }
- 投稿日:2019-09-29T21:43:08+09:00
【メモ】CSSのhover処理をスマートフォンでも適用させる
はじめに
ポートフォリオ作成時、画像の上にカーソルを置いた時に文字を浮かび上がらせる処理をしていました。
その処理をスマホでも適用させるための実装のメモを残します。結論
HTMLに以下を追加するのみです!
<div class='top' ontouchstart="">ontouchstart="" という属性を追加することでスマホ(タッチデバイス)でも画像をタップした際にhover時の動きをしてくれます。
ontouchstartとは、その名の通り「指先が触れた時に発生する」イベントです。この属性を追加しないと、スマホ時にhoverが反応しない事を本番環境にアップしてから気づいたので、スマホ時でのテストも大事ですね。(当たり前)
CSSに関しては何も追加しなくても適用されます。
終わる
以上、ただのメモでした。
- 投稿日:2019-09-29T14:57:18+09:00
[初投稿]CSS:FlexBoxレイアウトのチートシート
前置き
初めての投稿になるので文章が拙い部分や意味を誤認識している部分もあるかと思います。お気付きのことがあればご指摘いただけると幸いです。
概要
要素を簡単な記述で整列、配置が可能な為、mediaクエリを使用することでレスポンシブ対応が容易に可能になる便利なレイアウトです。(語彙力。。。)
詳しくは下記を参考にしてください。笑
仕様
W3C公式ページをご覧ください。
日本語訳をしてくださっているページもありました。ブラウザの対応状況
こちらから最新の状態を確認してください。 2019.9.29現在はほぼ全てのブラウザで対応されています。
用語
flex-container
FlexBoxレイアウトを使用する範囲です。子要素には適用されますが孫要素に適用されないので注意が必要です。
flex-items
コンテナの子要素です。FlexBoxレイアウトが適用されます。
主軸(main-axis)
後述するflex-directionの設定方向であり、アイテムを整列させる方向です。。
デフォルトは行方向(横方向)になります。交差軸(cross-axis)
記述について
コンテナとアイテムで可能な宣言は以下の通りです。
宣言/* 全てデフォルト値 */ flex-container{ flex-flow: row nowrap; /*アイテムの整列・折り返し: 横並び 折り返さない*/ justify-content: normal; /*余白の指定: 規定の値*/ align-items: stretch; /*交差軸方向の配置: */ align-content: } flex-item{ flex:none; /* アイテムをコンテナに収めるために、どのように伸長・収縮させるかを指定する。 デフォルトではアイテムはwidth,heightの値で固定。 */ order:0; /* 視覚的に配置を変更する */ }下記でそれぞれの宣言について詳しく説明していきます。
flex-container
以下、コンテナ側のプロパティについて詳細を説明していきます。
コンテナに設定できるプロパティは以下の通りです。
フレックスコンテナ内に宣言すると言う意味でコード上ではflex-container{}内でプロパティを紹介していきます。flex-container/* 全てデフォルト値 */ flex-container{ flex-flow: row nowrap; /*アイテムの整列・折り返し: 横並び 折り返さない*/ justify-content: normal; /*余白の指定: 規定の値*/ align-items: stretch; /*交差軸方向の配置: */ align-content: }flex-flow(アイテムの整列・折り返しの指定)
flex-directionとflex-wrapの一括指定プロパティです。
値の詳細は下記のflex-directionとflex-wrapに記します。
flex-directionとflex-wrapのそれぞれの値を使い指定します。flex-flow: <'flex-direction'> || <'flex-wrap'>
デフォルトflex-container{ flex-flow:row nowrap; }flex-direction(アイテムの整列)
アイテムの整列方向を指定します。 以下、各値の詳細
flex-directionflex-container{ flex-direction: row; /* 行のテキストの方向に配置 */ flex-direction: row-reverse; /* <row> と同様だが、逆向き */ flex-direction: column; /* 列方向に配置する */ flex-direction: column-reverse; /* <column> と同様だが、逆向き */ }flex-wrap(アイテムの折り返し)
アイテムがコンテナから溢れる時、折り返すか押し込むかを指定するプロパティです。 以下、各値の詳細です。
flex-wrapflex-container{ flex-wrap: nowrap; /* 折り返しなし 押し込む*/ flex-wrap: wrap; /* main-axis方向に折り返し*/ flex-wrap: wrap-reverse; /* wrapと逆方向に折り返し */ }justify-content (主軸方向に余白がある時の整列を指定)
主軸方向に余白ができた時のアイテムの整列の仕方を指定する。
justify-contentflex-container{ /* 位置による配置 */ justify-content: flex-start; /* 主軸方向の先頭に寄せる */ justify-content: flex-end; /* 主軸方向の末尾に寄せる */ justify-content: center; /* 主軸方向の中央に寄せる */ /* 均等配置 */ justify-content: space-between; /* 両端のアイテムはコンテナに合わせて配置し、各アイテムを均等に配置 */ justify-content: space-around; /* 各アイテムを均等に配置し行の両端に半分の大きさの間隔を置く */ justify-content: space-evenly; /* 各アイテムを均等に配置し全てのアイテムに同じ大きさの間隔を置く */ justify-content: stretch; /* 各アイテムを均等に配置しサイズが 'auto' であるアイテムは、コンテナーに合わせて引き伸ばす */ }align-content(全ての要素で交差軸方向の配置)
交差軸方向の配置を全ての要素で指定します。justify-contentの交差軸版
align-contentflex-container{ /* 位置による配置 */ align-content: flex-start; /* 交差軸方向の先頭に寄せる */ align-content: flex-end; /* 交差軸方向の末尾に寄せる */ /* 均等配置 */ align-content: space-between; /* 両端のアイテムはコンテナに合わせて配置し、各アイテムを均等に配置 */ align-content: space-around; /* 各アイテムを均等に配置し行の両端に半分の大きさの間隔を置く */ align-content: space-evenly; /* 各アイテムを均等に配置し全てのアイテムに同じ大きさの間隔を置く */ align-content: stretch; /* 各アイテムを均等に配置しサイズが 'auto' であるアイテムは、コンテナーに合わせて引き伸ばす */ }align-items(行単位で交差軸方向の配置)
交差軸方向の配置を行単位で指定します。
align-itemsflex-container{ align-items: stretch; /* 制約の範囲内に収まるようサイズを変更する*/ /* 位置による配置 main-axis方向の指定はないので注意*/ align-items: center; /* アイテムを中央付近にまとめる */ align-items: flex-start; /* 交差軸方向の先頭にまとめる */ align-items: flex-end; /* 交差軸方向の末尾にまとめる */ }flex-items
以下、アイテム側のプロパティについて詳細を説明していきます。
アイテムに設定できるプロパティは以下の通りです。
フレックスアイテム内に宣言すると言う意味でコード上ではflex-item{}内でプロパティを紹介していきます。flex-items/* 全てデフォルト値 */ flex-item{ flex:none; /* アイテムをコンテナに収めるために、どのように伸長・収縮させるかを指定する。 デフォルトではアイテムはwidth,heightの値で固定。 */ order:0; /* 視覚的に配置を変更する */ }flex(アイテムをコンテナに収めるために、どのように伸長・収縮させるかを指定)
flex-grow,flex-shrink,flex-basisの一括指定プロパティです。値の数によって効果が異なります。
値が一つの場合
単位無しの数値であればflex-grow、widthとして有効な値であればflex-basisとして扱われます。
flex:flex-grow | flex-shrink
値が二つの場合
最初の値は単位無しで記述し、flex-growとして扱われます。2つ目の値は単位無しであればflex-shrink,widthとして有効な値であればflex-basisとして扱われます。
flex:flex-grow && flex-shriknk | flex-basis
値が三つの場合
値はflex-grow,flex-shrink,flex-basisの順で記述し、flex-growとflex-shrinkは単位無しの数値flex-basisについてはwidthとして有効な値で記述します。
flex:flex-grow or flex-shrink
例外
flex例外flex-item{ flex:auto; /* flex: 1 1 auto コンテナに合うように伸縮をする*/ flex:initial; /* flex: 0 1 auto コンテナに合うように縮小はするが引き伸ばさない。 */ }-注意-
flex-grow,flex-shrink,flex-basisはそれぞれのプロパティと共に使用されるため、3つのプロパティが宣言されていることを保証するためflexで一括指定した方が良い
flex-growは与えられた比率が大きいほど引き伸ばされるためアイテムは大きくなるが、flex-shrinkは与えられた比率が小さいほど縮小されるためアイテムは小さくなる。flex-grow(コンテナに余裕がある時アイテムを引き延ばす比率)
コンテナに空間がある時に、アイテムにどれだけの比率を配分するか(伸縮係数)を記述する。
比率は他のアイテムに割り当てられている伸縮係数の合計の内、そのアイテムが締める伸縮係数の割合で配分される。
負の値を記述することはできない。flex-grow: <number>;
flex-shrink(コンテナに当てはまるようにアイテムを縮小する比率)
コンテナからアイテムがはみ出す時、どの程度の割合でアイテムを縮小するかを記述する。
負の値を記述することはできない。
flex-shrink: <number>;
flex-basis(アイテムの初期サイズ)
アイテムの初期サイズを記述します。値はwidthに指定できるもの(px,emなどの絶対指定や%による指定)が使用できます。負の値の指定はできません。
flex-basis: <width>;
align-self
flex-containerで指定できるaligin-itemsの値を上書きして指定することができます。使うことができる値はalign-itemsと同じです。
order (視覚的な配置を変更する)
視覚的な見た目を変更します。値を整数値で指定し、数値が小さい順に並び替えられます。
order: <integer>;
orderflex-item{ order:0; /* 数値が小さい順に視覚的に入れ替えられます */ }order は要素の視覚上の順序にのみ影響を与えるものであり、論理的な順序やタブオーダーには影響を与えません。order を speech など、視覚的ではないメディアで使用してはいけません。
ソース
MDN
- 投稿日:2019-09-29T14:23:50+09:00
カレンダー機能
..html
<select name="month" id="month"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select>ulタグ
h1タグ
..javascript
'use strict';
{
var select = document.querySelector('select');
var list = document.querySelector('ul');
var h1 = document.querySelector('h1');select.onchange = function() { var choice = select.value; // 条件式をここに書く var days = 31; if(choice === '4' || choice === '6' || choice === '9' || choice === '11'){ days = 30; }else if(choice === '2'){ days = 28; } createCalendar(days, choice + ' 月'); } function createCalendar(days, choice) { list.innerHTML = ''; h1.textContent = choice; for (var i = 1; i <= days; i++) { var listItem = document.createElement('li'); listItem.textContent = i; list.appendChild(listItem); } } createCalendar(31,'1 月'); }..css
body{
padding: 0;
margin: 0;
box-sizing: border-box;
}
ul{
padding: 0;
margin: 0;
width: 100%;
float: left;
}
ul li{
list-style: none;
background: pink;
text-align: center;
margin: 3px;
float: inherit;
width: 20%;
user-select: none;
}
- 投稿日:2019-09-29T04:37:37+09:00
セレクタ 属性値指定
- 投稿日:2019-09-29T02:24:09+09:00
Chainable BEM modifiersを使ってmodifierを効率的に書く
はじめに
CSS in JS
やCSS Modules
が主流の時代に、今さらBEM
かよ。。の記事になるかもしれませんが、Chainable BEM modifiers
やBEVM
について日本語で書かれている記事があまり無かったこともあり、自分の取り入れ方の紹介も兼ねて書いてみることにしました。対象読者
- SCSSが使える(読める)方
- BEM(MindBEMding)について理解があり、実際に使ったことがある方
- MindBEMdingの
Modifer
の書き方に煩わしさを感じている方
Chainable BEM modifiers
is 何?Jordan Lewisという方が、従来のBEMのModifierに対する課題を解消するために提唱されたソリューションです。
因みに、現時点で
Jordan Lewis
でググると、一番上にはオーストラリア式フットボール選手がヒットしますが、多分その人ではありません。Chainable BEM modifiers
https://webuild.envato.com/blog/chainable-bem-modifiers/スライド
https://www.slideshare.net/jordanlewiz/chainable-bem-modifiersChainable BEM modifiersの書き方
BEMのModiferを表すクラスセレクタを、接頭辞
-
に続けて名前空間(key)、値(value)のセットで書きます。Chainable BEM modifiersの例(公式な書き方)
<!-- Large green button --> <button class="btn -color-green -size-large">SCSSをつかってルールセットを書くと、次のようになります。
.btn { font-size: 20px; background-color: grey; &.-color-green { background-color: green; } &.-size-large { font-size: 30px; padding: 10px; } }従来のBEMのModiferの書き方
マルチクラスとシングルクラスでそれぞれ同じものを表すことができます。
Chainable BEM modifiersはマルチクラスの書き方に近いです。マルチクラス(クラスが連鎖している)
<button class="btn btn--color-green btn--size-large">.btn { font-size: 20px; background-color: grey; &.btn--color-green { background-color: green; } &.btn--size-large { font-size: 30px; padding: 10px; } }シングルクラス
<button class="btn--primary">.btn { font-size: 20px; background-color: grey; } .btn--primary { @extend .btn; background-color: green; font-size: 30px; padding: 10px; }上記のマルチクラスとシングルクラス、それぞれ表現方法は違えど、適用されるスタイルは結果的に同じものになります。
それぞれに適したシナリオが有りますが、Modiferを使った異なる規約が存在するのは混乱を招く、とLewis氏は嘆いています。Whilst both techniques are valid, they lend themselves for use in different scenarios. Plus, having two conventions using identical syntax in the same codebase is a recipe for confusion.
BEVMの登場
そこで登場したのが
BEVM
で、V
はVariationを表します。
従来のModiferを使ったシングルクラスのアプローチを、代わりにVariationに置きかえよう、という試みです。Modiferも含めると、
block__element--variation -modifier
という構文になります。(Element
が無い場合にはblock--variation
)なので、Variationを表す書き方は従来のBEMのModiferと同じになりますが、Modifierで扱ってきたものを、Variation(基本のものとは明確に異なる形態)とModifer(基本のものとは一部または少しの変化が生じたもの)に分けて、それぞれ扱いを区別しようという考えです。
実際どう使っているか?
結論、自分(というか、自分たち)はBEVMの
V
は使っておらず、ModiferだけChainable BEM modifiersの考えに近いものを取り入れています。Chainable BEM modifiersでは、
- 名前空間(key)と値(value)の組み合わせでセレクタ名を書く
- 例:
-color-red
,-size-large
- 基本となるモジュール(BlockまたはElement)に対して、同じCSSプロパティを2回以上変更してはいけない
- OK例:
<div class="btn -color-red -size-large">
- NG例:
<div class="btn -color-red -color-green">
がルールとして定められています。
課題感としては、何がVariationで何がModiferなのかを区別するのが面倒なことと、Block、Element、Modifierに続けて新しい書き方を覚えたくない、覚えさせたくないということw
ただ、それならば従来のMindBEMdingの書き方に戻るのかと言うと、それはちょっと勿体なく、Chainable BEM modifiersのおいしいところを取り入れることにしています。
従来のMindBEMdingでは、
<button class="btn btn--color-green btn--size-large">と書いていたのを、Chainable BEM modifiersを使うと
<button class="btn -color-green -size-large">となり、Modiferを表すセレクタから
btn-
が外れただけでエコになっているのですが、これを更に名前空間(key)を省略する形で<button class="btn -green -large">としています。
SCSSでは、次のようになります。.btn { font-size: 20px; background-color: grey; &.-green { background-color: green; } &.-large { font-size: 30px; padding: 10px; } }最初のMindBEMdingのセレクタ名から
btn--color
、btn--size
が外れて、かなりエコになりました。また、従来のシングルクラスのように、次のような書き方もすることがありますが、なるべくHTMLを見ただけでどんなスタイルなのかが予測できるのが好ましいと考えています。
<button class="btn -primary"> <button class="btn -secondary">.btn { font-size: 20px; background-color: grey; &.-primary { background-color: green; font-size: 30px; padding: 10px; } &.-secondary { background-color: blue; } }おまけ(状態を表すもの)
サーバー側もしくはJavaScriptによって、何らかの方法で変更された状態をあらわすクラスには接頭辞
is-
を付けましょう、と公式には書かれています。<input class="f-input -type-string is-invalid">.f-input { &.is-invalid { color: red; border: 1px solid red; } }SMACCSの考えが取り入れられているのかもしれませんが、これも個人的には
is-
を付けるメリットがあまり感じられず、そのルールを覚える学習コストの方が上回るため、他のModiferと同じ扱いにしても良いのでは?と考えています。おわりに
CSSを取り巻く設計手法はBEMの他にも色々と存在しますが、公式の形にとらわれずに、自分たちにとって都合の良いように取り入れて、上手く運用できればそれで良いのではないかと思います。
にしても、CSSはグローバル汚染問題やセレクタの命名が辛い。。
出来ることなら、コンポーネント指向のSPAでCSS in JSしたいです。
- 投稿日:2019-09-29T00:06:05+09:00
エンジニアスタンプラリー~フロントエンド編#6
企画主旨
Frontend Developer Roadmapをひたすら巡回する企画
詳しくはこちら今回の実施内容
CSSアーキテクチャ
ツールとかではなく設計手法のようだ。CSS Architectures
BEM
Block, Element, Modifierで構成や命名をする。筆者的には初めましてキーワード。
公式サイトQuick start / Methodology / BEMを参考にしてクラス名を決めた。
&を使ったSCSSの記述は良くないって聞いたけど、スタンプ獲得できれば問題なし。index.html<header class="header"> <h1 class="header__title">Frontend Developer Roadmap スタンプラリー</h1> <nav class="top-bar row justify-content-center"> <h2 class="top-bar__item top-bar__item_active col-sm-6"><a class="top-bar__link top-bar__link_front" href="#">フロントエンド</a></h2> <h2 class="top-bar__item top-bar__item_inactive col-sm-6"><a class="top-bar__link top-bar__link_back" href="#"> バックエンド</a></h2> </nav> </header>main.scss.header { &__title { font-size: 3em; text-align: center; margin: 0; padding: 30px 0; color: #00539f; animation: fadeInTitle 3s ease-in; } } .top-bar { &__item { margin: 0; padding: 20px 0; text-align: center; &_active{ background-color: $bg-color; } &_inactive{ background-color: white; } } &__link { display: block; text-align: center; &:hover { text-decoration: none; } } }成果物
厳密な命名をすればコードの統一感は増すし、依存関係とかもはっきりするかな、といったところ。
https://tonchan1216.github.io/WDR-frontend/v6/
https://github.com/tonchan1216/WDR-frontend/tree/v6.0