20190929のCSSに関する記事は7件です。

コーディングによるビジュアル加工

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%以上の値を指定すると、画像を明るくできます。

css
img {
  filter: brightness(300%);
}

Hue-rotate

0deg/360degでオリジナルと同じです。
180degで色が反転します。

css
img {
  filter: hue-rotate(90deg);
}

Saturate

0%にすると彩度がなくなり、100%でオリジナルと同じになります。
100%以上の値を指定すると、画像を鮮やかにできます。

css
img {
  filter: saturate(0%);
}

img { 
 filter: saturate(1000%); 
}

Invert

0%でオリジナル画像が表示され、100%で完全に反転します。
値を50%にすると、灰色1色になります。

css
img {
  filter: invert(100%);
}

Contrast

値を0%にすると灰色1色になります。
100%でオリジナルの画像と同じになります。

css
img {
  filter: contrast(50%);
}

Grayscale

モノクロ写真を再現
0%でオリジナル画像が表示され、100%で完全にグレーになります。
sturate(0%)はgrayscale(100%)と同じです。

css
img {
  filter: grayscale(100%);
}

Sepia

0%でオリジナル画像が表示され、100%で完全にセピアになります。

css
img {
  filter: sepia(100%);
}

Blur

0pxでオリジナル画像が表示され、値が大きくなるほどぼかしの度合いが強くなります。

img {
  filter: blur(5px);
}

Opacity

100%で完全に不透明、0%で完全に透明です。
(opacityプロパティと同じ)

css
img {
  filter: opacity(75%);
}

Drop Shadow

影

shadowの種類 内容
box-shadow 要素全体
filter: drop-shadow 画像内の透明部分
css
img {
  /* filter: drop-shadow(水平方向 垂直方向 影の広がり 色の指定); */
  filter: drop-shadow(5px 5px 10px #666);
}

url()メソッド

独自に作成したSVGフィルターを適用することができます。
そのデータのidを指定します。

css
filter: url(#id);

フィルタの重ねがけ

CSSフィルタは複数利用することができます。
適用したいフィルターを続けて入力するだけで重ねがけ可能です。
モノクロでぼかされた画像なども作成できます。

css
img { 
  filter: contrast(175%) brightness(3%);
}

ジェネレータ

CSSFilterGenerator.com

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では使えません。

css
mix-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;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】CSSのhover処理をスマートフォンでも適用させる

はじめに

ポートフォリオ作成時、画像の上にカーソルを置いた時に文字を浮かび上がらせる処理をしていました。
その処理をスマホでも適用させるための実装のメモを残します。

結論

HTMLに以下を追加するのみです!

<div class='top' ontouchstart="">

ontouchstart="" という属性を追加することでスマホ(タッチデバイス)でも画像をタップした際にhover時の動きをしてくれます。
ontouchstartとは、その名の通り「指先が触れた時に発生する」イベントです。

この属性を追加しないと、スマホ時にhoverが反応しない事を本番環境にアップしてから気づいたので、スマホ時でのテストも大事ですね。(当たり前)

CSSに関しては何も追加しなくても適用されます。

終わる

以上、ただのメモでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初投稿]CSS:FlexBoxレイアウトのチートシート

前置き

初めての投稿になるので文章が拙い部分や意味を誤認識している部分もあるかと思います。お気付きのことがあればご指摘いただけると幸いです。

概要

要素を簡単な記述で整列、配置が可能な為、mediaクエリを使用することでレスポンシブ対応が容易に可能になる便利なレイアウトです。(語彙力。。。)

詳しくは下記を参考にしてください。笑

仕様

W3C公式ページをご覧ください。
日本語訳をしてくださっているページもありました。

ブラウザの対応状況

こちらから最新の状態を確認してください。 2019.9.29現在はほぼ全てのブラウザで対応されています。

用語

flex-container

FlexBoxレイアウトを使用する範囲です。子要素には適用されますが孫要素に適用されないので注意が必要です。

flex-items

コンテナの子要素です。FlexBoxレイアウトが適用されます。

主軸(main-axis)

後述するflex-directionの設定方向であり、アイテムを整列させる方向です。。
デフォルトは行方向(横方向)になります。

交差軸(cross-axis)

主軸と直角に交わる軸です。
image↓IMG_0631.PNG

記述について

コンテナとアイテムで可能な宣言は以下の通りです。
宣言
/* 全てデフォルト値 */
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-direction
flex-container{
 flex-direction: row;  /* 行のテキストの方向に配置 */
 flex-direction: row-reverse;  /* <row> と同様だが、逆向き */
 flex-direction: column;  /* 列方向に配置する */
 flex-direction: column-reverse;  /* <column> と同様だが、逆向き */
}

flex-wrap(アイテムの折り返し)

アイテムがコンテナから溢れる時、折り返すか押し込むかを指定するプロパティです。 以下、各値の詳細です。
flex-wrap
flex-container{
 flex-wrap: nowrap; /* 折り返しなし 押し込む*/
 flex-wrap: wrap; /* main-axis方向に折り返し*/
 flex-wrap: wrap-reverse; /* wrapと逆方向に折り返し */
}

justify-content (主軸方向に余白がある時の整列を指定)

主軸方向に余白ができた時のアイテムの整列の仕方を指定する。
justify-content
flex-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-content
flex-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-items
flex-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>;

order
flex-item{
 order:0; /* 数値が小さい順に視覚的に入れ替えられます */
}

order は要素の視覚上の順序にのみ影響を与えるものであり、論理的な順序やタブオーダーには影響を与えません。order を speech など、視覚的ではないメディアで使用してはいけません。

ソース

MDN

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

カレンダー機能

..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;
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

セレクタ 属性値指定

セレクタの属性値指定

書式 説明
E[attr] 一つの属性名を指定する
E[attr="value"] 完全に一致する属性値を指定する
E[attr^="value"] 先頭が完全に一致する属性値を指定する
E[attr$="value"] 最後尾が一致する属性値を指定する
E[attr*="value"] 部分的に一致する属性値を指定する
E[attr~="value"] 属性値を空白記号で区切り、単語のうち一つと完全一致する値を指定する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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-modifiers

Chainable 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したいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エンジニアスタンプラリー~フロントエンド編#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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む