20191222のCSSに関する記事は14件です。

Nuxt.jsでhover/activeのレスポンシブ対応

一般的にWebアプリではクリックできることを示すために要素に :hoberを付けます。
モバイル版のアプリではマウスがないため、長押しをした際に :hoverのような変化を付けるとタップ(クリック)できることが伝わるかと思います。これはTwitterなど多くのアプリに見られる実装です。

この動作を実装したのでおこなったことをまとめます。

hover/activeの仕様

PCの :hover
hoverGif.gif

Mobileの :hover
mobileHoverGif.gif

これではmobileで長押し後、別の場所をタップするまで :hoverで設定したCSSが続いてしまいます。
これは想定している動作ではありません。

PCの :active
activeGif.gif

mobileの :active
mobileActiveGif.gif

mobileはいいのですが、PCではクリックしないと適用されませんでした。

なので、

  • PCでは :hover
  • mobileでは :active

とする必要があります。

デバイスを判別する

nuxt-user-agentというパッケージでユーザーのデバイスを判別し、対応するCSSを適用することにします。

github
https://github.com/fukuiretu/nuxt-user-agent

nuxt-user-agentをgithubのREADMEに従ってNuxtにインストールし、PCとmobileの判別をしていきます。

先ほどの例に導入したものがこちら
pcGif.gif
mobileGif.gif

<template>
  <div class="card-container">
    <div
      class="card"
      :class="{
        'card-pc': $ua.deviceType() === 'pc',
        'card-mob': $ua.deviceType() !== 'pc'
      }"
    >
      Sample
    </div>
  </div>
</template>

<style lang="scss" scoped>
.card-container {
  display: flex;
  justify-content: center;
}

.card {
  width: 80%;
  height: 200px;
  background: white;
  border: 1px solid black;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  &-pc{
    &:hover {
      background: #78c4db;
    }
  }
  &-mob {
    &:active {
      background: #78c4db;
    }
  }
}
</style>

これで

  • PCでは :hover
  • mobileでは :active

を実装することができました。

以下のように画面サイズで判別することも可能ではあります。

@media screen and (min-width: PhoneSize) { 
  &:hover {
    background: #78c4db;
  }
}

ただしiPad Pro等の大型タブレットまで考慮すると難しくなってしまうので、今回はデバイスを取得する実装になりました。

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

よく使う カラムレイアウトのマークアップ

めちゃめちゃよく使うので、今更ながらメモに残しとく?

左右のmarginは、.listItem + .listItemで、
上下のmarginは、2段目から取るようにしています。
左に左に、上に上に、marginをつけます。

こんな感じ↓
名称未設定ファイル (1).png

PCで2カラム、SPで1カラム

名称未設定ファイル (2).png

index.html
<ul class="col2List">
  <li class="col2ListItem"></li>
  <li class="col2ListItem"></li>
  <li class="col2ListItem"></li>
  <li class="col2ListItem"></li>
  <li class="col2ListItem"></li>
</ul>
style.scss
* {
  margin: 0;
  padding: 0;
}
.col2List {
  display: flex;
  flex-wrap: wrap;
  @media (max-width: 640px) {
    display: block;
  }
  .col2ListItem {
    width: 48%; // デザインにより変更
    @media (max-width: 640px) {
      width: 100%;
    }
  }
}
.col2ListItem + .col2ListItem {
  margin-left: 4%; // デザインにより変更
  @media (max-width: 640px) {
    margin-left: 0;
    margin-top: 7vw; // デザインにより変更
  }
}
@media (min-width: 641px) {
  .col2ListItem:nth-child(n + 3) {
    margin-top: 4.8%; // デザインにより変更
  }
  .col2ListItem:nth-child(2n + 1) {
    margin-left: 0;
  }
}

PCで3カラム、SPで1カラム

名称未設定ファイル.png

index.html
<ul class="col3List">
  <li class="col3ListItem"></li>
  <li class="col3ListItem"></li>
  <li class="col3ListItem"></li>
  <li class="col3ListItem"></li>
  <li class="col3ListItem"></li>
</ul>
style.scss
* {
  margin: 0;
  padding: 0;
}
.col3List {
  display: flex;
  flex-wrap: wrap;
  @media (max-width: 640px) {
    display: block;
  }
  .col3ListItem {
    width: 30%; // デザインにより変更
    @media (max-width: 640px) {
      width: 100%;
    }
  }
}
.col3ListItem + .col3ListItem {
  margin-left: 5%; // デザインにより変更
  @media (max-width: 640px) {
    margin-left: 0;
    margin-top: 7vw; // デザインにより変更
  }
}
@media (min-width: 641px) {
  .col3ListItem:nth-child(n + 4) {
    margin-top: 4.8%; // デザインにより変更
  }
  .col3ListItem:nth-child(3n + 1) {
    margin-left: 0;
  }
}

PCで4カラム、SPで1カラム

名称未設定ファイルのコピー.png

index.html
<ul class="col4List">
  <li class="col4ListItem"></li>
  <li class="col4ListItem"></li>
  <li class="col4ListItem"></li>
  <li class="col4ListItem"></li>
  <li class="col4ListItem"></li>
  <li class="col4ListItem"></li>
</ul>
style.scss
* {
  margin: 0;
  padding: 0;
}
.col4List {
  display: flex;
  flex-wrap: wrap;
  @media (max-width: 640px) {
    display: block;
  }
  .col4ListItem {
    width: 23%; // デザインにより変更
    @media (max-width: 640px) {
      width: 100%;
    }
  }
}
.col4ListItem + .col4ListItem {
  margin-left: 2.5%; // デザインにより変更
  @media (max-width: 640px) {
    margin-left: 0;
    margin-top: 7vw; // デザインにより変更
  }
}
@media (min-width: 641px) {
  .col4ListItem:nth-child(n + 5) {
    margin-top: 2.5%; // デザインにより変更
  }
  .col4ListItem:nth-child(4n + 1) {
    margin-left: 0;
  }
}

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

終盤問題ジェネレーター(仮)の開発

概要

私が開発を進めている終盤問題ジェネレーター(仮、以下ジェネレーターと略)の開発に関する記事です。
後述の通り、特にジェネレーターのPoCに焦点を当てています。
リバーシ検討図メーカーの話も入っているかもしれませんが、便宜上ジェネレーターの話として紹介いたします。
ITを本職とされている方々からすると気になる部分などあるかもしれませんが、素人の戯言でございますのでご容赦ください。

開発の目的

リバーシの終盤問題は既に複数の方が提供されています。
そういった問題集は良問が多い印象ですが、問題数に限りがあります。
無限に遊べる終盤問題集があればいいなと思い、開発を始めました。

環境選択

開発するときにまず、どの環境を対象にするかを考えました。
候補として主に下の3つがありました(表は私の知っている限りの話です)。

環境 iOS Android Web
言語 Swift or
Objective-C
Java or
Kotlin
HTML5+CSS
+JavaScript
iOS対応 O X O
Android対応 X O O
PC対応 X X O
バイナリ実行 O O X

これに通信機能を付けると、バックエンドのコードも書く必要があります。
私は「PCでも遊べるようにしたい」「バックエンドでNode.jsを使いたい」といったことを考え、Webで開発することにしました。

PoC

準備段階

ジェネレーターで最も重要なのは生成エンジンの部分です。
本稿では「本当にそういったエンジンが作れるのか?」の検証(PoC)部分を中心に説明いたします。
開発初期は棋譜を出力し、作成された問題をWZebraでチェックしていました。
(参考図)
image.png

その後簡単な盤面表示関数を実装して、こちらでチェックするようにしました。
(X=黒石、O=白石)
image.png

PoC:Gen.1

Gen.1(第一世代、以下同様)として、ランダムに着手するだけのエンジンを作りました。
(ただし全体を通して、ジェネレーター関数はdeterministicとなるようケアしました。)

生成例1
f5f4d3f6g7c4g6f7g3h6b4h7h8f3e7e6h5c5f2c3b2e2d6d7d2g2h2e8f8a4b3g4h4c6d8a2b5c8g5b7c7f1a8c2e1a7a1g8e3d1c1b1a3a5g1h3a6b6b8h1

当然これでは、問題として通用する盤面は生成されません。
(下記解析例参照)
image.png
image.png

ただしこの、ランダムに着手するエンジンが全く使えないわけではありません。
様々試す中で、「ランダムな着手の一部を変更することで、互角に近い局面を生成すること」が可能であることが分かりました。
例えば棋譜例1ならば、52.h1 53.b8とすることでドロー局面が生じます。
image.png

