browserslistはpackage.jsonに書くか.browseslistrcに書くか

browserslistとは何か

名前のとおりターゲットブラウザを設定できるツールで色々なNodeのツールで使用できます。
例えばautoprefixerやbabel、postcss-preset-envなどはbrowserslistを解析してそこで設定されているブラウザを対象にした処理を行うようになっています。
2022年7月現在、browserslistの設定方法は2種類あります。

  1. package.jsonにbrowserslistという項目として記述する
  2. .browserslistrcというファイルを新しく作成しそこに記述する

1,2では記述方法が違うので注意が必要です。

browserslistは%(パーセンテージ)で設定できるがシェア率はどこでわかるの?

browserslistはCan I Useのデータを使用しています。
※browserslistのgithubページのREADME参照

そしてCan I usestatcounter GlobalStatsというサービスを利用しています。

ということはbrowserslistのブラウザのシェア率を決めているのはstatcounter GlobalStatsというサービスです。

statcounter GlobalStatsがどのようにデータを取得しているからは不明です…。

Stylelintを利用してコードを自動整形する方法

cssを分析して間違いを指摘してくれるツールStylelint。
これを使えば複数人でコードを共有していても自動的に同じ作法で書かれたコードを作ることができます。
一度その仕組みを組んでしまえばあとは楽で便利ですが、導入部分が少し複雑なのでnpm-scriptsでStylelintを稼働して作法がバラバラなCSSファイルを自動整形できるようにするまでの流れを残して置きます。

前提条件

  • node.jsがインストールされている

ディレクトリ構造作成+パッケージインストール

プロジェクトフォルダを作成しnpmで必要なパッケージをインストールします

mkdir lintTest

cd lintTest

npm init -y 

npm i -D stylelint stylelint-config-standard stylelint-config-recess-order

パッケージの説明

styleint
stylelint本体です

stylelint-config-standard
stylelintのルール集です。
stylelintは設定項目が非常に多く自分で一つ一つ設定するのはとても大変ですが、このパッケージを入れるだけで簡単にルールを統一できます。

stylelint-recess-order
stylelintで自動整形する際にCSSの並びを統一してくれます。
-recess-はTwitter社が公開していた整形ツールRECESSのことです。
言い換えると「RECESSのように並び変えるstylelintのプラグイン」です。

.stylelintrc.jsを作成する

次に設定ファイルを作成します。ファイル形式は色々な選択肢がありJSON,YAML,Javascript形式が使用できます。
コメントアウト可能なYAMLかJavascript形式がよいので今回はJavascript形式で作成します。

touch .stylelintrc.js

vm .stylelintrc.js
module.exports = {
   extends: [
       "stylelint-config-standard",
       "stylelint-recess-order",
   ],
}

これでとりあえずstylelintを実行する準備ができました。

対象のCSSを作成する

CSSファイルを作成します。

mkdir -p src/css

cd src/css

touch style.css

npm-scriptsにタスクを記述する

package.jsonのscriptsにタスクを登録して実行します。

"lint:css": "stylelint src/**/*.css" --fix

※–fixオプションが重要です。これがないと自動整形されません

これでstylelintで検証し自動整形することができました。

PostCSSで入れ子を実現できるプラグイン「postcss-nesting」使用時に起きる問題と解決法

cssのポストプロセッサPostCSSは使用したい機能だけを利用してcssを加工するツールです。非常にたくさんのプラグインが存在しその種類によってはSASSの機能を再現することが可能です。SASSでは非常に使用頻度が高い入れ子表記を実現可能にするプラグインpostcss-nestingを使用時にちょっと気になる問題があったのでその問題と解決策を紹介します。

問題1) Sassの&(アンパサド)のように親要素の名前をclass名に出力することはできない。よってBEMの時によく使う子要素の命名tipsが使用できない。

.button {

    // 本来なら .button__textと出力してほしいがこれは意図したとおりにならない
    &__text {
        color: black;
    }
}

■解決方法

postcss-nestingではなく類似プラグインpostcss-nestedを使う

問題2)出力されたソースのインデントが気持ち悪い

例)

  • 入力元ファイル
.foo {

  .bar {
    font-size: 2rem;
  }

  &__fuz {
    font-size: 2rem;
  }
}
  • 出力ファイル
.foo .bar {
    font-size: 2rem;
  }

  .foo__fuz {
    font-size: 2rem;
  }

■解決策

stylelintを導入して別スクリプトで整形する。

stylelint-config-standardを設定ファイルとしてstylelintコマンドを–fixオプション付きで使用するとインデントが消えます。(stylelint-config-recommendedだとこうはなりません)

