- 投稿日:2019-12-22T22:24:41+09:00
Nuxt.jsでhover/activeのレスポンシブ対応
一般的にWebアプリではクリックできることを示すために要素に
:hober
を付けます。
モバイル版のアプリではマウスがないため、長押しをした際に:hover
のような変化を付けるとタップ(クリック)できることが伝わるかと思います。これはTwitterなど多くのアプリに見られる実装です。この動作を実装したのでおこなったことをまとめます。
hover/activeの仕様
これではmobileで長押し後、別の場所をタップするまで
:hover
で設定したCSSが続いてしまいます。
これは想定している動作ではありません。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の判別をしていきます。<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等の大型タブレットまで考慮すると難しくなってしまうので、今回はデバイスを取得する実装になりました。
- 投稿日:2019-12-22T17:34:42+09:00
よく使う カラムレイアウトのマークアップ
めちゃめちゃよく使うので、今更ながらメモに残しとく?
左右のmarginは、.listItem + .listItemで、
上下のmarginは、2段目から取るようにしています。
左に左に、上に上に、marginをつけます。PCで2カラム、SPで1カラム
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カラム
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カラム
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; } }
- 投稿日:2019-12-22T17:21:42+09:00
終盤問題ジェネレーター(仮)の開発
概要
私が開発を進めている終盤問題ジェネレーター(仮、以下ジェネレーターと略)の開発に関する記事です。
後述の通り、特にジェネレーターのPoCに焦点を当てています。
リバーシ検討図メーカーの話も入っているかもしれませんが、便宜上ジェネレーターの話として紹介いたします。
ITを本職とされている方々からすると気になる部分などあるかもしれませんが、素人の戯言でございますのでご容赦ください。開発の目的
リバーシの終盤問題は既に複数の方が提供されています。
そういった問題集は良問が多い印象ですが、問題数に限りがあります。
無限に遊べる終盤問題集があればいいなと思い、開発を始めました。環境選択
開発するときにまず、どの環境を対象にするかを考えました。
候補として主に下の3つがありました(表は私の知っている限りの話です)。
環境 iOS Android Web 言語 Swift or
Objective-CJava or
KotlinHTML5+CSS
+JavaScriptiOS対応 O X O Android対応 X O O PC対応 X X O バイナリ実行 O O X これに通信機能を付けると、バックエンドのコードも書く必要があります。
私は「PCでも遊べるようにしたい」「バックエンドでNode.jsを使いたい」といったことを考え、Webで開発することにしました。PoC
準備段階
ジェネレーターで最も重要なのは生成エンジンの部分です。
本稿では「本当にそういったエンジンが作れるのか?」の検証(PoC)部分を中心に説明いたします。
開発初期は棋譜を出力し、作成された問題をWZebraでチェックしていました。
(参考図)
その後簡単な盤面表示関数を実装して、こちらでチェックするようにしました。
(X=黒石、O=白石)
PoC:Gen.1
Gen.1(第一世代、以下同様)として、ランダムに着手するだけのエンジンを作りました。
(ただし全体を通して、ジェネレーター関数はdeterministicとなるようケアしました。)生成例1f5f4d3f6g7c4g6f7g3h6b4h7h8f3e7e6h5c5f2c3b2e2d6d7d2g2h2e8f8a4b3g4h4c6d8a2b5c8g5b7c7f1a8c2e1a7a1g8e3d1c1b1a3a5g1h3a6b6b8h1
当然これでは、問題として通用する盤面は生成されません。
(下記解析例参照)
ただしこの、ランダムに着手するエンジンが全く使えないわけではありません。
様々試す中で、「ランダムな着手の一部を変更することで、互角に近い局面を生成すること」が可能であることが分かりました。
例えば棋譜例1ならば、52.h1 53.b8とすることでドロー局面が生じます。
PoC:Gen.2
Gen.1における試行の結果から、以下のような条件でエンジンを動作させることが有効と予想されます。
- ランダムな着手を途中で打ち切る
- 打ち切った局面から完全解析を実行
- 特定の評価値範囲内(例えば、黒+1~+10など)にある局面を抽出する
実際にこの条件で実行すると、以下の課題が見つかりました。
- 既に終局している局面が生成される。
- 最善進行の途中の局面が生成される。
- 不要なノードの探索に計算リソースが消費される
PoC:Gen.3
Gen.2の欠点を解消するため、追加で以下の制約を入れました。
- 連続して評価値Xの局面が生じる場合、評価値Xとなる空きマス数最多の局面のみを抽出する(課題1, 2対策)。
- 最低空きマス数を設定(課題3対策)
1について、例えば以下の3局面が検出された場合、1枚目の局面のみを抽出し、残りの局面は破棄することを意味します。
以上の対策の結果、以下のような棋譜を生成するエンジンが出来上がりました。
生成例2c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1h1a7 c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1g7c8 c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7a3h3a7ただし、生成された局面が「不自然」という課題がありました。
PoC:Gen.4
ジェネレーターをより実戦向きにするため、抽出される局面がより「自然」となるよう改良を実施しました。
解決に当たり、まず以下のような仮説を立てました。
- 人間から見て「不自然」な局面は、局面の見た目で判断されている。
- 局面の見た目は石の配置に依存する。
- 石の配置の「自然さ」を評価する静的評価関数を導入し、より評価値の高い局面を抽出することで、より「自然」な局面のみを生成するエンジンとなる
これを確認するため、まず以下の対策を行いました。
- 「自然さ」の評価関数導入
- 「自然さ」評価値上位の問題の抽出
評価方法の一例として、「空きマス同士が隣り合っているか?」を紹介いたします。
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 )を参考にしました。ある程度評価関数の実装とパラメーター設定ができたところで、一度アンケートを実施しました。
あなたはこの盤面が...
— AL4TH/あるふぉーす (@al4_th) December 15, 2019あなたはこの盤面が...
— AL4TH/あるふぉーす (@al4_th) December 15, 2019この時、同じ評価関数から得られた2つの局面について同時にアンケートをとりました。
結果、片方は「不自然」が多数、もう片方は「自然」が多数といったアンケート結果になりました。
このアンケート結果から、以下のように考えました。
- 同じアルゴリズムから「不自然」「自然」両方の局面を生成しうる。
- 評価関数の改良で「不自然」な局面を排除できるようになるのではないか?
PoC:Gen.5
Gen.4の考察から、色々と評価関数の調整を実施しました。
詳細は割愛しますが、以下のような局面(黒番)をコンスタントに生成するエンジンができました。
参考動画 : https://youtu.be/kfDp3Uc4LRI
まとめ
Gen.5である程度「自然」な局面を選択的に生成できるようになりましたので、PoCの目的を達しました。
エンジンは32bit整数 x 2をseedとして入力可能ですので、最大で64bit unsigned intの最大値=4294967295パターンの問題を生成可能です。
(必要な時はさらに追加可能。)
これからは、作成したエンジンを使って終盤問題アプリを作っていきたいと考えています。最後に、オセロ Advent Calendarにお誘い頂いた@sensuikan1973さんに感謝申し上げます。
長らく駄文にお付き合いいただきありがとうございました。
- 投稿日:2019-12-22T17:13:32+09:00
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で、
getComputedStyle
とgetPropertyValue
を使用できる
モダンブラウザすべてに対応しています。
(ユーザーがJSを「実行しない」にしていなければ)取得できます。考え方
- JSでは現在、「直接の」判定はできない。
- しかし、CSS変数は取得できる。
- Media Query で、CSS変数の値を変えることが可能。
...ということは...??
- Media Query で CSS変数を定義
- 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 です。
そのため、isDarkmode
はfalse
を返します。ダークモードでは、
cssVariable == "True"
→ Truthy なので、true
を返します。Truthy - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
Falsy - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN=====
以上により、ブラウザがダークモードかを取得することができました!
- 投稿日:2019-12-22T13:32:28+09:00
ヘッダーを作るときに考えること
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.csssection { margin-top: -60px; padding-top: 60px; }もしこれを
background
と併用してしまうと、padding-top
の分だけ伸びた背景がmargin-top
のネガティブマージン分だけ上にズレることになるため、本来の位置よりもヘッダーの高さ分上にズレて見える<section>
が爆誕します(そもそもmargin
やpadding
を当てている場合もそれらを上書きしてしまいますね)。これを防ぐためには先ほどのヘッダーのように、内に
身代わりの<div>
をかますことが大事です。section.html<section id="#section01"> <div class="section_container"> <div class="section_inner"> <!-- 中身は省略 --> </div><!-- /.section_inner --> </div><!-- /.section_container --> </section>section.csssection { margin-top: -60px; padding-top: 60px; } .section_container { background: #000000; /* ... */ }他にも考えることは色々とあるのですが、HTMLをシンプルにしすぎるのもほどほどにした方がよさそうです。
おまけ
実ははじめに見ていただいたQiitaのヘッダーのガワ部分も、
<div class="st-HeaderContainer">
とガッツリ<div>
だったりします。
(グローバルフッターは<footer>
だったので、なにか意図があるのかないのか分かりませんが)あらためて、タグの定義された意図を再解釈する必要があると感じる年末なのでした。
- 投稿日:2019-12-22T13:12:11+09:00
progate html,css道場 2
- 投稿日:2019-12-22T13:02:27+09:00
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率です)
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を搭載の機種を対象とします。
html
とbody
はどちらに記述するべきか?どちらでも問題ないようです。
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 Kaku Gothic ProN
とHiragino Kaku Gothic Pro
を比較して『N』はいくつかの漢字が旧字体になります。
Hiragino Sans
はProN
寄りです。参考: 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に向いていないのでこれは削除します。
あくまで一般的で無いだけで、電子書籍等のサイトでは採用してみるのも面白いかもしれません。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おすすめゴシック体 - Qiitabody { 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-weight
をnormal, bold
で記述していた人は数値で入力する癖をつけないといけませんね。教えて
Bootstrapを参考にしたのですが、
Segoe UI Emoji
,Segoe UI Symbol
と2種類記載する理由が分かりませでした。
ご存じの方いましたらご教授ください。最後に
2020年まで使えるfont-familyおすすめゴシック体 - Qiitaでは多数の方にご迷惑をおかけしました。(私のせいでは無いけれど)
慣れ親しんだフォントが記載されなくなって、なんだか不思議な感じです。斜め読みした方も、全部読んでくれた方もお疲れさまでした。
1ヶ月以上前から書き始めて、何度も何度も修正したので変なところがあるかもしれません。
見つけたらご指摘ください。絵文字とスマホはもうちょっと改良の余地があるかもしれない。
- 投稿日:2019-12-22T12:42:20+09:00
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.cssheader { 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を無効化する?
とか言ってたかも。
- 投稿日:2019-12-22T10:58:53+09:00
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
で分かりやすいです。
15px
は1.5rem
と書きましょう![疑問] 全部pxじゃだめなの?
1rem
=10px
より全部px
で書くほう分かりやすい。
15px
と書いたほうが楽だし。なぜこんな変な書き方が流行ったのでしょうか?
IE9以前(だったかな)は
font-size
をpx
で指定すると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-size
を20px
に変更したとします。
この場合にブラウザに表示されるp
のfont-size
は18.75px
です。
なぜこんな数字になるのか?20px * 62.5% * 1.5rem
で18.75px
となるわけです。「良いんじゃん!」と思った方、本来
p
は20px * 1.5rem
で30px
となるべきです。
ユーザー設定20px
なんて極端な数値で紹介していますが、17px
や15px
などで設定している方はザラに居るはずです。
そうなったときに値の変動が小さい問題が発生します。。pxでの問題
html { font-size: 10px; } p { font-size: 1.5rem; }ユーザーがブラウザの
font-size
を20px
に変更したとします。
この場合にブラウザに表示されるp
のfont-size
は15px
です。
ユーザーの設定を無視する最低な書き方になります。
今はユーザーファーストな時代です。
ユーザーの設定にも負けない、デザインにpx
単位で忠実なものが美徳な時代もありましたが...解決策
正しい書き方は以下
p { font-size: 0.9375rem; }以上です。
正しい書き方はhtml
にfont-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
だけではありません、margin
やpadding
などなどrem
で指定しなければいけませんね。mixinを作りまくってください。app.cssp { font-size: 0.9375rem; margin-top: 10px; margin-bottom: 10px; }こんな書き方をするとユーザー設定が影響して、文字サイズだけ変更できたのに余白が変更できないのでチグハグなことになっちゃいます。ちゃんと適切に
rem
で指定しましょう。
border
などは、rem
で指定すると1px
以下になってしまい、見えなくなってしまうのでpx
で指定するような例外的なプロパティもあるので注意してください。終わり
レムりんよりラムりんがスキです。
CSS Advent Calendar 2019最終日も私です。よろしくおねがいします。
← 17日『CSS設計で気をつけること』
→ 19日『CSS設計で気をつけること』
- 投稿日:2019-12-22T10:22:39+09:00
可愛いしろくまの404ページを作ってみた
WordPressの自作テーマを作成中、404ページをちょっと変わったデザインにしてみようと思い、404の「0」の部分をしろくまに変えたデザインを作ってみました。
404ページに行くのが楽しくなる!...かも?
実際に作った、しろくまくん入りの404ページ
こちらが実際にWordPressテーマ作成中に作った、しろくまくん入りの404ページになります。
ページが見つからなかった。という悲しさを表現する為に泣かせています( ;∀;)ちなみに雪の結晶以外は全て、HTMLとCSSのみで作りました!
書いたコード
※スマホで見るとぐしゃぐしゃになってしまいます(`;ω;´)
全体のコード
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の値を出してくれる便利なサイトです。最後までご覧いただきありがとうございました!
- 投稿日:2019-12-22T07:45:49+09:00
かっこいい横スクロールを実装する
ちょっと個人的なメモ程度なので適当です。
<!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では使いにくいです。
- 投稿日:2019-12-22T07:21:48+09:00
ダークテーマとかに切り替える。
皆さんこんにちはルサカです。最近ダークテーマ流行してますよね!
今回は、ユーザーのテーマを取得したり、ユーザーがテーマを変更できるといったものを作って行きたいと思います。まぁ作っていこう!
@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フォローしてください!
- 投稿日:2019-12-22T04:05:41+09:00
初めてのtailwindcss (Vue.js + PurgeCSS)
この記事は
CSS Advent Calendar 2019 21日目の記事です。
気になってたtailwindcssを、Vue.jsでやってみましたという記事です。
リポジトリはこちら→ https://github.com/hisako135/tailwindcss_vue_demo
やったことは以下のような感じです。
- Vue.js でのtailwindcssのセットアップ
- PurgeCSS でのファイル容量の削減
tailwindcssってなんぞ
"Bootstrapをゴリゴリいじってカスタマイズしても良いのだが、そこに時間かけるんならCSSフレームワーク使う利点なくない...?
" などと思ったことがある人はいませんか...?
グリッドシステムと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の考え方についてはこちらの翻訳記事に詳細書いてありますので是非!
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.jsconst 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.js
でtailwind.css
をimportしますsrc/main.jsimport Vue from 'vue' import App from './App.vue' import '@/assets/tailwind.css' //これ Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')セットアップは以上です!
![]()
今回は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の特徴を極一部ですがご紹介します!
めちゃくちゃ詳しく書いて下さっている記事はこちらですので是非!
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.jsmodule.exports = { theme: { extend: {} }, variants: {}, plugins: [] }作成された
tailwind.config.js
にカスタマイズしたいプロパティや追加したいプロパティを記載していきます。
tailwindcssでは現状transition
のようなアニメーションに関するプロパティが定義されていません。
そういうものの追加にも便利そうですね。拡張が簡単なのは嬉しい![]()
(今回はtransitionのutilityクラスを定義するのにtailwindcss-transitionsを使用しました。)PurgeCSSで使ってないCSSを削除
さて、なんだかスマートに感じるtailwindcssですが、ファイル容量は実は結構重いです。
PurgeCSSで、使ってないCSSを削除していきましょう。
- PurgeCSSをインストール
npm install @fullhuman/postcss-purgecss --save-dev
postcss.config.js
にプラグイン設定
- tailwindcssとVue.jsのそれぞれの特徴を踏まえ適切にパージするように
defaultExtractor
とwhitelistPatterns
を設定します。詳細はこちら → https://medium.com/@kyis/vue-tailwind-purgecss-the-right-way-c70d04461475postcss.config.jsconst 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
After
644KB減!!
すごいぞ!PurgeCSS!!![]()
今回はサンプルのためスタイリング自体が少ないので、実際のプロジェクトではもっと大きくなるんでしょうけれども、いやぁしかし気持ち良いですね
![]()
まとめ
以上、初めてのtailwindcss (Vue.js + PurgeCSS)でした!
個人的にはめちゃくちゃ好きな思想のフレームワークです。
シンプルで良い。自由 is フリーダム。必要なものは自分で作る緻密かつ堅牢なCSSフレームワークに疲弊している方、ぜひトライしてみては如何でしょうか?
参考にさせて頂いたものまとめ
- tailwindcss
- CSS Utility Classes and "Separation of Concerns" 翻訳
- TailwindCSS入門 ~ Utility First + デザインシステムの構築 ~i
- tailwindcss/setup-examples
- Setting up Tailwind CSS with Vue.js
- Vue + Tailwind + PurgeCSS — The right way
- React上でtailwindcssを使いたい!
tailwindcssなのかTailwindcssなのか、はたまたTailwindCSSなのか、正しい表記が未だに分かりません
![]()
- 投稿日:2019-12-22T03:13:26+09:00
あなたの好きな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); }まあこうなる。
では、これは?
<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); }順番を変えただけで見え方が変わってしまった。
これには理由がある。適用される 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; }親要素をたどって起点を探す
absoluteの
bottom, right
が基準となるのはposition: relative
がついている親要素。つまり、
.container
にposition: relative
を設定すれば
.container
を基準としたポジションとなる。.container { position: relative; }従順なやつだなと思う。