PoC:Gen.2

Gen.1における試行の結果から、以下のような条件でエンジンを動作させることが有効と予想されます。

  1. ランダムな着手を途中で打ち切る
  2. 打ち切った局面から完全解析を実行
  3. 特定の評価値範囲内(例えば、黒+1~+10など)にある局面を抽出する

実際にこの条件で実行すると、以下の課題が見つかりました。

  1. 既に終局している局面が生成される。
  2. 最善進行の途中の局面が生成される。
  3. 不要なノードの探索に計算リソースが消費される

PoC:Gen.3

Gen.2の欠点を解消するため、追加で以下の制約を入れました。

  1. 連続して評価値Xの局面が生じる場合、評価値Xとなる空きマス数最多の局面のみを抽出する(課題1, 2対策)。
  2. 最低空きマス数を設定(課題3対策)

1について、例えば以下の3局面が検出された場合、1枚目の局面のみを抽出し、残りの局面は破棄することを意味します。

image.png
image.png
image.png

以上の対策の結果、以下のような棋譜を生成するエンジンが出来上がりました。

生成例2
c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1h1a7
c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1g7c8
c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7a3h3a7

ただし、生成された局面が「不自然」という課題がありました。

PoC:Gen.4

ジェネレーターをより実戦向きにするため、抽出される局面がより「自然」となるよう改良を実施しました。
解決に当たり、まず以下のような仮説を立てました。

  • 人間から見て「不自然」な局面は、局面の見た目で判断されている。
  • 局面の見た目は石の配置に依存する。
  • 石の配置の「自然さ」を評価する静的評価関数を導入し、より評価値の高い局面を抽出することで、より「自然」な局面のみを生成するエンジンとなる

これを確認するため、まず以下の対策を行いました。

  1. 「自然さ」の評価関数導入
  2. 「自然さ」評価値上位の問題の抽出

評価方法の一例として、「空きマス同士が隣り合っているか?」を紹介いたします。

Evaluator.js
/*e0 and e1 : empty squares of upper/lower half.*/
function LFCountConnectedEmptySquares(e0,e1) {
  var a = e0 << 8 & e0;
  var b = e1 << 8 & e1 | e0 >>> 24 & e1;
  var c = LFCountNumberOfDisks(a, b);
  a = e0 << 7 & (e0 & 0x7f7f7f7f);
  b = e1 << 7 & (e1 & 0x7f7f7f7f) | e0 >>> 25 & e1;
  c += LFCountNumberOfDisks(a, b);
  a = e0 << 9 & (e0 & 0xfefefefe);
  b = e1 << 9 & (e1 & 0xfefefefe) | e0 >>> 23 & 0x000000fe & e1
  c += LFCountNumberOfDisks(a, b);
  a = e0 << 1 & (e0 & 0xfefefefe);
  b = e1 << 1 & (e1 & 0xfefefefe);
  return c + LFCountNumberOfDisks(a, b);
}