他にもstylelint-config-primerというgituhubのcssコーディング規約がありこちらもインデントを消すことができます。

さらにstylelintで順番を入れ替えると良いです。並べ替えにはstylelintのプラグインstylelint-config-recess-orderを使うのがおすすめです。

※recessとはTwitter社が公開していたcssを整形するツール「RECESS」の事を指す
※RECESSのように並べ替えて整形しますよということ
※RECESSは今はアーカイブに変わっている(現役ではない)

Edgeで画像の右上のマークは何?出る条件と影響について

久しぶりにEdgeを画像にマウスカーソルをあてたらに右上に知らないアイコンが出て「おや?」と思ったかたはいないでしょうか?

他の画像に同じことをしてもアイコンが出てこないのもあるし制作者の意図なのか紛らわしいですね。

クリックするとわかりますが正体はEdgeの画像検索機能です。

これはbingの画像検索機能に依存している機能で対象画像に関連コンテンツがあると判断されればボタンが表示されます。

例えば、日本地図が入っているの画像上の「画像検索」ボタンをクリックすると日本地図の画像が関連コンテンツに表示されます。

画像検索って何?

画像の内容をコンピュータが解析し得られる情報を画像から抽出する機能です。

画像検索の仕組みは、

①コンピュータ(人工知能)に膨大な画像を認識させ
②アルゴリズムを使って似たような画像を覚えさせ
③膨大な状況をデータベースに保存しておき
④検索された画像と似たような条件の画像をデータベースから合致するものを提案する

という流れがほぼ同じだと思います。サービス毎で違うのはアルゴリズムの箇所でしょう。検索される回数が増えていくほどコンピュータが状況を蓄積していくので精度が上がっていきます。

たくさんのサービスがある画像検索

画像検索機能はGoogleも提供していてスマートフォンアプリのGoogleレンズは有名です。

  • レンズで読み込んだテキストを抽出
  • レンズで読み込んだ画像にあるものの類似品を検索
  • レンズで読み込んだものの名前を調べることが可能

このような事ができて実際に体験すると最初はとても感動します。
※この機能はGoogleフォトにもスマホ版Googleアプリにも存在します

その他に画像検索サービスといえば…

  • Yahoo
  • Bing
  • TinEye
  • Image Raider
  • Pixsy
  • Piterest

などが有名です。

各サービスによって特徴が違いますがBingの画像検索は検索した画像からのテキスト抽出機能と検索結果の人物でのフィルタリング機能が特徴的です。

Edgeで画像検索ボタンが邪魔なら消せます

Edgeに話はもどりますがこのボタンが邪魔な場合もあります。
そんな時は検索ボタンを非表示にさせることができます。

作り手側からできる

imgタグでsrc属性で画像を呼び出しているHTML構造の時に表示されるようなのでCSSでbackground-imageプロパティで呼び出すとこの機能の対象から外れるようです。(2022年6月現在)

しかし、ブラウザの標準仕様でかつ便利機能なので「標準仕様なので消せません」として後述のユーザー側で非表示にする方法を伝えたほうが賢明ですね。

ユーザー側からできる

Edgeの設定でこの機能を無効にできます。
方法は次のとおりです。

Edgeの画像検索ボタン無効化方法

①Edgeの右上にある「…」のボタンを押し設定ウィンドウを表示します

②メニューの下の方にある「設定」を押します

③設定画面内の左そでにある「外観」を押します
※ブラウザの幅によってはメニューが表示されませんのでその時はブラウザの幅を広げてください

④項目「ショートカットメニュー」にある「画像検索」を押します

⑤「画像のポイント時にビジュアル検索を表示する」という項目がONになっているのでOFFに設定します

これで画像の上にカーソルをのせたとき画像検索ボタンは表示されなくなります。

画像検索ボタンは表示しておいてもあまり影響がないように見えますが関連コンテンツにセンシティブな内容が多く出てくるような事があれば非表示設定にしておいてもよいかもしれません。

特に子供も使用する状況が多いのなら誤って押しかねないですからね。

jsonファイルを利用してデータとテンプレートを分ける – npm + nunjucks + stylus で静的サイト制作を効率的にする(6)

テンプレートエンジンnunjucksの利用環境構築を紹介してきましたがテンプレートエンジンの何が便利かというと次のようなことです。

  1. ヘッダーやフッターなどのページに共通な部分を一か所にまとめることができる
  2. リストのような同じ構造の大量のコードを一か所にまとめることができる

今回は2の詳細を紹介します。

