Quantcast
Viewing all 8576 articles
Browse latest View live

コーディング初心者卒業!BEMを使用して簡単にCSS設計をしてみよう。

Ateam cyma Advent Calendar 2019、22日目です!
本日は株式会社エイチームでcymaのデザイナーをしている @ryo_cyが担当します。
今回はBEMというCSSの命名規則について、画像を使いながらわかりやすく説明していこうと思います!

BEMとは?

BEMとはBlock、Element、Modifierという3つの要素の頭文字を取ったものになります。
命名の書き方はblock__element--modifierとblockを先頭に記述します。
いきなりBlock、Element、Modifierと言われても何かよくわからないので、簡単に図にまとめてみました。
オレンジ色の枠で囲んでいる塊がBlock。
緑色の枠で囲んでいる要素がElement。
紫色で囲んでいる装飾部分がModifier。
以下の図を参考にしてBlock、Element、Modifierをより詳しく見ていきたいと思います。
Image may be NSFW.
Clik here to view.
Component.png

Block

Blockは、要素をまとめているメイン、サイドバー、記事のリスト一覧など、大きな塊部分を示します。
先程の図でいうと以下のオレンジ色の部分になります。
Image may be NSFW.
Clik here to view.
ComponentBlock.png

図のカード型コンテンツのフレームがBlockになります。
htmlとscssは以下のようになります。