これはマスクしたbitboardをビットシフトしてAND演算することで、縦横斜めのいずれかの方向に空きマスがつながっているかを評価するものです。
あるマスから見て隣接マスは8か所ありますが、そのうち4か所と隣接しているかどうかを評価しています。
例えばa1マスから見てa2マスは下方向で隣接していますが、a2マスから見るとa1マスは上方向に隣接しています。
これらを重複してカウントする必要はありませんので、このうち「a1から見たa2の位置関係」のみをカウントしています。
このアルゴリズムは、bitboardでの着手アルゴリズムに着想を得て実装しています。
なおJavaScriptでは64bit整数が利用できないため、bitboardは32bit整数 x 2で表しています。
そのため空きマスビットはe0とe1の2つで表現しています。
この点についてはこちらの記事( https://qiita.com/rimol/items/9ed84a4fd4cbfdb83d71 )を参考にしました。

ある程度評価関数の実装とパラメーター設定ができたところで、一度アンケートを実施しました。

この時、同じ評価関数から得られた2つの局面について同時にアンケートをとりました。
結果、片方は「不自然」が多数、もう片方は「自然」が多数といったアンケート結果になりました。
このアンケート結果から、以下のように考えました。

  • 同じアルゴリズムから「不自然」「自然」両方の局面を生成しうる。
  • 評価関数の改良で「不自然」な局面を排除できるようになるのではないか?

PoC:Gen.5

Gen.4の考察から、色々と評価関数の調整を実施しました。
詳細は割愛しますが、以下のような局面(黒番)をコンスタントに生成するエンジンができました。
image.png

参考動画 : https://youtu.be/kfDp3Uc4LRI

まとめ

Gen.5である程度「自然」な局面を選択的に生成できるようになりましたので、PoCの目的を達しました。
エンジンは32bit整数 x 2をseedとして入力可能ですので、最大で64bit unsigned intの最大値=4294967295パターンの問題を生成可能です。
(必要な時はさらに追加可能。)
これからは、作成したエンジンを使って終盤問題アプリを作っていきたいと考えています。

最後に、オセロ Advent Calendarにお誘い頂いた@sensuikan1973さんに感謝申し上げます。
長らく駄文にお付き合いいただきありがとうございました。

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

JSでブラウザがダークモードかを判定する

はじめに

ブラウザにダークモードが搭載されるようになった!
CSSで、ダークモード時の Media Query が記述できる!
Can I use... Support tables for HTML5, CSS3, etc

→JSでは取得できないの...??探してもあまり見つからないし....

いろいろ試行錯誤した結果、取得する方法を発見(?)したので、紹介しようと思います。

条件

  • CSSで、Media Query "prefers-color-scheme" が記述できる
    2019.12.22現在、最新版Firefox, Chrome, Safari, Operaは使用できます。Edgeは残念ながら...
    Can I use... Support tables for HTML5, CSS3, etc
  • JSで、 getComputedStylegetPropertyValue を使用できる
    モダンブラウザすべてに対応しています。
    (ユーザーがJSを「実行しない」にしていなければ)取得できます。

考え方

  • JSでは現在、「直接の」判定はできない。
  • しかし、CSS変数は取得できる。
  • Media Query で、CSS変数の値を変えることが可能。

...ということは...??

  1. Media Query で CSS変数を定義
  2. JSでCSS変数を取得し、値によって判定が可能

実装

今回記述したコードは、GitHubにあげておりますので、併せてごらんください。
a01sa01to/DarkmodeGetter_js

=====

1. CSS変数を定義

/* ライトモードの時、CSS変数 isDarkmode は存在しない */
html{ ... }

@media (prefers-color-scheme: dark){
  /* ダークモードの時 */
  html{
    --isDarkmode: True;
    ....
  }
}

prefers-color-scheme - CSS: カスケーディングスタイルシート | MDN

変数名や値などは、競合しないように適宜変えても構いません。

=====

2. CSS変数を取得

/* 1. <html> に変数を設定したので、まずは <html> を取得する */
const htmlTag = document.querySelector("html");
// -> <html lang=...> ..... </html>

/* 2. CSSプロパティの取得 */
const comStyle = getComputedStyle(htmlTag);
// -> CSSStyleDeclaration {0: ... }

/* 3. 変数の取得 */
const cssVariable = comStyle.getPropertyValue('--isDarkmode');
// -> "True"(ダークモード)・""(ライトモード)
// ライトモードは、変数を指定していないため、空の文字列が返される

もちろん、わざわざ上記のように書かずとも、1行で記述可能です。

getComputedStyle(document.querySelector("html")).getPropertyValue('--isDarkmode');

1.でCSS変数を変更した場合は、こちらも変更する必要があります。

=====

3. 判定

/* 2 のコードの続き。"cssVariable" が定義されている前提 */
const isDarkmode = !!cssVariable;

// これでも同じ
const isDarkmode = Boolean(cssVariable);

ライトモードでは、cssVariable == "" なので、Falsy です。
そのため、 isDarkmodefalse を返します。

ダークモードでは、 cssVariable == "True"Truthy なので、 true を返します。

Truthy - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
Falsy - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN

=====

以上により、ブラウザがダークモードかを取得することができました!

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

ヘッダーを作るときに考えること

Webサイトを訪問した際、一番初めに目に入るものとはなんでしょうか。

目を惹くメインビジュアル?仰々しいキャッチコピー?
リッチなサイトならばローディング画面?

サイトの構成によってその答えも異なりますが、ほとんどの場合、
そうした注目ポイントに付随するように ヘッダー の存在があるのではないでしょうか。

この文章を読んでいる頃ならまだ、最近新しくなったQiitaロゴを有した黄緑色のヘッダーが画面上部に拝めるのではないかと思います。スマホの方は少しだけ上にスクロール。

サイト共通のヘッダーとは、ある種サイトの名刺のようなものであり、サイトの回遊を助けるナビゲーターであり、常にユーザーに寄り添うような(最近は追従するヘッダーも多いですね)、甘くてクリーミーな特別な存在(パーツ)なのです。

Webサイトを構築するうえで、(この言葉は苦手なのですが) 必須 ともいえるヘッダー。

そんなヘッダーを作るときにHTMLをどう書くかについて考えます。

サンプルケース

サンプルとして特に装り気もない 一般的な ヘッダーをつくります。

一般的ってなんじゃいという話なのですが、

  • タイトル兼トップに戻るリンクゾーン
  • ナビゲーションリストゾーン
  • ハンバーガーメニューボタン

最低限これらさえあればヘッダーとして名乗りを上げることはできるでしょう。

クラスに関してはわかりやすいようBEMライクに書くとして、ひとまずアウトラインを作成します。

header.html
<header class="header">
  <!-- タイトル兼トップに戻るリンクゾーン -->
  <h1 class="header_title">
    <a href="/">サイトタイトル</a>
  </h1>
  <!-- ナビゲーションリストゾーン -->
  <nav class="header_nav">
    <ul class="header_navList">
      <li><a href="#section01">項目01</a></li>
      <li><a href="#section02">項目02</a></li>
      <li><a href="#section03">項目03</a></li>
    </ul>
  </nav>
  <!-- ハンバーガーメニューボタン -->
  <button type="button" class="header_btn"></button>
</header>

う〜んセマンティック。見事にヘッダーの材料が揃っていますね。
(ハンバーガーメニューに関してはコードが長くなるため今回は省略します)

とはいえCSSを当てていない状態ではヘッダーもどきにすらなりきれていません。
早速調理を開始したいところなのですが、このHTMLには欠けているものがあります

<div> がひとつもないのです。

<header>は<div>の代わりではない

これは <header> に限らず、HTML5においてよく言われることですね。
<section><nav> のようにHTMLのアウトラインを生成するわけではない……つまりセクショニングコンテンツではないとされているため、 <header> で囲む意味としては「ここがヘッダーですよ〜」という目印程度のものと考えられます(それが重要ではあるのですが)。

ただ、今のコードではその目印である <header class="header"> しか、色をつけたり引き伸ばしたりする対象がありません。

header.css
.header {
  display: flex;
  align-items: center;
  background: #ccc;
  width: 100%;
  height: 60px;
  /* etc... */
}

こんな感じでほとんどのCSSが一点に集中せざるを得なくなります。
ここから「背景は画面いっぱいに、だけど内部の最大幅を1000pxに収めたい」とかしようとすると、えっこれ無理では?……となって、結局 <div> でcontainerやinnerを書くことになります。
そんなことなら最初からこうしましょう。

header.html
<header class="header">
  <div class="header_container">
    <div class="header_inner">
      <!-- 中身は省略 -->
    </div><!-- /.header_inner -->
  </div><!-- /.header_container -->
</header>
header.css
.header {
/*   display: flex;
  align-items: center;
  background: #ccc;
  width: 100%;
  height: 60px; */
}

.header_container {
  background: #ccc;
  width: 100%;
  height: 60px;
}

.header_inner {
  display: flex;
  align-items: center;
  margin: auto;
  max-width: 1000px;
}

ネストは増えましたが、こんな感じに分割した方が後々の修正もしやすそうですね。
<header> にいたってはCSSが空っぽになってしまいましたが、「<header>は<div>の代わりではない」ので、<header>を修飾するためには別の <div> が必要だった と考えるとよさげです。

そもそも、 <header class="header"> という書き方も、今となってはもにょります。
まるでHTML5すら知らなかった幼き日に書いた <div class="header">置換しただけ のようで……。
(BEMのルール的には仕方なさそうなのですが)

<section>も<div>の代わりにしない方がいい

先ほどの修正によって、 <header> に何もCSSが当たらなくなったように、個人的にはセクショニングコンテンツである <section> にも直接CSSをあらかじめ当てておくのはやめた方がいいのではないかと考えています。

通常の場合は特に問題ないのですが、例えば先ほどのヘッダーがスクロールに合わせて追従する……。
いわゆる固定ヘッダーになった場合、position: fixed; を付けることでヘッダーを浮かせて固定します。

header.css
.header {
  position: fixed;
}

浮いたヘッダーに後に続くメインコンテンツが隠れないよう、ヘッダーの高さ分(今回は 60px)ずらす必要があるのですが、もし固定ヘッダーに各セクションへのアンカーリンク <a href="#~~~"> がある場合、アンカーの到着する位置も同じだけズラす必要があります。

この問題を解消するCSSが以下なのですが、

section.css
section {
  margin-top: -60px;
  padding-top: 60px;
}

もしこれを background と併用してしまうと、padding-top の分だけ伸びた背景が margin-top のネガティブマージン分だけ上にズレることになるため、本来の位置よりもヘッダーの高さ分上にズレて見える <section> が爆誕します(そもそも marginpadding を当てている場合もそれらを上書きしてしまいますね)。

これを防ぐためには先ほどのヘッダーのように、内に身代わりの <div> をかますことが大事です。

section.html
<section id="#section01">
  <div class="section_container">
    <div class="section_inner">
      <!-- 中身は省略 -->
    </div><!-- /.section_inner -->
  </div><!-- /.section_container -->
</section>
section.css
section {
  margin-top: -60px;
  padding-top: 60px;
}

.section_container {
  background: #000000;
  /* ... */
}

他にも考えることは色々とあるのですが、HTMLをシンプルにしすぎるのもほどほどにした方がよさそうです。

おまけ

実ははじめに見ていただいたQiitaのヘッダーのガワ部分も、
<div class="st-HeaderContainer">
とガッツリ <div> だったりします。
(グローバルフッターは <footer> だったので、なにか意図があるのかないのか分かりませんが)

あらためて、タグの定義された意図を再解釈する必要があると感じる年末なのでした。

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

progate html,css道場 2

hello world.の"."を赤くする

文中の一部にCSSを適用させたい場合
タグを使う。

spanは改行されない。

h1,pタグは改行される

<h1>aa<p>a</p></h1>

aa

a

<h1>aa<span>a</span></h1>

aaa

あとは、spanタグにCSS適用して終わり!

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

font-familyについて本気で考えてみた

『CSS Advent Calendar 2019』最終日?。
担当は本日20代最後の日を迎える私です。
18日目(CSSの単位remの正しい使い方)も書いていますのでよろしくおねがいします。

今年はmacOSのアップデートによりヒラギノが動かなくなったり、
来年初頭にはWindows7がサポート終了、Edgeのブラウザエンジン変更など、
エンドユーザーの環境を考えなければならない節目の時です。

そこでいつもコピペで済ましているfont-familyについて1から考え直してみます。
全部読もうとしている人はスクロールバーを見てから考えてください。

結果

コピペユーザーのために先に結果を記載します。
ブログ等に転載する場合はこのページのURLぐらい貼ってください。

@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 100;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 200;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 300;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 400;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Bold");
  font-weight: bold;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Hiragino Sans", "Noto Sans CJK JP", "Original Yu Gothic", "Yu Gothic", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Sans Emoji";
}

Github: RinoTsuka/jp-font-family

確認済み環境

IE11 Edge Chrome Firefox safari アルファベット 日本語
Windows7 - - Segoe UI Original Yu Gothic
Windows7(Noto) - Segoe UI Noto Sans CJK JP
Windows8.1 - Segoe UI Yu Gothic
Windows8.1(Noto) - Segoe UI Noto Sans CJK
Windows10 - Segoe UI Original Yu Gothic
Windows10(Noto) - Segoe UI Noto Sans CJK JP
macOS 10.12 - - San Francisco Hiragino Sans
macOS 10.13 - - San Francisco Hiragino Sans
macOS 10.14 - - San Francisco Hiragino Sans
macOS 10.15 - - San Francisco Hiragino Sans
Ubuntu 18.04以上 - - - Noto Sans CJK JP? Noto Sans CJK JP
iOS 11未満 - - - - HelveticaNeue Hiragino Kaku Gothic ProN
iOS 11以上 - - - - San Francisco Hiragino Sans
Android - - - - Roboto Noto Sans CJK JP