具体的にはjsonファイルでリストデータを保持してテンプレートファイルにループ処理でリストタグを吐き出すようにします

▼今までの構築の流れはこちら

JSONファイルについて

jsonファイルについて簡単な説明です

  • JavaScript Object Notation の略。Notationは「記法」という意味。「JavascriptのObject記法」
  • データ交換を行うためのテキストベースの記述形式。軽量なため様々なプログラミング言語で使用される。
  • 名前のとおりJavascriptの構文の一部なのでJavascriptで扱いやすい
  • キー:値のペアで構成され、値は①オブジェクト②配列③数値④文字列⑤真偽値⑥nullの6種類のみとなる
  • 文字コードはUTF-8が必須

jsonファイルを用意する

まずデータ構造を決めます。

今回はアベンジャーズヒーローをリストでだします

一人分のデータ構造を以下のようにします

{
    name: "アイアンマン",
    actor: "ロバートダウニーJr"
}

nameキーの値がヒーロー名でactorキーの値が演じている俳優名にします。

2人目のヒーローを追加すると次のようになります。

{
    name: "アイアンマン",
    actor: "ロバートダウニーJr"
},
{
    name: "キャプテンアメリカ",
    actor: "クリスエヴァンス"
}

数が少ないうちはこのように下にコピペしていけばよいですがこれが大量になると作業が大変です。

こんな時はGoogleスプレッドシートでデータを管理しcsvファイルをWEBツールでjsonファイルに変換すると楽です。

jsonファイルに変換するcsvファイルを用意する

↑スプレッドシートに登録

Googleスプレッドシートでメニュー内「ファイル>ダウンロード>カンマ区切り形式」で簡単にCSVファイルを生成することができます。

※Excelでも同様のことができますが文字コードがUTF-8ではないのでデフォルトでUTF-8のGoogleスプレッドシートのほうが楽です

必要なデータができたらCSVファイルをダウンロードします。

ダウンロードしたCSVファイルを今度はJSONに変換します。

csvファイルをjsonに変換する

下記サイトでcsvファイルを簡単にjsonに変換できます。

▼CSVJSON
https://csvjson.com/

先ほどダウンロードしたcsvファイルをアップロードして「>Convert」ボタンを押すと右側にJSONコードとして吐き出されます。
これをコピーしてjsonファイル内に貼り付けます

今回はdata.jsonというファイルを新規作成して以下のようにします

{
  avengers: [
    // ここに貼り付け
  ]
}

[注意]コピーしたjsonデータはキーavengersの値として貼り付けます

できたjsonファイルは src/tpl/data.jsonとしてプロジェクトフォルダに保存します

nunjukcsにdata.jsonを読み込むように設定する

package.jsonのscripts項目の一部を変更します

// 変更前
"build:html": "nunjucks **/*.njk -p src/tpl -o dist"

// 変更後
"build:html": "nunjucks **/*.njk src/tpl/data.json -p src/tpl -o dist"

↑このように追記するとnunjucks-cliに
njk拡張子のファイルを対象に、src/tpl/data.jsonファイルを設定ファイルで使用して、src/tplフォルダを基準に、distフォルダにhtmlを生成してね。
ということを伝えることができます。

これでnunjucksで設定ファイルを読み込むことができました。

次にテンプレート側で処理を行います。

njkファイルにデータを表示する

nunjucksのfor文を使用してリスト表示を一か所にまとめます

<ul>
  {% for item in avengers %}
  <li>{item.name}|{item.actor}</li>
  {% endfor %}
</ul>

これでもしHTML部分の変更(例えばliタグにクラスを足したい、liの子要素を追加したい)が発生しても一か所を変更すればよいので管理が楽になります。

StylusでヘルパーCSSを作成する際に便利な関数、mixin(メディアクエリ編)

sassではよくメディアクエリを設定しやすくするためmixinを使用しますがstylusでも同様にメディアクエリ用のmixinを作成すると効率が各段によくなります。今回はメディアクエリ用のmixinをstylusでどう作るか紹介します。

Stylusの環境構築方法はこちらの記事

実際に追加するコード

mq(num)
  breakpoints = {
    sm: 576,
    md: 768,
    lg: 992,
    xl: 1200
  }

  for key, val in breakpoints
    if (num == key)
      num = val

  @media only screen and (min-width unit(num, px))
    {block}
  • breakpointsの値はTwitterBootstrapと同じにしていますがプロジェクト別に設定しても問題ありません。
  • モバイルファーストで設定しています。
  • breakpointsの他にmq(num)のnumに数字を設定すればその値はメディアクエリの切り替えポイントになります。