html
<divclass="card"></div>
scss
.card{border:1pxsolid#ccc;padding:20px;}

Element

Elementは、大きな塊の中に入っているタイトルやボタン、説明文などの細かな部品を示しています。
先程の図でいうと以下の緑色の部分になります。
Image may be NSFW.
Clik here to view.
ComponentElement.png

図のカード型コンテンツのフレームに入っている各要素がElementになります。
htmlとscssは以下のようになります。

html
<divclass="card"><imgclass="card__image"src='a.jpg'><h1class="card__title">Title</h1><pclass="card__description">Lorem ipsum dolor ...</p><aclass="card__link">More</a></div>

クラス名を記載するときは以下のようにblock__elementという規則で命名します。

scss
.card{border:1pxsolid#ccc;padding:20px;&__image{width:100%;}&__title{font-size:24px;}&__description{margin-top:10px;}&__link{padding:5px30px;border:1pxsolid#ccc;}}

scssを記載するときはblockの中に&__をつけてElement名を記載します。

このように記載することで可読性が上がることと、コンパイル時に一つのクラスとしてcssが書き出されるため、その他のクラス名と重複することがありません。
例としてblockとtitleがCSSで出力されるときは以下のようになります。

css
.card{border:1pxsolid#ccc;padding:20px;}.card__title{font-size:24px;}

Modifier

Modifierは、ボタンやタイトルに色をつけたりと、各要素の装飾を行う際に使用します。
例えば、先程の図の右側コンテンツのボタンだけ青くしたいときなどに使用します。
下の図の紫色の部分がModifierです。
Image may be NSFW.
Clik here to view.
ComponentModifier.png

今回はボタンの色を変化させるので、ボタンのクラス名にModifierを追記します。
htmlとscssは以下のようになります。

html
<divclass="card"><imgclass="card__image"src='a.jpg'><h1class="card__title">Title</h1><pclass="card__description">Lorem ipsum dolor ...</p><aclass="card__link card__link--feature">More</a></div>

クラス名を記載するときは上記のようにblock__element--modifierという規則で命名します。

scss
.card{border:1pxsolid#ccc;padding:20px;&__image{width:100%;}&__title{font-size:24px;}&__description{margin-top:10px;}&__link{padding:5px30px;border:1pxsolid#ccc;&--feature{color:#fff;background:#55C0E1;border:1pxsolid#55C0E1;}}}

Modifierを記載するときはblockもしくはElementの階層中に&--をつけてModifier名を記載します。

BEMの必要性

BEMについて簡単に説明しましたが、なぜBEMを使用する必要があるのでしょうか。
私が思うに、以下の点が挙げられます。
- 保守性が高くなる
- 可読性が上がる
- 再利用がしやすい

保守性が高くなる

一番の理由とも言える部分です。
命名を規則化する事によって、保守性が高くなります。
BEMの規則上block要素が1つになるので、各要素のまとまりごとに管理することができ、要素の追加、削除を簡単に行うことができます。

Image may be NSFW.
Clik here to view.
ComponentMaintainability.png

可読性が上がる

BEMはblock__element--modifierと、記述する規則があるため、SCSSで記載する際にネストが深くなりすぎず、すぐに読み解くことができます。

Image may be NSFW.
Clik here to view.
ComponentReadability.png

再利用がしやすい

BEMはblockを起点として1つの塊で使用しているため、ページ内でコンテンツを移動したときや、同じデザインでコンテンツを追加した際に、他のスタイルによる影響を受けないため再利用がしやすくなります。

Image may be NSFW.
Clik here to view.
ComponentReuse.png

BEMをもう少し実用的に使用してみる

簡単にBEMの書き方、特徴を説明してきたので、ここからはもう少し深掘りして見ていきたいと思います。
先程までの説明は、1つのブロックに対しての説明のみでしたので、複数の要素が関わる場合どのように考え、記述していくのかを把握することによってよりイメージがしやすくなると思います。
まずは以下のようなデザインがあったとします。

Image may be NSFW.
Clik here to view.
ComponentMix.png

このデザインを制作する場合、どのようにBlockとElementを分けていくのか最初に考えてみましょう。

デザインをBlock、Elementに分けてみる

先程のデザインを分けてみると以下の3つのブロックに分けることができます。

Image may be NSFW.
Clik here to view.
ComponentMixBEM.png

ポイントはボタンをBlockとして分けて考えているというところです。
Blockを分けて考えることによって、デザインパターンが違っても1度作ったソースコードを簡単に再利用することが可能になります。
それでは実際にソースを見ていきましょう。
(SCSSはセレクタの構造を見やすくするため、プロパティを簡素化しています。)

HTML

html
<divclass="feature"><imgclass="feature__image"src="a.jpg"><divclass="feature__copy"><h1class="feature__title">Lorem ipsum dolor sit amet consectetuer adipiscing elit</h1><pclass="feature__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p><aclass="button"href="#">More</a></div></div><ulclass="cardList"><liclass="cardList__item"><imgclass="cardList__image"src="b.jpg"><h2class="cardList__title">Title</h2><pclass="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p><aclass="button"href="#">More</a></li><liclass="cardList__item"><imgclass="cardList__image"src="c.jpg"><h2class="cardList__title">Title</h2><pclass="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p><aclass="button"href="#">More</a></li><liclass="cardList__item"><imgclass="cardList__image"src="d.jpg"><h2class="cardList__title">Title</h2><pclass="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p><aclass="button"href="#">More</a></li></ul>

SCSS

scss
.feature{overflow:hidden;position:relative;&__image{float:right;width:60%;}&__copy{position:absolute;top:45px;left:0;}&__title{font-size:1.5rem;}&__description{font-size:0.875rem;margin:20px040px;}}.cardList{display:flex;justify-content:space-between;&__item{width:32%;border:1pxsolid#ccc;}&__image{width:100%;}&__title{font-size:1.5rem;}&__description{font-size:0.875rem;margin:5px020px;}}.button{padding:5px30px;border:1pxsolid#ccc;border-radius:5px;}

再利用するデザイン要素がある場合は、上記のようにブロックを分けることでソースコードが理解しやすくなるとともに、管理も簡単になります。

まとめ

BEMを使ったCSS設計の考え方や書き方について紹介させていただきました。
ごく一部のデザイン例を参考に記載しましたが、今回の内容を意識してサイトの構築をしてもらえれば管理のしやすい構造になっていくことでしょう!
最初のうちはどこでBlockを切り分けたらいいのか戸惑うかもしれませんが、デザイン全体を見たときに再利用できる部分を1つのまとまりとして認識していくことによって、徐々に慣れていくと思います。

今回は有名で考え方も簡単なBEMを紹介しましたが、CSS設計はBEMの他にもFLOCSS、SMACSS、OOCSSなど様々な手法があるので、サイトの規模やチームによって何を選択していくのかが、構築・運用していく上で大切になっていきます。
この記事が皆さんのCSS構築の参考になったら幸いです。

おわりに

Ateam cyma Advent Calendar 2019の22日目、いかがでしたか?
23日目は@sakura523さんがゲームUIデザイナーからWebデザイナーにジョブチェンした話をしてくれますのでお楽しみに!

株式会社エイチームでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。

エンジニアで興味を持った方はcymaのQiita Jobsをご覧ください。

そのほかの職種は、エイチームグループ採用サイトをご覧ください。


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

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

まぁ作っていこう!

@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><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><metahttp-equiv="X-UA-Compatible"content="ie=edge"><title>ダークテーマ</title><linkrel="stylesheet"href="style.css"></head><bodytheme="dark"></body></html>

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

:root{--s-1:02px5pxrgba(0,0,0,0.26);--s-2:02px10pxrgba(0,0,0,.2);}body[theme="dark"]{--m-bg:#121212;--d-color:#fff;--s-color:#9F9F9F;--s-bg:#242424;--b-1:1px#242424solid;--a-color:#EF5455;}body[theme="light"]{--m-bg:#FFF;--d-color:#202124;--s-color:#5F6368;--b-1:1pxsolid#dadce0;--a-color:#EF5455;}@keyframess-1{0%{box-shadow:00.001px0.001pxrgba(0,0,0,0.26);}100%{box-shadow:02px5pxrgba(0,0,0,0.26);}}body{background:var(--m-bg);color:var(--d-color);}

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

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

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

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

#themechange{border:var(--b-1);background:var(--m-bg);color:var(--a-color);font-size:18px;font-weight:bold;padding:10px15px;border-radius:4px;transition:all1s;}#themechange:hover{border-color:var(--a-color);background:var(--a-color);color:#fff;box-shadow:02px5pxrgba(0,0,0,0.26);animation:s-11sease0s1alternatenonerunning;}#themechange:focus{outline:none;}

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

document.getElementById("themechange").addEventListener("click",function(){vartheme=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フォローしてください!

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

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

<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><metahttp-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:02px5pxrgba(0,0,0,0.26);border-radius:8px;flex:00auto;margin-left:10px;background-color:#DADCE0;flex-shrink:0;}</style></head><body><divclass="main"><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div><divclass="card"></div></div></body></html>

PCでは使いにくいです。

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を使いましょう。

@mixinfont-size($size,$base:16){font-size:$size/$base+rem;}p{@includefont-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設計で気をつけること

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

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

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

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

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

ちなみに雪の結晶以外は全て、HTMLとCSSのみで作りました!
Image may be NSFW.
Clik here to view.
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:0auto;width:320px;height:320px;border-radius:50%;background:#3c3c3b;&__ear{// 耳position:absolute;top:50px;width:60px;height:60px;border-radius:80px100px0100px/100px130px0100px;background:#fff;&--left{// 左耳left:60px;&:after{// 左耳の穴position:absolute;top:12px;left:12px;width:40px;height:40px;border-radius:80px100px0100px/100px130px0100px;background:#000;content:'';}}&--right{// 右耳right:60px;transform:scale(-1,1);&:after{// 右耳の穴position:absolute;top:12px;right:8px;width:40px;height:40px;border-radius:80px100px0100px/100px130px0100px;background:#000;content:'';}}}&__face{// 顔position:absolute;bottom:0;left:50%;width:160px;height:250px;border-radius:80px80px00;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:100px200px;animation:Cry3sinfinite;&--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:24px24px24px24px/63px63px24px24px;background:skyblue;opacity:0;animation:Tears3sinfinite;}&__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:03px3px0;border-style:solid;border-color:#000;border-radius:0020px0/0020px0;&--left{// 口の左側left:135px;transform:rotate(25deg);}&--right{// 口の右側right:135px;transform:rotate(65deg);}}}@keyframesCry{// まばたきをするアニメーション0%{height:20px;transform:translateY(0);}25%{height:0;transform:translateY(15px);}50%{height:20px;transform:translateY(0);}100%{height:20px;transform:translateY(0);}}@keyframesTears{// 涙が流れるアニメーション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の値を出してくれる便利なサイトです。

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

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

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

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

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

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

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

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

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

サンプルケース

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

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

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

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

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

header.html
<headerclass="header"><!-- タイトル兼トップに戻るリンクゾーン --><h1class="header_title"><ahref="/">サイトタイトル</a></h1><!-- ナビゲーションリストゾーン --><navclass="header_nav"><ulclass="header_navList"><li><ahref="#section01">項目01</a></li><li><ahref="#section02">項目02</a></li><li><ahref="#section03">項目03</a></li></ul></nav><!-- ハンバーガーメニューボタン --><buttontype="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
<headerclass="header"><divclass="header_container"><divclass="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
<sectionid="#section01"><divclass="section_container"><divclass="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>だったので、なにか意図があるのかないのか分かりませんが)

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

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> を取得する */consthtmlTag=document.querySelector("html");// -> <html lang=...> ..... </html>/* 2. CSSプロパティの取得 */constcomStyle=getComputedStyle(htmlTag);// -> CSSStyleDeclaration {0: ... }/* 3. 変数の取得 */constcssVariable=comStyle.getPropertyValue('--isDarkmode');// -> "True"(ダークモード)・""(ライトモード)// ライトモードは、変数を指定していないため、空の文字列が返される

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

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

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

=====

3. 判定

/* 2 のコードの続き。"cssVariable" が定義されている前提 */constisDarkmode=!!cssVariable;// これでも同じconstisDarkmode=Boolean(cssVariable);

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

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

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

=====

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

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

概要

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

開発の目的

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

環境選択

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

環境iOSAndroidWeb
言語Swift or
Objective-C
Java or
Kotlin
HTML5+CSS
+JavaScript
iOS対応OXO
Android対応XOO
PC対応XXO
バイナリ実行OOX

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

PoC

準備段階

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

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

PoC:Gen.1

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

生成例1
f5f4d3f6g7c4g6f7g3h6b4h7h8f3e7e6h5c5f2c3b2e2d6d7d2g2h2e8f8a4b3g4h4c6d8a2b5c8g5b7c7f1a8c2e1a7a1g8e3d1c1b1a3a5g1h3a6b6b8h1

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

Image may be NSFW.
Clik here to view.
image.png

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

Image may be NSFW.
Clik here to view.
image.png

Image may be NSFW.
Clik here to view.
image.png

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

生成例2
c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1h1a7c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7g1g7c8c4c5f6d3e2b3b4b5e6f1d2f7a4g6b2b1a2e3f3c3a5g2g3g4c6b6d6f2f4d7h4g5d8e8f8c7g8c1a1f5d1c2h6h5h2e1b8b7a6e7a3h3a7

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

PoC:Gen.4

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

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

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

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

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

Evaluator.js
/*e0 and e1 : empty squares of upper/lower half.*/functionLFCountConnectedEmptySquares(e0,e1){vara=e0<<8&e0;varb=e1<<8&e1|e0>>>24&e1;varc=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&e1c+=LFCountNumberOfDisks(a,b);a=e0<<1&(e0&0xfefefefe);b=e1<<1&(e1&0xfefefefe);returnc+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 may be NSFW.
Clik here to view.
image.png

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

まとめ

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

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


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

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

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

こんな感じ↓
Image may be NSFW.
Clik here to view.
名称未設定ファイル (1).png

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

Image may be NSFW.
Clik here to view.
名称未設定ファイル (2).png

index.html
<ulclass="col2List"><liclass="col2ListItem"></li><liclass="col2ListItem"></li><liclass="col2ListItem"></li><liclass="col2ListItem"></li><liclass="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カラム

Image may be NSFW.
Clik here to view.
名称未設定ファイル.png

index.html
<ulclass="col3List"><liclass="col3ListItem"></li><liclass="col3ListItem"></li><liclass="col3ListItem"></li><liclass="col3ListItem"></li><liclass="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カラム

Image may be NSFW.
Clik here to view.
名称未設定ファイルのコピー.png

index.html
<ulclass="col4List"><liclass="col4ListItem"></li><liclass="col4ListItem"></li><liclass="col4ListItem"></li><liclass="col4ListItem"></li><liclass="col4ListItem"></li><liclass="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;}}

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

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

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

hover/activeの仕様

PCの :hover
Image may be NSFW.
Clik here to view.
hoverGif.gif

Mobileの :hover
Image may be NSFW.
Clik here to view.
mobileHoverGif.gif

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

PCの :active
Image may be NSFW.
Clik here to view.
activeGif.gif

mobileの :active
Image may be NSFW.
Clik here to view.
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の判別をしていきます。

先ほどの例に導入したものがこちら
Image may be NSFW.
Clik here to view.
pcGif.gif

Image may be NSFW.
Clik here to view.
mobileGif.gif

<template><divclass="card-container"><divclass="card":class="{
        'card-pc': $ua.deviceType() === 'pc',
        'card-mob': $ua.deviceType() !== 'pc'
      }"
    >
      Sample
    </div></div></template><stylelang="scss"scoped>.card-container{display:flex;justify-content:center;}.card{width:80%;height:200px;background:white;border:1pxsolidblack;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等の大型タブレットまで考慮すると難しくなってしまうので、今回はデバイスを取得する実装になりました。

最近流行りの斜めデザインのレイアウトを組む時に気をつけたほうが良いこと

最近流行りの斜めデザインのレイアウトを組む時に気をつけたほうが良いこと

こんばんわ。寒いですね。
いいネタが思いつかなかったので、最近苦戦した斜めデザインのCSSについて書きます。
斜めのデザインをCSSのskewで再現しようとすると、特定のブラウザで挙動が不安定なので気をつけよう・・・という内容になります。

問題の内容

まずはこれを見てください。

See the Pen povPeoy by Tatataichichichi (@unt_taichi) on CodePen.

よくある背景画像が斜めにトリミングされたデザインのレイアウトですね。
では、次にこちらを見てください。

See the Pen gObWweb by Tatataichichichi (@unt_taichi) on CodePen.

斜めになっている方向が、上のものとは逆向きになっているだけなのですが。。。
実はこちら、Safariなどのwebkit系のブラウザでレンダリングのバグが発生します。
背景画像の斜めの要素の部分が、ページをスクロールしたりコンテンツの表示域を可変させると、チラついた状態になり正しくレンダリングされません。

このレンダリングのバグの発生条件は、transformskewで右側に傾斜をつけた要素に対して、overflow:hiddenのCSSが適用されると起こるようです。

原因?

で、おそらくの原因ですが、transformskewで角度をつけたことにより、スタックコンテキストが生成されz-indexがただしく適用されず、Safariなどのブラウザ上ではレンダリングのバグとして表示されてしまう・・・ように見えます。

スタックコンテキストとz-indexについては、@ykyk1218さんの記事で分かりやすく書かれています。

参考記事:z-indexが言うことを聞いてくれない場合はこの辺のことが原因だと思うよ
https://qiita.com/ykyk1218/items/155ec7a8552da9fb2d8e

解決方法・・・?

解決方法としては、transform:skewで斜めに角度をつけた要素に、更にtranslate3d(0,0,0)でスタックレベル(Z軸)の指定をしてください。
これでSafariでもチラつかなくなると思います。

See the Pen LYEyWmM by Tatataichichichi (@unt_taichi) on CodePen.

分からなかったこと

・・・skewプロパティを使うことによりスタックレベルがずれるのが原因として、どうして右側に角度がついた時にレンダリングがおかしくなるのだろう。。。もし詳しい方いらっしゃいましたら教えていただけると幸いです。

それにしても寒いですね。。。風邪をひかないように暖かくしてクリスマスを迎えましょう!

Inline-blockとblockの違い

まとめて書くやり方css

Borderの長さを短くしたい

Vw,vh,vmin,vmaxの使い方


Cssのcontentの中に入れられるもののサイト。

先頭の文字だけ大文字にする

web版石巻バリアフリーマップから見た、障がいのある方へ情報を渡すUIとは

CivicTech AdEventCalendar 23日目です。

私は宮城県石巻市で、多目的トイレの情報をWeb上のマップにする活動をしています。

Webマップを作るきっかけ

私は自分自身も脳性麻痺によって手や足に障がいを抱えています。それで自らの目線を生かしてITサービスを作れたらと考えていました。それで、色々模索していた時に1冊の冊子に出会いました。
それが「石巻バリアフリートイレマップ」です

Image may be NSFW.
Clik here to view.
IMG_3940.jpg

Image may be NSFW.
Clik here to view.
IMG_3941.jpg

この冊子は、石巻市内の公共施設や大規模商店、コンビニや公園にある多目的トイレの機能をまとめた冊子です。しかし冊子という媒体である以上、情報に限界があります。それで、この冊子をWeb化することでより、当事者にとって必要な情報を渡せないだろうと思い、この冊子をWeb化するプロジェクトを立ち上げました。2020年の春に公開することを目標に取り組んでいます。

Web化することのメリット

以下モバイル版
Image may be NSFW.
Clik here to view.
IMG_3937.PNG

冊子からWebにすることで、最大のメリットは情報の豊富さである。Web化することで多目的トイレの情報に写真を付けることができます。実際に車椅子で生活しておられる方は、車椅子自体が各自の障がいに合わせてカスタムメイドされているので、大きさがバラバラである。それで、多目的トイレであってもその大きさと、当人の車椅子の大きさによっては、その多目的トイレが利用できないという現状が生まれてく来ます。しかし、写真によってトイレの様子やそれに加え、トイレの縦横の実寸を加えることによって、当人が自分で利用できるかできないかを判断してもらえるようにしてみました。
また、Web化をすることで、スマートフォンでも情報が見られるように設計できます。そもそもトイレという者は、突発的に生じてくるものです。しかし3.40年前の障がいのある方は、出掛ける前に事前に行くトイレを計画したり、もしくは絶食や絶水までもしていました。しかし、多目的トイレの情報がいつでもスマートフォンで探せるようにすることで、仮に障がいがあっても外に出掛けることの壁を少しでも取り除くことができるでしょう。

障がいのある方に向けたUI

これらのメリットを分かりやすく伝えることができるように、私は地図上に、多目的トイレがある建物をマッピングしました。そして、そのマッピングしたところのボタンを押すと、各建物の情報がモーダルの形になって表示されます。多目的トイレにある機能は、アイコンで色付けすることによって、この多目的トイレにどんな機能があるのか、見ただけで分かるようにしました。

Image may be NSFW.
Clik here to view.
IMG_3938.PNG

さらには、写真を伴う情報はスライドショーの方式で見られるようにしました。サイドに切り替えられるボタンを置き、それを押すことであらゆる方向で撮影した写真が表示されます。そうすることで、障がいを抱えておられる方が、自分にとってこの多目的トイレが利用できるかどうかを判断することができるでしょう。

視覚障がいがある方へのUI

しかし、視覚に障がいのある方にむけた場合は、サイトの作り方が少し変わってきます。視覚に障がいがある方は、スクリーンリーダーを使ってサイトを見ています。スクリーンリーダーでサイトを読んでもらうためには、いろいろな工夫が必要でした。まずスクリーンリーダーは、alt要素にある情報は読んでもらえるのですが、alt要素が付けられるHTMLタグは、非常に限られてきます。それでボタン類については、イメージ画像を使うことにしました。さらにマッピングしたボタン内のテキストも見た目を優先させてしまうと、改行をしたくなりますが、改行を入れてしまうと1つの建物名が複数の単語にスクリーンリーダーが認識してしまします。それで、ボタンのdivに対して、CSSでwhite-space: pre-wrapにすれば、テキストがdivの大きさに合わせて行を変えてくれて、しかもスクリーンリーダーが一つの単語として認識してくれます。

Image may be NSFW.
Clik here to view.
IMG_3939.jpg

さらに、モーダルの情報も1度のタップで必要な情報が渡せるように、あえてモーダルの上の部分に「i」というイメージ画像をおき、そこにalt要素で必要が情報を持たせることで、スクリーンリーダーがその情報を読ませることができます。そうするなら、視覚に障がいがある方でも必要な情報を得ることができるでしょう。

すべての人に向けたUIとは

自分自身も障がいがあるので、どんなUIなら使いやすいだろうかと少しは理解できていると思っていた。しかし、障がいは各々あり、それをすべて考慮してベストなものを提供することは非常に難しいと思いました。しかし、そこで分からないと決めつけるのでないと私は思っています。大切なことはそれぞれの障がいを考えてそれに寄り添う形で、UIを設計していくことが大切なのでないかと私は思っています。もちろん、この「石巻バリアフリーマップ」も今後もアップデートをしていきますが、その度に利用者の事情に寄り添って作って行ければと考えています。

〜まだfont-familyをコピペしているあなたへ�〜 フォントを理解し直そう

はじめに

初めまして、レバレジーズ株式会社でフロントエンドエンジニアをしている渡邉です。
先日サイトのリニューアルをしたのですが、その際フォントの設定で苦しめられたのでフォントについて調べ直してみました(タイトルにあるfont-familyをコピペで使ってたのは他でもない私です…)。結構細かい決まりやテクニックがあるので、この機会にひとつでも新たな知識を共有できたら幸いです。

font-familyの使い方

CSSでフォントの種類を指定する際はfont-familyというプロパティを使用します。例えばレバテックキャリアのページでは以下の様なfont-familyが指定されています。

body{  font-family:"Noto Sans JP","ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic Pro",メイリオ,Meiryo,"MS Pゴシック","MS P Gothic",Arial,icomoon,sans-serif;}

このように複数のフォントファミリーを指定するのはOSやブラウザによって使えるフォントが違ってくるためです。このように環境によって使えるフォントファミリーを意識しないと、思わぬ画面デザインになってしまうことがあります。

またfont-familyプロパティには以下のような決まりや特徴があります。

  • 選択した要素に対してフォントファミリー名総称ファミリー名の優先順位リストを指定することができる
  • 先に書かれたものほど優先順位が高い
  • 複数指定する場合はコンマで区切る
  • 空白が含まれている場合は「’」か「”」で囲う(例:”Times New Roman”)
  • 総称ファミリー名を最低一つは入れておくべき(理由は後ほど)
  • フォントの指定は1文字ずつ行われる(!)
  • つまり一文字ずつチェックされ、優先順位の高いフォントにその文字が指定されていない場合は一つ下の優先順位のフォントをチェックするということが繰り返される
  • 英語と日本語のフォントを指定する場合は英語を先、日本語を後に持ってくる(逆にすると英語フォントにも日本語フォントが当てられる)
  • OSやブラウザーなどの環境により、日本語の指示を無視してしまう環境があるため日本語名とアルファベット名両方を書いた方が良い

今出てきた、フォントファミリーとか総称ファミリーとかって何?

  • フォントファミリー名… 似たフォントがひとまとまりになったグループ。イタリック、ボールドといったフォントフェイスがグループになっている。(例:"Noto Sans JP", "ヒラギノ角ゴ Pro W3")
  • 総称フォントファミリー名…フォントを特徴によって分類されたフォントグループ。指定したフォントがなかった場合の代価案になる。ブラウザのデフォルトフォントになるという“最悪のケース”を防ぐためにつけるため、基本最後の選択肢に持ってくる。(例:sans-serif)

フォントの種類

フォントファミリー名は無限に存在しますが、総称ファミリー名はそこまで多くありません。特徴を覚えておくと便利です。

Image may be NSFW.
Clik here to view.
名称未設定のアートワーク.jpg

  • serif(セリフ)
    • 終わり止め払いのちいさんが飾りがあるもの
    • 飾りは『うろこ』や『ひげ』言われることもある
    • Times New Romanとか有名
    • 日本語フォントの明朝体にあたる
  • Sans serif(サンセリフ)
    • セリフ(文字端の小さな飾り)がないもの。
    • フランス語でセリフがないという意味
    • Helveticaとか有名
    • 日本語フォントだとゴシック系にあたる
  • monospace(モノスペース)
    • 全ての文字が同じ幅の文字
  • cursive
    • 筆記体、繋がった文字

フォント界のヒーロー?Webフォント

font-familyで複数のOSやブラウザ対策するのはめんどくさいですよね。デザインが変わってしまうのも気になります。そのような問題を解決してくれるのがWebフォントです。

メリット

  • あらかじめサーバーにあるフォントデータを使うためどの端末で見ても同じフォントで表示される
  • 複数のフォントを指定しなくても良いので楽

デメリット

  • 英語と比べて日本語ファイルは数が膨大なため、読み込みが重くなりがち

フォントについての問題や事件

ここから先はちょっと細かい話になります。ブラウザやOSによって使えないフォントを指定してしまうと意図しない表記になることがあります。ここでは有名な表記崩れや最近起こったフォント問題について挙げてみました。

Chromeのsans-serifフォントが「MSPゴシック」→「メイリオ」に変更問題

  • 2017年アップデートに伴い、windowx版chrome56とfirefox57のsans-serifのフォントが「MSPゴシック」→「メイリオ」に変更
  • 以前もsans-serifの適用フォントの変更はあった

対策

  • メイリオのフォントを指定する

教訓

  • フォントをユーザーがカスタマイズしていた場合、デザイナーの認識と違うフォントになっている可能性がある
  • OS依存システムフォントは変わってしまう可能性があるので、常にチェック&メンテナンスの必要がある

游ゴシックのwindows/Chrome表示がかすれちゃう問題

  • 游ゴシックはWindows と Mac の両方にプリインストールされているシステムフォント
  • webフォント以外でOS 間の差異がなく使えるフォントと期待されていた
  • しかし…windowxのchromeで游ゴシックを見ると掠れて見づらいという問題発生
  • windowsにはMacにはないRegularとLightが入っていてそれがデフォルト状態で表示されてしまうことが原因
  • @font-faceでオリジナルフォントを作るという対策があったが、Chrome62以降効かなくなった

対策 その1(font-weigntの指定)

font-family: "游ゴシック体", YuGothic, "游ゴシック", "Yu Gothic", "メイリオ", sans-serif;
font-weight: 500;
  • font-weightを500に指定

  • 游ゴシック最優先で、游ゴシックがなければ Windowsではメイリオ(さらになければMS Pゴシック)Macではヒラギノ角ゴとなるように指定する(windowsでヒラギノ角ゴを指定すると太字になるため)

対策 その2(font-family内で直接font-weightを指定)

font-family: "游ゴシック体", YuGothic, "游ゴシック Medium", "Yu Gothic Medium", "游ゴシック", "Yu Gothic", "メイリオ", sans-serif;
  • (注意)この指定方法をした文字を太字にすると文字がにじむ
  • (注意)いつこの指定方法が使えなくなるかわからない

教訓

  • 夢のフォントなど(まだ)存在しない!!

游ゴシック IEでテキスト下に余白ができる

  • IEではなぜか游ゴシックを指定すると、下に少し余白ができます…さすがIE

対策

  • IEだけフォント指定を変える
// IEのみの指定方法
_:lang(x)::-ms-backdrop, body {
    font-family: "メイリオ", Meiryo, sans-serif;
} 

// もしくは
_:-ms-fullscreen, :root body {
  font-family: Meiryo, sans-serif;
}
  • この他paddngを少しだけつけるなどでも対処可能

教訓

  • IE対応やめませんか?

MacOS Catalinaにアップデート後にサイトが明朝体化問題

  • Amazonのサイトも明朝体に(中国のサイトのようで怪しい…)
  • Mac CatalinaのChromeだとヒラギノフォントが認識されなくなったことが原因?
  • 「ヒラギノ角ゴシック Pro/ProN」が古いフォントとして認識されたことが影響している?

対策

  • font-familyの指定にHiragino Sansを追加

教訓

  • 昨日まで当たっていたフォントが今日も当たるとは限らない

ios13/safariで日本語フォント激太り問題

  • iOS13のsans-serifの Hiragino Sansにbold指定した場合、W7がなく近似のW8が当たることが原因

対策

  • font-weight:boldではなくfont-weight:600を指定する
  • (13.1ではすでに解決)

教訓

  • font-weightの指定にも気をつけろ(そろそろ教訓がなくなってきた

MacOS Mojave以降のアンチエイリアス問題

  • macOS Mojaveからアンチエイリアス方式が変わり、非Retina画面だとフォントが細く(汚く)表示される
  • アンチエイリアスの方法が変わりサブピクセル方式からグレースケール方式になったのが原因

対策

  • 対策なし。細いフォントファミリーやfont-weightを指定しない

教訓

  • 誰かにとって綺麗なものは他の誰かにとっては醜いものになる(そろそろ教訓がな略

結局どのフォントを使うのが良いの?

全てのサイトにとってのベストは無いので、ページスピード重視だったらブラウザごとにフォントファミリー指定、デザイン重視だったらWebフォントで指定など、その時々でそのサイトやユーザーに合ったフォント指定をすることが必要になってきます。また、ブラウザのアップデートなどにより状況も変わっていくので、常に最新情報を追っかけていく必要があります。
私も今後随時知識をアップデートしていこうと思います。ここまで読んでいただき、ありがとうございました。

【CSS】を上下左右中央で、エリアいっぱいに配置する

やりたいのはこれ!

Image may be NSFW.
Clik here to view.
上下左右中央配置 (3).png

作りたいのは、よくあるサムネイル付き記事の 一覧ページ↑↑。
(ほんでもって、ホバーしたら画像がふわっと拡大表示なんかしたりね、するよね。ね。)(←後述します)

今回は、cssだけでごにょごにょがんばります。

実装

3カラムとか作る前に、一旦width100%でコンポーネントを作ります。
Image may be NSFW.
Clik here to view.
widthが100% (3).png

index.html
<articleclass="articleWrap"><aclass="thumbnailWrap"href="#"><imgclass="thumbnail"alt="画像のalt"src="画像のパス"/></a><h3class="title"><ahref="#">記事タイトル</a></h3><pclass="text">どんな画像を入れてもピッタ。。。</p></article>
style.scss
a:hover{cursor:pointer;}.articleWrap{width:100%;background-color:#eee;}.thumbnailWrap{overflow:hidden;position:relative;display:block;height:200px;// ←画像の高さを設定します。/* (※ @mediaで、ウィンドウ幅ごとにheightを書き分けている↓↓のは、リキッドデザインに対応するためです。
  この一手間で、ウィンドウ幅が伸び縮みしてもきれいに表示させることが出来ます!)*/@media(min-width:641px)and(max-width:1000px){height:18vw;}@media(max-width:640px){height:48vw;}}$times:5;//何倍.thumbnail{min-height:calc(100%*#{$times});//←ここがポイント!min-width:calc(100%*#{$times});//←ここがポイント!transform:translate(-50%,-50%)scale(calc(1/#{$times}));//←←scale(1/5) = scale(0.2)ここがポイント!position:absolute;top:50%;left:50%;}

↓何してる??

<img class="thumbnail">5倍して、5で割ります
からのー、
translateとpositionで中央配置!
すると、ほーらできあがり\(^o^)/
($timesは、5にしています。いろんな画像をはめてみたところ、5で問題なく表示できました。)

ホバーしたらふわっと拡大表示させちゃう😊

せっかくなので、ユーザーがリンク領域だと認識できるように、
ホバーしたらアニメーションをさせてみましょう!

htmlに、classを1つ、zoomAnimationを新たに付加します。
場所は、thumbnailのところです。

index.html
<articleclass="articleWrap"><aclass="thumbnailWrap"href="#"><imgclass="thumbnail zoomAnimation"alt="画像のalt"src="画像のパス"/></a><h3class="title"><ahref="#">記事タイトル</a></h3><pclass="text">どんな画像を入れてもピッタ。。。</p></article>

scssには、以下のstyleを追記します。↓

style.scss
// 記事をホバーしたら。。.zoomAnimation{transition:all0.5sease;transform-origin:center;&:hover{transform:translate(-50%,-50%)scale(calc(1/#{$times}+0.02));//←0.02足す}}

scaleを0.2から、ホバーしたら0.22にして、少しだけふわっと大きくなるようにしました。
ってことで、これでコンポーネントは完成!

See the Pen どんな画像も中央でぴったりフィット by sayaka kiyose (@sayaka_kiyose) on CodePen.

3カラムにして見た目を整えよう!

Image may be NSFW.
Clik here to view.
widthが100% (2).png

前に書いた記事内の、3カラムレイアウト<li class="col3ListItem">の中に、
<article>タグごと放り込むだけ!おわり!

See the Pen 【3カラム】どんな画像も中央でぴったりフィット by sayaka kiyose (@sayaka_kiyose) on CodePen.

background-imageじゃだめなの?

いざCMS化して、方向もサイズもバラバラな画像たちが
imgタグに流し込まれたら、崩れてしまった。。。
だったらいっそのこと、
imgタグなんかやめちゃって、background-imageからのbackground-size:coverにしちゃって。。。↓
Image may be NSFW.
Clik here to view.
名称未設定ファイル (1).png

↑↑こんな風に出来たらなんて楽なんだろう。

でも、CSSはあくまで装飾。
コンテンツによっては、<img>タグとして画像を表示させたいときもありますよね。
見た目だけOKではなく、
セマンティックなマークアップをしていきましょう。!!





長くなりましたが終わり!

Viewing all 8576 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>