動作確認いただけましたらコメントで教えてもらえると幸いです。

考えたいこと

なんとなく書いてるけど「なんでこのような書き方をするの?」を考えてみます。

対象環境

環境のサポート状況や需要を考えて、対象環境を決めてみます。

ブラウザ

対象ブラウザ

・Internet Explorer
・Edge
・Google Chrome
・Firefox
・safari
・safari(iOS)
・Chrome(And)
利用者数から対象ブラウザは上記とします。
さようならopera。(ブラウザエンジンはGoogle Chromeと同じなので大体Chromeと一緒です)

対象バージョン

基本的には最新から2つ前までのバージョンぐらいで良いかなと考えています。2つ前にもなると利用者が大幅に減るためです。
そんなにfont-familyの仕様は変わらないのでブラウザのバージョンに神経質になる必要はないと思います。
ただしIEは除く。
Windows7がサポート終了になりますが、あと数年はWindows7に対してサポートすることになるでしょう。
Windows7で使える最も古い物はIE8ですが、サポートが切れるWindows7のためにIE10以前をサポートするにはCSS開発コスパが悪すぎるので、対象はIE11にすることにします。

参考:各Windows OSで利用できるIEのバージョンを知る:Tech TIPS - @IT

OS

Windows

こちらはユーザー数ではなく、MicrosoftがサポートしているOSか否かで判断します。
Windows7のサポートが終了になり、Windows 8.1から游ゴシックが搭載されるのですが、莫大なユーザー数を抱えるWindows7を切るわけにはいかないので、1,2年は対象としなければならないでしょう。
なのでWindows7以上を対象とします。

mac

まず私のQiitaの記事のとある1ヶ月のmacユーザーです。(Windowsと比べて異常なmac率です)
ga.png

10.11のOSになるとかなり閲覧者が減ります。
10.12このラインを取りたいと思います。
これは『10.11 El Capitan』がOS X、『10.12 Sierra』がmacOSとなる分岐点でもあります。
macOSになるとHiragino Sansというフォントが登場することになります。
同時にSan Franciscoも登場しています。
これでmacで対象とするOSは全てHiragino Sansが使えることになります。

Linux

Linuxはコマンドラインからしか触らないのでよく知らないのですが、Ubuntu 18.04からNoto CJK(Noto Sans CJK JP)が標準らしいです。
sans-serifこれを記載するだけでNoto Sansが適用されるようです。
ユーザー数がほとんどいないので、OSバージョンではなくNoto Sansを採用することにします。

参考: Ubuntu 18.04 LTSの日本語フォントを変更する!【詳細解説】 | LFI

iOS(iPadOS)

ユーザー数が多く、日本語フォントの種類が少ないためすべて対応します。

Android

Noto Sans CJK JPを搭載の機種を対象とします。

htmlbodyはどちらに記述するべきか?

どちらでも問題ないようです。
font-sizeなどなどbodyに書くと思うので、見やすくするためにbodyに統一して書きたいですね。

CSS - Bootstrapはなぜhtmlとbody両方にfont-familyを記述しているのか?|teratail

どんなときにクォーテーションで囲うのか?

マルチバイトまたは半角スペースが含まれるときにクォーテーションで囲います。
囲う必要がない場合は囲わないほうが数バイトですが、容量の削減が出来ます。
またIEは必要ない場合に囲むと、適用されないものもあります。

// 囲う
body {
  font-family: "游ゴシック", "Hiragino Sans", "??";
}

// 囲う必要がない(囲っても動く)
body {
  font-family: -apple-system, HiraKakuProN-W3, sans-serif;
}

'(シングルクォーテーション)と"(ダブルクォーテーション)どちらを使えばいいのか?

答えはどっちでも良いです。
どちらを使っても同じです。、コーディング規約があるならそちらに従いましょう。
なければどちらか好みの方に決めてしまいましょう。

// これは気持ち悪い
body {
  font-family: "Sample Win", 'Sample Mac', sans-serif;
}

『何か理由があって分けてるのか?』と誤解を招かれるかもしれないので統一しましょう。

絵文字について?

絵文字について考えたことありますか?
私は全く気にしたことがなかったのですが、どうやらちゃんと指定しないと、IEでモノクロの絵文字が表示されるようです。
データベースはmb4で対応しているのにfont-familyは対応しないなんてありえない!
ということで絵文字用のフォントもfont-familyに記載していきます。

参考:絵文字?を含むテキストを表示する @font-face 設定(Unicode 10.0対応版) | ダーシマ・ヱンヂニヤリング

日本語表記とアルファベット表記を併用する必要があるのか?

ないです!
昔々、日本語表記をしないと反映されないブラウザがあったそうな。
safariでは日本語表記を認識しなかったそうですが、現在は認識されているようです。
いつから認識するようになったかは不明。
また、日本語表記とアルファベット表記で違うものを読み込んでいる特殊なフォントもあります。
なので全てアルファベット表記で揃えましょう。

日本語とアルファベットでfontを変える必要があるのか?

body {
  font-family: Arial, Meiryo;
}

などメイリオにもアルファベットが内包されいてるのになぜArialを記載するのでしょうか?
これはMeiryoのアルファベットがArialに比べてキレイではないから、という理由でこのような書き方をされてきました。
日本語はアルファベットに比べて文字がでかい。それに合わせてアルファベットの文字が作成されているので、総じて日本語フォントのアルファベットは純粋なアルファベットフォントと比べ、見た目で劣ります。
なので基本的にはこのような書き方をすることが必要です。
しかし、後述しますが例外フォントが存在するのです。

カーニングについて

カーニング(font-feature-settings)ですが、できるフォントとできないフォントが存在します。
カーニングできるフォントのみでfont-familyを構成することは出来ないので、考えないことにします。
font-feature-settingsを設定する場合、カーニング出来たらラッキー!ぐらいに考えてください。

候補に上がるフォント

気になりごとが調べ終わりました。
まずは一般的に利用されてきたフォント、新たに候補に加えるに値するフォントを列挙します。
いずれかの環境に入っていて、無償でダウンロードできるフォントを△とします。

Windows macOS Linux iOS Android
アルファベット
Segoe UI
Verdana
Arial
-apple-system
BlinkMacSystemFont
Helvetica Neue
Helvetica
Roboto ○ 
日本語
Yu Gothic
YuGothic
Meiryo
BIZ UDPGothic
UD Digi Kyokasho
MS PGothic
Hiragino Sans
Hiragino Kaku Gothic ProN
Osaka
Noto Sans CJK JP
Droid Sans
絵文字
Segoe UI Emoji
Segoe UI Symbol
Apple Color Emoji
Noto Sans Emoji
共通
sans-serif

こんな漢字でしょうか?
いくつか見慣れないものがあるかもしれませんが、後述します。

うんちく?

ちょっと余談。

游ゴシックのフォント名

Windowとmacで微妙に違う。
※今回これが後でこれが重要なポイントになる。

WindowはYu Gothicで日本語表記は游ゴシック
macはYuGothicで日本語表記は游ゴシック体

-apple-systemとBlinkMacSystemFont

mac用のフォントだが、フォント名とは全然違うSan Franciscoというフォントが適用される。
参考:San Francisco フォントを探る - Qiita

BlinkMacSystemFontはレンダリングエンジンBlink搭載ブラウザ(Chrome, Opera)で適用される。
-apple-systemその他ブラウザで適用される。
GoogleとAppleの(ブラウザ)仲の悪さからこうなったのだろうか?

Hiragino Kaku Gothic ProNの『N』ってなによ?

hiragino.png

Hiragino Kaku Gothic ProNHiragino Kaku Gothic Proを比較して『N』はいくつかの漢字が旧字体になります。
Hiragino SansProN寄りです。

参考: ProとProN、StdとStdNの違い - フォント専門サイト fontnavi

Window10の新フォント

Window10はアップデートでいくつかのモリサワフォントが追加されています

UDデジタル教科書体(UD Digi Kyokasho NK-R)
その名の通り教科書向けに作成されたフォントです。
UDとはユニバーサルデザインのことで、見た目よりも読みやすさを優先したフォントにつけられることが多いです。

BIZ UDゴシック(BIZ UDPGothic, BIZ UDGothic)