使い方

実際には引数に数字か文字列を入力します

.hoge
  mq(sm)
    background-color: gold

これでメディアクエリの設定が楽になりました。

webpackにbabelを導入する – npm + nunjucks + stylus で静的サイト制作を効率的にする(5)

webpackを使用してjsファイルを集束(バンドル)することができましたがJavascriptは様々な規格があるので環境によって動かない場合があります。

そうならない為にひと手間加えてより確実に用意したjsコードが実行されるようにします。

今までの流れは下記記事に書いてあります。

Babelというものを使用します。

[Babel] Javascript用のコンパイラです。新しい書き方のjsコードを古い書き方のコードに変換することができます。

Babel公式サイト

webpackでjsファイルをバンドルする際にこのbabelを稼働させて古い書き方のコードに変換するという流れです。

必要なもの

  • webpack
  • babel-loader
  • @babel/core
  • @babel/preset-env
  • babel.config.json
  • webpack.config.jsの更新

▼各アイテムについて
[babel-loader] webpackでbabelを呼び出すために使用します
[@babel/core] coreという言葉からわかるようにbabel本体です
[@babel/preset-env] babelにはたくさんのプラグインがあり、一つずつインストールすると大変なので関連するプラグインを良い感じに使用してくれるbabel用プラグインです
[babel.config.json] babelの設定ファイルです

各ツールのインストールと設定

npmでツールをインストールしていきます

npm i -D webpack babel-loader @babel/core @babel/preset-env

インストールが終わったらwebpack.config.jsを変更します

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/js/index.js',
  output: {
    path: path.resolve(__dirname, './dist/js'),
    filename: 'script.bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
    ]
  },
  target: ['web']
}

↑これは

  1. test: /.m?js$/ ⇒.jsか.mjs(moduleに対応できる新しいjsの拡張子)という拡張子のファイルを対象にして
  2. exclude: /node_modules/ ⇒ node_modulesフォルダは除外して
  3. use以下 ⇒ bable-loaderをオプションにpreset-envプラグインを使用して処理を行って

という設定になります。

webpack.config.jsの設定が終わったらbabel.config.jsonを作成します

touch babel.config.json

babel.config.jsonには以下の設定を行います

{
  "presets": ["@babel/preset-env"]
}

ここまで来たら今回の処理は終了です。
以前に作成していた下記コマンドを実行してbabelで変換されたjsファイルができているか確認してください

npm build:js

IE11のサポート終了にともないこれからは古いjsコードに対応しなくてもよくなりましたがReactを使用するプロジェクトなどはBabelを活用しなければいけないのでwebpackとbabelはまだまだ手放せません。

今までの流れは下記記事に書いてあります。

StylusでヘルパーCSSを作成する際に便利な関数、mixin(margin、padding編)

node.js製のCSSプリプロセッサstylusは変数を使用でき、またmixinという決まった処理を自動的に展開させることができる機能があるのでヘルパースタイルを効率的に作成することができます。

先発のCSSプリプロセッサsassでも同様のことができますがsassの記述をそのまま持ってきても当然動かないのでstylusでの書き方を最近sassから乗り換えた人や stylusを使い始めた人に紹介します。

stylusのコンパイル環境は各自調べるか下記記事をご参考に

用意するファイル

_vars.stylとstyle.stylを用意します。

_vars.stylの頭のアンダースコアを忘れないでください。アンダースコアをつけると「このファイルは内部でしか使用しない(ファイルを生成しない)」という事になります。

style.stylファイルが元となりcssにコンパイルされます。

mixinを追加する

_vars.stylに以下のコードを追加します。

spaces($max = 100, $step = 1, $unit = 'px')
  $props = {
    m: 'margin',
    p: 'padding'
  }

  $spaces = {
    t: 'top',
    r: 'right',
    b: 'bottom',
    l: 'left'
  }

  for $pKey, $pVal in $props
    for $i in 0 .. ($max / $step)
      $num = $i * $step
      $value = $i == 0 ? $num : unit($num, $unit)

      .hp_{$pKey}{$num}
        {$pVal} $value !important

      for $key, $val in $spaces
        .hp_{$pKey}{$key}{$num}
          {$pVal}-{$val} $value !important

上記の処理はこんな流れです。

①$props、$spacesという変数を作成しプロパティ省略名とそのプロパティ名を設定します。(tはtop。後で「mtはmargin-top」だよと伝えるために設定)

②各スペース(top,right,bottom,left)ごとに$maxで設定した値までクラスを生成します。

$stepを設定すると数字が飛び飛びで設定されます。$stepを5に設定するとmt0、mt5、mt10と5ずつ生成されます。