Microsoft Officeに特化したフォントだそうです。
Officeに特化というだけあってWindows10以外でも利用できるようにMORISAWA BIZ+に登録するとダウンロードできるようになっています。BIZだけど個人でもOK!
ゴシック体だけではなくBIZ UD明朝という明朝体も同時に採用されています。

見た目は游ゴシックよりもメイリオより。
Windowsの日本語フォントの中ではダントツに可読性が高いです。
ただし仮想ボディーギリギリまで利用しているので、他のフォントと比較するとline-heightが小さく見えます。

フォントラインナップ | MORISAWA BIZ+ | フォント製品 | 製品/ソリューション | 株式会社モリサワ
ダウンロード:「MORISAWA BIZ+ 無償版」(旧:MORISAWA BIZ+「BIZ UD ゴシック/明朝 スタンダード版」)書体改訂のご案内[2018.10.24] – BIZ+

問題点のあるフォント

Yu Gothic

・IEで下部に余白ができるバグがある。
游ゴシックが一般的に使われているので今回は無視することにします。
気になるのであれば、IE11をハックなどでメイリオにすると良いです。
・Chromeでfont-weight: 400;のときかすれて見れる不具合がある。

Segoe UI

U+2546のグリフが、U+2545と同じになっているバグがある。
Segoe - Wikipedia

U+2546を利用することは無いと思うので見なかったことにしましょう。
あなたの環境で正しく表示されているか分かりませんがこんな文字です。 →

-apple-system, BlinkMacSystemFont, Hiragino Sans

ウエイトの種類が多いので、ウエイトの少ない日本語フォントと組み合わせたとき、日本語とアルファベットでウエイトに差が出てしまう。
Hiragino Sansと組み合わせることで回避出来ます。

Hiragino Kaku Gothic ProN

macOS CatalinaでHiragino Kaku Gothic ProNが適用されない。

よく調べていないので下記サイトを御覧ください。
Mac Catalina WEBでのヒラギノフォント表示問題について考えたメモ - かもメモ

BIZ UDPGothic

バグでは無いと思うが、英数字がやたらとデカイ。
アルファベットフォントが適用されていれば上記は関係なくなる。

font-familyを作る

ようやくfont-familyを書きます。

Original Yu Gothic

まず、Google Chromeの游ゴシックが細い問題に対処します。
詳細はfont-familyにChromeでも読みやすい游ゴシックを指定する方法 - Qiita

@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 100;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 200;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 300;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 400;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Bold");
  font-weight: bold;
}

body {
  font-family: "Original Yu Gothic";
}

(以降@font-faceが行を占領するので省略します)

すべて並べる

アルファベット、日本語、共通、絵文字の順で、更にいい感じのフォント順に並べていきます。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Helvetica Neue",
    Helvetica,
    "Segoe UI",
    Verdana,
    Arial,
    Roboto,
    "Hiragino Sans",
    "Hiragino Kaku Gothic ProN",
    YuGothic,
    Osaka,
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

こんな感じでしょうか。
ここから上から順に見ていきます。
問題がある場合を記載します。

Helvetica Neue, Helvetica

対象環境を決めています。macOSでは全て-apple-systemが搭載されているのでHelvetica Neue, Helveticaは不要なので削除します。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Verdana,
    Arial,
    Roboto,
    "Hiragino Sans",
    "Hiragino Kaku Gothic ProN",
    YuGothic,
    Osaka,
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

Verdana, Arial

対象のWindowsにはSegoe UIが搭載されているので不要です。
ArialはiOSでも採用されていますが、iOS11以前の環境でも-apple-systemが利用できる(San Franciscoではない)ためこちらも不要です。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Hiragino Kaku Gothic ProN",
    YuGothic,
    Osaka,
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

これでアルファベットが-apple-system, BlinkMacSystemFont, Segoe UI, Robotoの4つに確定しました。

Hiragino Kaku Gothic ProN

古いiOSで必要ですがmacには不要です。
iOSではHiragino Kaku Gothic ProNが無くなればsans-serifが適用され結果的にHiragino Kaku Gothic ProNが適用されます。
なので削除します。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    YuGothic,
    Osaka,
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

YuGothic

mac用の游ゴシック。
Hiragino Sansがあるので不要です。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    Osaka,
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

Osaka

もうこの時代に記載する必要は無いですね。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "BIZ UDPGothic",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

BIZ UDPGothic

Windowsの新しいフォントの1つですね。
個人的にすごく読みやすいのですが、いかんせん文字がデカイ。
行間をBIZ UDPGothicに合わせると他のフォントの行間が想定より大きくなり、
他のフォントに合わせるとBIZ UDPGothicがギチギチになってしまう。
デザインの難易度が上がってしまうので、残念ながら外します。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "UD Digi Kyokasho",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

UD Digi Kyokasho

Windowsの新しいフォントのもう1つ。
『教科書』をうたうだけあり、ハネや強弱などしっかりしていて読み物には良さそうですが、小さい文字では潰れがちで向いてない感じがしました。
フォントとしては好きですがWebに向いていないのでこれは削除します。
あくまで一般的で無いだけで、電子書籍等のサイトでは採用してみるのも面白いかもしれません。

UDデジタル教科書体提供開始 | 株式会社モリサワ

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

Yu Gothic

最初にOriginal Yu Gothicを定義しているので不要です。
有ってもいいです。

以前ブラウザに翻弄されて、怖い経験があるのでフォールバックとして残します。
悪戦苦闘のあと → 2020年まで使えるfont-familyおすすめゴシック体 - Qiita

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "Original Yu Gothic",
    "Yu Gothic",
    Meiryo,
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

Meiryo

長年親しんだフォントですが、もはや不要。
対象のWindowsでは sans-serif = Meiryo です。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "Original Yu Gothic",
    "Yu Gothic",
    "MS PGothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

MS PGothic

もはや言うこともないぐらい不要。
今のデフォルトはメイリオなので適用されてしまったら劣化します。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "Original Yu Gothic",
    "Yu Gothic",
    "Droid Sans",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

Droid Sans

Droid Sans = sans-serifなので、こいつを消せば終わりです。

body {
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Hiragino Sans",
    "Noto Sans CJK JP",
    "Original Yu Gothic",
    "Yu Gothic",
    sans-serif,
    "Apple Color Emoji",
    "Segoe UI Emoji",
    "Segoe UI Symbol",
    "Noto Sans Emoji",
  ;
}

完成

これで完成です。
省略していた@font-faceを表示して、最後に整形してあげます。

@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 100;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 200;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 300;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Medium");
  font-weight: 400;
}
@font-face {
  font-family: "Original Yu Gothic";
  src: local("Yu Gothic Bold");
  font-weight: bold;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Hiragino Sans", "Noto Sans CJK JP", "Original Yu Gothic", "Yu Gothic", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Sans Emoji";
}

このfont-familyのメリットはmacでfont-weightが100〜900まですべて使えるという事です。
なのでこれからはfont-weightnormal, boldで記述していた人は数値で入力する癖をつけないといけませんね。

教えて

Bootstrapを参考にしたのですが、Segoe UI Emoji, Segoe UI Symbolと2種類記載する理由が分かりませでした。
ご存じの方いましたらご教授ください。

最後に

2020年まで使えるfont-familyおすすめゴシック体 - Qiitaでは多数の方にご迷惑をおかけしました。(私のせいでは無いけれど)
慣れ親しんだフォントが記載されなくなって、なんだか不思議な感じです。

斜め読みした方も、全部読んでくれた方もお疲れさまでした。
1ヶ月以上前から書き始めて、何度も何度も修正したので変なところがあるかもしれません。
見つけたらご指摘ください。

絵文字とスマホはもうちょっと改良の余地があるかもしれない。

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

progate html,css道場 1

HTML&CSS 道場 初級編で詰まったところ

liリストを横に広げる

改善前コード

index.html
<header>
<div class= "header">
  <div class="logo">Progate</div>
    <div class="header-menu">
      <ul>
        <li>プログラミングとは</li>
        <li>学べるレッスン</li>
        <li>お問い合わせ</li>
      </ul>
    </div>
  </div>
</header>
stylesheet.css
header {
  height: 90px;
  width: 100%;
  background-color: #26d0c9;
}

header .header-logo {
  font-size: 36px;
  padding: 20px 40px;
  color: #fff;
  float: left;
}

header .header-menu {
  padding: 33px 20px;
  color: #fff;
  float: left; 
}

メニューリストを縦から横へ改善する

<div class="header-menu">
header .header-menu {
  padding: 33px 20px;
  color: #fff;
  float: left; 
}

メニューに指定したクラスに行うのではなく
liタグに対して 変更をかける

header li {
  padding: 33px 20px;
  color: #fff;
  float: left; 
}

なぜ?
floatはpaddingを無効化する?
とか言ってたかも。

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

CSSの単位remの正しい使い方

CSS Advent Calendar 201918日目に空きがあったので埋めます。

QiitaやGoogleでremと検索すると、間違った使い方をしている記事がたくさん出てきます。

remはroot emの略!

って分かってるならRootを潰すな!
rootはユーザー設定により変動するかもしれないものです。
ユーザビリティを考えるなら、きちんとユーザーの設定に対応出来るようにしましょう。

よく見る間違った使い方

html {
  font-size: 10px;
  // または
  font-size: 62.5%;
}

p {
  font-size: 1.5rem;
}

間違った使い方の言い分

モダンブラウザの初期値は16pxです。
だからrootを62.5%10px)にすれば1rem = 10pxで分かりやすいです。
15px1.5remと書きましょう!

[疑問] 全部pxじゃだめなの?

1rem = 10pxより全部pxで書くほう分かりやすい。
15pxと書いたほうが楽だし。

なぜこんな変な書き方が流行ったのでしょうか?

IE9以前(だったかな)はfont-sizepxで指定するとIEの機能「文字拡大」が機能しなくなるという不具合があったため、remを使って対処する」という使い方をしていました。
IE9が出た頃はCSS3が利用されて間もなく、SASSも今ほど流行ってなく、「計算が大変だから1rem = 10pxとして計算をしやすくしましょう。」という広まり方でした。
もうIE9以下を対応することはほとんど無いはずです。
現在では過去に考えられたものを、みんなコピペして紹介して、紹介されているものを見た人が鵜呑みにしているのでしょう。

なんでブラウザのfont-sizeが16pxだと思っているの?

過去には16pxでないものもありました。
また、モダンブラウザはデフォルトfont-sizeを簡単に変更できるようになっています。

root(html)に指定すると何が問題か

%での問題

html {
  font-size: 62.5%;
}

p {
  font-size: 1.5rem;
}

ユーザーがブラウザのfont-size20pxに変更したとします。
この場合にブラウザに表示されるpfont-size18.75pxです。
なぜこんな数字になるのか?20px * 62.5% * 1.5rem18.75pxとなるわけです。

「良いんじゃん!」と思った方、本来p20px * 1.5rem30pxとなるべきです。
ユーザー設定20pxなんて極端な数値で紹介していますが、17px15pxなどで設定している方はザラに居るはずです。
そうなったときに値の変動が小さい問題が発生します。。

pxでの問題

html {
  font-size: 10px;
}

p {
  font-size: 1.5rem;
}

ユーザーがブラウザのfont-size20pxに変更したとします。
この場合にブラウザに表示されるpfont-size15pxです。
ユーザーの設定を無視する最低な書き方になります。
今はユーザーファーストな時代です。
ユーザーの設定にも負けない、デザインにpx単位で忠実なものが美徳な時代もありましたが...

解決策

正しい書き方は以下

p {
  font-size: 0.9375rem;
}

以上です。
正しい書き方はhtmlfont-sizeを指定してはいけません。

分かりにくい問題

0.9375remが瞬時に15pxだと分かる人がどれだけいるでしょうか?
この場合はSassを使いましょう。

@mixin font-size($size, $base: 16) {
  font-size: $size / $base + rem;
}

p {
  @include font-size(15);
}

参考:font-size指定にremを使うmixin - Qiita

IE8以前を対応する予定がないならpxと併用して表記する必要はありません。
remを使うのはfont-sizeだけではありません、marginpaddingなどなどremで指定しなければいけませんね。mixinを作りまくってください。

app.css
p {
  font-size: 0.9375rem;
  margin-top: 10px;
  margin-bottom: 10px;
}

こんな書き方をするとユーザー設定が影響して、文字サイズだけ変更できたのに余白が変更できないのでチグハグなことになっちゃいます。ちゃんと適切にremで指定しましょう。
borderなどは、remで指定すると1px以下になってしまい、見えなくなってしまうのでpxで指定するような例外的なプロパティもあるので注意してください。

終わり

レムりんよりラムりんがスキです。

CSS Advent Calendar 2019最終日も私です。よろしくおねがいします。

← 17日『CSS設計で気をつけること
→ 19日『CSS設計で気をつけること

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

可愛いしろくまの404ページを作ってみた

WordPressの自作テーマを作成中、404ページをちょっと変わったデザインにしてみようと思い、404の「0」の部分をしろくまに変えたデザインを作ってみました。

404ページに行くのが楽しくなる!...かも?

実際に作った、しろくまくん入りの404ページ

こちらが実際にWordPressテーマ作成中に作った、しろくまくん入りの404ページになります。
ページが見つからなかった。という悲しさを表現する為に泣かせています( ;∀;)

ちなみに雪の結晶以外は全て、HTMLとCSSのみで作りました!
9a0f6d606ffec1e45a87a4f929c807ae.gif

書いたコード

※スマホで見るとぐしゃぐしゃになってしまいます(`;ω;´)

全体のコード

See the Pen 404Shirokuma by yuma11 (@yuma11) on CodePen.

しろくまの部分

See the Pen Shirokuma by yuma11 (@yuma11) on CodePen.

コードの解説

shirokuma.scss
.kuma { // しろくまの背景
  position: relative;
  margin: 0 auto;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: #3c3c3b;
  &__ear { // 耳
    position: absolute;
    top: 50px;
    width: 60px;
    height: 60px;
    border-radius: 80px 100px 0 100px / 100px 130px 0 100px;
    background: #fff;
    &--left { // 左耳
      left: 60px;
      &:after { // 左耳の穴
        position: absolute;
        top: 12px;
        left: 12px;
        width: 40px;
        height: 40px;
        border-radius: 80px 100px 0 100px / 100px 130px 0 100px;
        background: #000;
        content: '';
      }
    }
    &--right { // 右耳
      right: 60px;
      transform: scale(-1, 1);
      &:after { // 右耳の穴
        position: absolute;
        top: 12px;
        right: 8px;
        width: 40px;
        height: 40px;
        border-radius: 80px 100px 0 100px / 100px 130px 0 100px;
        background: #000;
        content: '';
      }
    }
  }
  &__face { // 顔
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 160px;
    height: 250px;
    border-radius: 80px 80px 0 0;
    background: #fff;
    transform: translateX(-50%);
    &:before { // 顔の左下部分(斜めになっている場所)
      position: absolute;
      bottom: 20px;
      left: -5px;
      width: 20px;
      height: 50px;
      background: white;
      content: '';
      transform: skewX(-20deg);
    }
    &:after { // 顔の右下部分(斜めになっている場所)
      position: absolute;
      right: -5px;
      bottom: 20px;
      width: 20px;
      height: 50px;
      background: white;
      content: '';
      transform: skewX(20deg);
    }
  }
  &__eye { // 目
    position: absolute;
    top: 130px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #000;
    transform-origin: 100px 200px;
    animation: Cry 3s infinite;
    &--left { // 左目
      left: 120px;
      &:after { // 左目の中身(白い部分)
        position: absolute;
        top: 50%;
        left: 50%;
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: #fff;
        content: '';
        transform: translateX(-50%);
      }
    }
    &--right { // 右目
      right: 120px;
      &:after { // 右目の中身(白い部分)
        position: absolute;
        top: 50%;
        left: 50%;
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: #fff;
        content: '';
        transform: translateX(-50%);
      }
    }
  }
  &__tears { // 涙
    position: absolute;
    top: 145px;
    right: 125px;
    width: 8px;
    height: 15px;
    border-radius: 24px 24px 24px 24px / 63px 63px 24px 24px;
    background: skyblue;
    opacity: 0;
    animation: Tears 3s infinite;
  }
  &__nose { // 鼻
    position: absolute;
    top: 150px;
    left: 50%;
    width: 30px;
    height: 20px;
    border-radius: 40% 40% 55% 55%;
    background: #000;
    transform: translateX(-50%);
    &--bottom { // 鼻の下(縦に伸びている線)
      position: absolute;
      top: 150px;
      left: 50%;
      width: 3px;
      height: 30px;
      background: #000;
      transform: translateX(-50%);
    }
  }
  &__mouth { // 口
    position: absolute;
    top: 174px;
    width: 20px;
    height: 20px;
    border-width: 0 3px 3px 0;
    border-style: solid;
    border-color: #000;
    border-radius: 0 0 20px 0 / 0 0 20px 0;
    &--left { // 口の左側
      left: 135px;
      transform: rotate(25deg);
    }
    &--right { // 口の右側
      right: 135px;
      transform: rotate(65deg);
    }
  }
}

@keyframes Cry { // まばたきをするアニメーション
  0% {
    height: 20px;
    transform: translateY(0);
  }
  25% {
    height: 0;
    transform: translateY(15px);
  }
  50% {
    height: 20px;
    transform: translateY(0);
  }
  100% {
    height: 20px;
    transform: translateY(0);
  }
}

@keyframes Tears { // 涙が流れるアニメーション
  0% {
    opacity: 0;
    transform: translateY(0);
  }
  25% {
    opacity: 1;
  }
  50% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 0;
    transform: translateY(0);
  }
}

作ってみて感じたこと

CSSで何か作るのって凄く楽しい...!!
書いたコードがすぐに反映されていくから楽しくて仕方なかったです(´∇`)