$unitには単位を設定します。昔はpxの一択でしたが今はremも使用することもあるかもしれません。remを使用する場合は$stepは少数点まで設定するとよいと思います。

※変数の頭に$(ドル)をつけていますがこれはstylusでは必須ではありません。なくても良いのですが変数だと一目でわかるように設定しています。

※クラス名ですが個人的にPRECSSというCSS設計が好きなのでヘルパーcssのprefix「hp_」をつけています。これは好みなのでわかりやすいように変更してください。

▼PRECSS公式サイト
https://precss.io/ja/

次にstyle.stylで_vars.stylに書いたmixinを呼び出します。

spaces($max = 100, $step = 5, $unit = 'px')

これでstyle.cssにmarginとpaddingのヘルパースタイルが生成されます。

flexbox使用の要素が折り返さない!?解決への鍵はflex-basisの値だった

CSSに用意されているレイアウト用プロパティdisplay:flexですがいままで未対応だったIE11のサポート終了にともないもっと気軽に使用することができるようになりました。

しかし、設定の仕方で意図しない見た目になることが多々あります。

今回はその中のひとつの問題の解決方法です。

現象)フレックスアイテム内の要素が折り返さない

前提は下記のようになります。

  • 親要素がdisplay: flexで横並びに設定
  • 子要素の一部にflex-basis: auto;が設定されている。そしてdisplay: flex; flex-wrap: wrapを指定する
  • 孫要素のフレックスアイテムが自動改行されない。

問題)子要素にflex-basis:auto;があるとその中のflex-wrapが効かなくなる

プロパティflex-wrapはflexアイテムを勝手に改行してくれる機能です。

解決方法)flex-basis:autoをやめflex: 1 0 0%;のようにショートハンドで記入する

flex: 1 で指定しても大丈夫です。

flex: 1 で設定した場合は以下の処理と同等です

flex: 1 1 0

flex-basis: autoはflex:1の初期値ではないので注意してください。

webpackを使用してjavascriptを集束(バンドル)する – npm + nunjucks + stylus で静的サイト制作を効率的にする(4)

前回までで次のようなことをやってきました。

  • nunjucks でhtml生成
  • stylus でcss生成
  • imagemin で画像圧縮

javascriptはそのままコピーして使用する想定でしたが使用量が増えてしまった時のためにwebpackを使用してバンドルする流れも残しておきます。

今回はjavascriptを対象にしますがTypescriptを使用するケースもありますのでそれは別の記事で残しておきます。

  • [webpack] 複数のjavascriptファイルを適切にまとめてくれるツール。jsファイル以外のファイルもまとめてくれる。
  • [Typescript] javascriptを拡張して作られた言語。

webpackの存在意義の変化

いままではES6未対応のIE11に新しい書き方のjsを読み込ませるために使用していたケースがほとんどでした。

2022年6月15日のIE11サポート終了によりES6がすべての主要ブラウザ対応になりこの処理は不要となります。

あたらしいjavascriptの書き方では今までツールなしでできなかったモジュール(外部jsファイル)の読み込みもできるのでモジュールバンドルという機能も不要となりwebpackの役割は終了したかと思えます。

しかし、ReactやTypescriptなどではまだまだ必要でEdgeに搭載されている(余計な…)IEモード対応案件なんて恐怖なものが出てくる時のためにまだまだwebpackは捨てられないようです。

webpackでjavascriptを集束(バンドル)する方法

必要なパッケージをインストールします

npm i -D webpack-cli

※webpackを扱っている色々な記事ではwebpackとwebpack-cliの両方を入れていますがnpm-scriptsだけでwebpackを呼び出すのでwebpack-cliだけのインストールで十分です。

package.jsonのscript部分を以下のように修正します。

// 変更前
"build:js": "cpx \"src/js/**/*.js\" dist/js/"
"watch:js": "chokidar \"src/**/*.js\" -c \"npm run build:js\""

// 変更後
"build:js": "webpack"
"watch:js": "webpack --watch"

つぎにwebpack.config.jsファイルを作成してwebpackの処理を設定していきます。

touch webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/js/index.js',
  output: {
    path: path.resolve(__dirname, './dist/js'),
    filename: 'script.bundle.js'
  },
  module: {
    rules: [
      {test: /\.js$/},
    ]
  },
  target: ['web']
}

ここまで来たらコマンドを入力してscript.bundle.jsができることを確認します。

今回はここまでで次回はwebpackにbabelを導入してEdgeのIEモード対応(いるのか?)に備えます。