まだまだ技術的に足りない部分や、知らない部分が多いので今後もスキルを高めていきたいと思います。

ちなみにしろくまくんを作っている中で、border-radiusの値を8つ指定して使うことが多かったのですが、そんな時にかなり便利なサイトを見つけました↓
FANCY-BORDER-RADIUS
こちらのサイトは直感的に形を作るだけで、その形のborder-radiusの値を出してくれる便利なサイトです。

最後までご覧いただきありがとうございました!

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

かっこいい横スクロールを実装する

ちょっと個人的なメモ程度なので適当です。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>横スクロール</title>
    <style>
        html,
        body {
            margin: 0;
            width: 100%;
            height: 100%;
        }

        .main {
            width: 100%;
            height: 200px;
            overflow-x: scroll;
            display: flex;
        }

        .main::-webkit-scrollbar {
            display: none;
        }

        .card {
            width: 200px;
            height: 170px;
            margin-top: 5px;
            margin-right: 5px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
            border-radius: 8px;
            flex: 0 0 auto;
            margin-left: 10px;
            background-color: #DADCE0;
            flex-shrink: 0;
        }
    </style>
</head>

<body>
    <div class="main">
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
    </div>
</body>

</html>

PCでは使いにくいです。

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

ダークテーマとかに切り替える。

皆さんこんにちはルサカです。最近ダークテーマ流行してますよね!
今回は、ユーザーのテーマを取得したり、ユーザーがテーマを変更できるといったものを作って行きたいと思います。

まぁ作っていこう!

@media (prefers-color-scheme: light) {
  body {
    background-color: white;
    color: black;
  }
}

@media (prefers-color-scheme: dark) {
  body {
    background-color: black;
    color: white;
  }
}

っていう方法でもダークテーマとかの切り替えはできますが、
テーマを変更する処理が結構めんどくさいので、今回は、以下のコードのようにbodyタグにtheme属性を作ってテーマの切り替えを容易にします。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ダークテーマ</title>
    <link rel="stylesheet" href="style.css">
</head>
<body theme="dark">

</body>
</html>

ちなみにCSSはこのように属性ごとにCSS変数を設定しています。
CSS変数についてあまりわからないという方は
CSS カスタムプロパティ (変数) の使用(MDN)を見ると理解が深まると思います。

:root {
    --s-1: 0 2px 5px rgba(0, 0, 0, 0.26);
    --s-2: 0 2px 10px rgba(0, 0, 0, .2);
}

body[theme="dark"] {
    --m-bg: #121212;
    --d-color: #fff;
    --s-color: #9F9F9F;
    --s-bg: #242424;
    --b-1: 1px #242424 solid;
    --a-color: #EF5455;
}

body[theme="light"] {
    --m-bg: #FFF;
    --d-color: #202124;
    --s-color: #5F6368;
    --b-1: 1px solid #dadce0;
    --a-color: #EF5455;
}
@keyframes s-1 {
    0% {
        box-shadow: 0 0.001px 0.001px rgba(0, 0, 0, 0.26);
    }
    100% {
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
    }
}

body{
    background: var(--m-bg);
    color: var(--d-color);
}

切り替え系を作っていこう!

ここからが本番ですね!
まずHTMLにこのようなボタンを追加してください。

<button id="themechange">テーマの変更</button>

ちなみに私の場合は以下のようにボタンを装飾しました。

#themechange{
    border: var(--b-1);
    background: var(--m-bg);
    color: var(--a-color);
    font-size: 18px;
    font-weight: bold;
    padding: 10px 15px;
    border-radius: 4px;
    transition: all 1s;
}

#themechange:hover{
    border-color: var(--a-color);
    background: var(--a-color);
    color: #fff;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
    animation: s-1 1s ease 0s 1 alternate none running;
}
#themechange:focus{
    outline: none;
}

切り替えの処理はJavaScriptで書きます。

document.getElementById("themechange").addEventListener("click",function(){
    var theme = document.body.getAttribute("theme")
    if (theme === "dark") {
        document.body.setAttribute("theme","light")
    } else {
        document.body.setAttribute("theme","dark")
    }
})

次に、OSのテーマを取得して、テーマの初期値を設定しましょう。
コードは以下のようになります。

if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    document.body.setAttribute("theme","dark")
} else {
    document.body.setAttribute("theme","light")
}

これで基本的なテーマ切り替えが完了しました。
他にも、ユーザーがテーマを変更したらその設定をlocalstorageに保存するといったことができると思います。

デモ!

See the Pen jOEmWEW by anyfre (@anyfre) on CodePen.

まとめ

結構簡単にできました。
Twitterフォローしてください!

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

初めてのtailwindcss (Vue.js + PurgeCSS)

この記事は

CSS Advent Calendar 2019 21日目の記事です。
気になってたtailwindcssを、Vue.jsでやってみましたという記事です。
リポジトリはこちら→ https://github.com/hisako135/tailwindcss_vue_demo
スクリーンショット 2019-12-22 3.10.21.png

やったことは以下のような感じです。

tailwindcssってなんぞ

"Bootstrapをゴリゴリいじってカスタマイズしても良いのだが、そこに時間かけるんならCSSフレームワーク使う利点なくない...?:thinking: " などと思ったことがある人はいませんか...?
グリッドシステムとForm周りさえあればよくて、他の必要なコンポーネントは自分で作った方が楽だよな、とかゴニョゴニョ...(小声)

そこでtailwindcssです!

Most CSS frameworks do too much.
(ほとんどのCSSフレームワークは多くのことをやり過ぎている)
https://tailwindcss.com/#what-is-tailwind

"あらゆる種類のコンポーネントが用意されているCSSフレームワークって初期段階に素早く作るのには確かにとっても便利。でもカスタマイズしようとするとしんどいよね。事前に設計されたコンポーネントの代わりに、低レベルなUtilityクラスを提供することによって、HTMLを離れることなくデザインをカスタマイズできるよ。"
というのがtailwindcssです。

ちなみにCSSでのUtilityクラスとは、.font-small {font-size: 10px;}.text-left {text-align: left;} のように、単一のプロパティを定義した汎用的なクラスを指します。Helperクラスとも呼ばれたり。
FLOCSSではUtilityレイヤーに、FLOCSSのベースとなっているMCSSではCosmeticsレイヤーあたりに記載されるやつです。

tailwindcssのUtility-firstの考え方についてはこちらの翻訳記事に詳細書いてありますので是非!
:book: CSS Utility Classes and "Separation of Concerns" 翻訳

セットアップ手順

何はともあれVue.jsでのtailwindcssのセットアップをやっていきましょう。
まずはvue-cliでVue.jsプロジェクトを作成します。

以降、tailwindcss/setup-examples を参考に進めます。

  • tailwindcssをインストール
npm install tailwindcss
  • postcss.config.js ファイルを作成しプラグインとして設定
postcss.config.js
const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer');

module.exports = {
  plugins: [
    tailwindcss,
    autoprefixer,
  ]
}
  • src/assets/tailwind.css というtailwindのスタイル用のCSSファイルを作成します
src/assets/tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;
  • main.jstailwind.css をimportします
src/main.js
import Vue from 'vue'
import App from './App.vue'
import '@/assets/tailwind.css' //これ

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

セットアップは以上です! :tada:

今回はNavigationやCardの例を利用してサクッと画面を作っています。
あんまりtailwindcssで作り込まれてると <transition>コンポーネント使いづらいな...と、うっすら思いましたとさ(結果、使ってない)。

src/components/Header.vue
<template>
  <nav class="flex items-center justify-between flex-wrap bg-teal-500 p-6">
    <div class="flex items-center flex-shrink-0 text-white mr-6">
      <svg class="fill-current h-8 w-8 mr-2" width="54" height="54" viewBox="0 0 54 54" xmlns="http://www.w3.org/2000/svg"><path d="M13.5 22.1c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05zM0 38.3c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05z"/></svg>
      <span class="font-semibold text-xl tracking-tight">Tailwind CSS</span>
    </div>
    <div @click='hideMenu=!hideMenu' class="block lg:hidden">
      <button class="flex items-center px-3 py-2 border rounded text-teal-200 border-teal-400 hover:text-white hover:border-white">
        <svg class="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
      </button>
    </div>
    <div :class='{"hidden md:hidden sm:hidden":hideMenu}' class="w-full block flex-grow lg:flex lg:items-center lg:w-auto">
      <div class="text-sm lg:flex-grow">
        <a href="#responsive-header" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
          Docs
        </a>
        <a href="#responsive-header" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
          Examples
        </a>
        <a href="#responsive-header" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white">
          Blog
        </a>
      </div>
      <div>
        <a href="#" class="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0">Download</a>
      </div>
    </div>
  </nav>
</template>

<script>
export default {
  data() {
    return {
      hideMenu: true
    }
  }
}
</script>

ざっくり紹介tailwindcss

さて、tailwindcssの特徴を極一部ですがご紹介します!
めちゃくちゃ詳しく書いて下さっている記事はこちらですので是非!
:book: TailwindCSS入門 ~ Utility First + デザインシステムの構築 ~i

:(コロン) でブレークポイントや擬似クラスの指定ができる

lg:inline-block hover:text-white でブレークポイントや擬似クラスへの指定をしています。1つのスタイルを使い回せるの便利だな〜。

src/components/Header.vue
<a href="#responsive-header" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white">Blog</a>

@apply

組み合わせて自由に見た目を作れるのが利点とはいえ、何度も同じクラスを並べるのは苦痛ですよね。@apply で、utilityの組み合わせをカスタムコンポーネントのクラスとしてまとめることができます。

src/assets/tailwind.css
@tailwind base;
@tailwind components;
/* Extracting Components */
.btn-teal {
  @apply bg-teal-500 text-white py-2 px-4 rounded w-full;
}
.btn-teal:hover {
  @apply bg-teal-700 transition-colors transition-250 transition-linear;
}
@tailwind utilities;

カスタムコンポーネントのクラスは、utilitiesの前に読み込まないとダメだそうです。

カスタマイズが簡単

tailwindcssで定義されているスタイルは、 tailwind.config.js でカスタマイズできます。

npx tailwind init //tailwind.config.jsファイルを作成するコマンド
tailwind.config.js
module.exports = {
  theme: {
    extend: {}
  },
  variants: {},
  plugins: []
}

作成された tailwind.config.js にカスタマイズしたいプロパティや追加したいプロパティを記載していきます。
tailwindcssでは現状 transition のようなアニメーションに関するプロパティが定義されていません。
そういうものの追加にも便利そうですね。拡張が簡単なのは嬉しい :relieved:
(今回はtransitionのutilityクラスを定義するのにtailwindcss-transitionsを使用しました。)

PurgeCSSで使ってないCSSを削除

さて、なんだかスマートに感じるtailwindcssですが、ファイル容量は実は結構重いです。
スクリーンショット 2019-12-22 2.08.01.png

PurgeCSSで、使ってないCSSを削除していきましょう。

  • PurgeCSSをインストール
npm install @fullhuman/postcss-purgecss --save-dev
postcss.config.js
const autoprefixer = require('autoprefixer');
const tailwindcss = require('tailwindcss');
const purgecss = require('@fullhuman/postcss-purgecss')({
  // テンプレートファイルへのパス。今回は'./src/**/*.vue'
  content: [
    './src/**/*.vue'
  ],
  // https://medium.com/@kyis/vue-tailwind-purgecss-the-right-way-c70d04461475
  defaultExtractor: (content) => {
    const contentWithoutStyleBlocks = content.replace(/<style[^]+?<\/style>/gi, '')
    return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || []
  },
  whitelistPatterns: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!cursor-move).+-move$/, /^router-link(|-exact)-active$/ ],
})

module.exports = {
  plugins: [
    autoprefixer,
    tailwindcss,
    // 開発中はビルド時間がかかってしまうので、productionの時のみ実行
    ...process.env.NODE_ENV === 'production'
    ? [purgecss]
    : []
  ]
}

Before/After

npm build して、 dist/css/配下のCSS容量を見て見ます。

Before

スクリーンショット 2019-12-21 22.07.39.png

After

スクリーンショット 2019-12-21 22.18.58.png

644KB減!!
すごいぞ!PurgeCSS!! :tada:

今回はサンプルのためスタイリング自体が少ないので、実際のプロジェクトではもっと大きくなるんでしょうけれども、いやぁしかし気持ち良いですね :relieved:

まとめ

以上、初めてのtailwindcss (Vue.js + PurgeCSS)でした!
個人的にはめちゃくちゃ好きな思想のフレームワークです。
シンプルで良い。自由 is フリーダム。必要なものは自分で作る :relieved:

緻密かつ堅牢なCSSフレームワークに疲弊している方、ぜひトライしてみては如何でしょうか?

参考にさせて頂いたものまとめ

tailwindcssなのかTailwindcssなのか、はたまたTailwindCSSなのか、正しい表記が未だに分かりません :relieved:

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

あなたの好きなCSSプロパティは何ですか?

次の中から選んでね

  • transform: translate
  • margin: 0 auto
  • position: absolute

transformが好きなあなた

普通の人。みんな大好きtransform。
要素を変形するには万能なCSSプロパティ。

<div class="box"></div>
<div class="box box--move"></div>
.box {
  width: 100px;
  height: 100px;
  border: 1px solid red;
  box-sizing: border-box;
}

.box--move {
  transform: translate(100px, 0);
}

スクリーンショット 2019-12-22 2.46.35.png

まあこうなる。

では、これは?

<div class="box box--move-large"></div>
<div class="box box--large-move"></div>
.box--move-large {
  transform: translate(100px, 0) scale(2);
}

.box--large-move {
  transform: scale(2) translate(100px, 0);
}

スクリーンショット 2019-12-22 2.46.42.png

順番を変えただけで見え方が変わってしまった。
これには理由がある。

適用される 1 つ以上の CSS 変形関数です。変形関数は、左から右へ順に重ねられ、つまり右から左の順に変形の混合の効果が適用されます。
https://developer.mozilla.org/ja/docs/Web/CSS/transform

つまり、 2倍大きくなってからの translate(100px, 0)200px 移動することになる。

margin: 0 auto が好きなあなた

安定志向。
昔ながらの伝統的な中央寄せ。

<div class="box box--center"></div>
.box {
  width: 100px;
  height: 100px;
  border: 1px solid red;
}

.box--center {
  margin: 0 auto;
}

コンポーネント指向が浸透した昨今は

レイアウトは親要素に任せる方が適切なシーンが多い。
.box はどこに配置さるかを気にしない

<div class="container">
  <div class="box"></div>
</div>
.container {
  display: flex;
  justify-content: center;
}

position: absoluteが好きなあなた

きっと、すいも甘いも知った人。
absolute の従順さに惚れ惚れする。

<div class="container">
  <div class="box box--bottom"></div>  
</div>
.box--bottom {
  position: absolute;
  bottom: 10px;
  right: 10px;
}

.container {
  width: 80%;
  height: 300px;
  border: 1px solid blue;
  margin: 20px auto;
}

スクリーンショット-2019-12-22-3.02.49.png

親要素をたどって起点を探す

absoluteの bottom, right が基準となるのは position: relative がついている親要素。

つまり、 .containerposition: relative を設定すれば
.container を基準としたポジションとなる。

.container {
  position: relative;
}

スクリーンショット-2019-12-22-3.03.24.png

従順なやつだなと思う。

※動画解説版
https://www.youtube.com/watch?v=VFkwIGoKATo

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