LoginSignup
70
76

More than 5 years have passed since last update.

HTML/CSSをもう少し極めたいデザイナー/エンジニアに伝えたい「3つ」のこと

Last updated at Posted at 2019-01-05

デザイナーにもエンジニアにも取っつきづらいHTML/CSS

結構嫌われ者ですよね。HTMLとCSS。
デザイナーからは「え、コードじゃん。やだわ。」とシンプルに言われたり、エンジニアからは「CSSの書き方が独特すぎてちょっと。。。」なんて言われたりします。悲しい。

「ではHTMLとCSSを極めてマークアップエンジニアになるかー」とそれらを極めた人は、現状のWebの進化に置いてけぼりにされて飯が食えなさそうな雰囲気がプンプンします。(私のことですね!)
デザインリサーチをしこたま学んでUXデザイナーの道に進むか、オブジェクト指向をしこたま学んでフロントエンドエンジニア(以下FE)になるか、はたまた全然違う職種になるか、という選択を迫られることになるはずです。

しかし、今のマークアップエンジニアがUXデザイナーやFEに振り切ったとしても、結局HTML/CSSを書く人がより減っていくことになります。
最終的に「Web上のデザイン」が決まるのは「CSS」になるので、だれかしらがCSSを書かないとUXに貢献できるUIは作成できないわけです。

「デザインやFEのスキルがあって、アドオンでHTML/CSSが書けると良い」という形で、アドオン扱いされてしまうようになってしまったマークアップエンジニアのスキルを、デザイナーもエンジニアも、それ以外の人も書けるようになるために記事を書いていこうと思います。

たかがHTML/CSSです。大したことはないのです。
ただ、実際初めてみると、されどHTML/CSSというのも事実なのです。困りました。。。

厄介なのは「なんとなくできてしまう」こと

HTMLやCSSを使えばページが作れること自体は、ググれば一発でわかります。
テキストエディタも、Sublime TextAtomVSCodeあたりを使えばオシャにコードが書けます。(私はVSCodeを使っています。)

ただ、ページを作っていくと、なんか闇の中に放り込まれた感覚がありませんか?
世の初心者向けのページを見ながらなんとなくページを作っていくと、自分がどこにどのCSSを書いたのか全くわからなくなり、ある部分のデザインを変えたつもりが他の箇所のデザインが変わっていることなんかもあります。

ただ、結局なんだかんだ言っても、
なんとなーーーーくごちゃっと書いてみたら、なんかできちゃった!!

となるのが、HTML/CSSの怖いところです。
なんかできちゃうんですよね。

ただ、その作ったサイトを運用していきたいと思って、どこか修正をしようとしたときには
もう何がなんだかわからないよー!えーん!
なんてことになるわけです。

なので今回は、初心者でもちゃんと保守性高く、品質の高いコードを書けるように以下の3つを説明をしていきます!

  • まずは「小さいもの」から作るべし!
  • 「レスポンシブ」に作るべし!
  • px%を使い分けるべし!

まずは「小さいもの」から作るべし!

初心者向けのサイトを見ていると、だいたい「大きいもの」から作るようになっています。

それもそのはずで、<html>の中に<body>を書いて、その後に全体を囲う<div id="wrapper">を作って…となっていくので正しいといえば正しいです。

しかし、この「大きいものから作る」というのが、後々「一部のデザインを変えたつもりが他の箇所のデザインも変わっちゃっていた」につながるわけです。

これを解消するために「小さいもの」から作るようにすると良いです。

デザインの統一を考える

例えば、ポートフォリオサイトを作っていて「お問い合わせ」というようなボタンがあったとしましょう。
この「お問い合わせ」というボタンの見た目は、ページ内で統一されていたほうが良いですよね。

基本的なページデザインをするときのざっくりとした流れは、ワイヤーフレームを作って情報設計を明確にしてから色を乗せて…というような「大枠からデザインしていく」のがベーシックかと思います。

もちろんデザインの仕方としては正しいのですが、デザインレビューを通したつもりでもどうしてもデザインに統一性がない状態に気づず、結局そのままコーディングに入ってしまって、リリースしてから気づいてもう手遅れ…みたいなことが起こりかねます。
ページの上部と下部に「お問い合わせ」というボタンがあるUIだとして、その「お問い合わせ」のボタンが上部は赤いボタンで下部が青いボタンになってしまっていたらユーザビリティに問題が出てしまいます。(極端な例ではありますが…)

しかし、保守性の高いHTML/CSSを書こうと「小さいもの」からコーディングすれば、自然とパーツのデザインの統一を見直す機会も得ることができます。

若干ページ内でボタンのデザインが違ったとしても、コーディングの段階で「共通化」しようとするので、デザインもきれいになっていきます。

当然、「ボタン」という単位でCSSを書くようなるので、「お問い合わせ」ボタンのデザインを変えようとしたときにページ全体のボタンのデザインを一気に変えることができます。

BEMを知る

では、そのお問い合わせのボタンのデザインを決めるためにCSSをあてたいわけですが、そのためには「class名」を決めなければなりません。

そのclassは自由に名前をつけられるわけですが、この名前をちゃんとつけないと「あー!こっちのボタンとあっちのボタンほとんど一緒なのにまたイチからCSS書かないとだめだー!」となりがちです。

そんなことが起きないようにするためには「class名の設計」を行う必要があり、それの基礎となるのが「BEM」という考え方です。

BEMと言ってもいろいろあるのですが、ざっくりとした概要は以下の通りです。

  • 一つの塊を、要素の大小に関わらず「block」とする
  • blockに依存する中身の要素を「element」とする
  • blockやelementがいろいろな状態を持つとき、その状態のことを「modifier」とする
  • block、element、modifierは「block__element--modifier」と表現する

だいたいこんな感じです。
block名やelement名が一つの英単語で収まらない場合は、様々なやり方がありますが、私はlowerCamelCaseを使うのが好きです。
(記事を読み進めていくと命名の仕方が掴めると思うので、よくわからないなーという方はそのまま読み進めてください〜)

BEMで書く

上記のルールを基にボタンを作っていきます!

ただ、その前に、reset用cssの説明をします。
この記事ではEric MeyerのCSSを使っています。
また、追加で以下のコードを入れてコーディングしていますのでご承知おきください。

reset.css
*, ::before, ::after {
  box-sizing: border-box;
}

:root {
  font-size: 13px;
  line-height: 1.2;
  color: #333;
}

上記の準備が出来たら本番です。buttonのコーディングをしていきます。

html
<button class="button button--level1">お問い合わせ</button>
css
.button {
  display: inline-block;
  border: none;
  border-radius: 5px;
  border: 1px solid;
  padding: 9px 14px;
  text-align: center;
  font-size: inherit;
  line-height: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.button.button--level1 {
  border-color: #f35;
  background-color: #f35;
  color: #fff;
}

そして、見た目は以下のようになります。
image.png
それっぽいですね!

今回、button--level1という記述をしていますが、これが「modifier」と呼ばれるものです。
これは、ボタンというUIに複数の表示パターンがあることを想定しているために入れました。

命名するときは、色名(redなど)や機能名(inquiryなど)で命名するよりか、
レベルで分けたほうがデザインの情報設計とすり合わせがしやすくなります。

そのページ上で、一番強調したいボタンなのか、それともリンクよりも少し目立たせたいためにボタンのUIにしているのか、という「情報設計上でのコンテキスト」で命名したほうが使いやすいと私は思います。
image.png
このようなボタンができた場合に、button--red2というのも微妙ですし」、button--inquiry2というのも微妙ですし、ボタンの中の文言が「もっと見る」とかだったら、同じデザインなのにbutton--moreというmodifierを作らなければならなくなります。

なので、上記のbuttonにはbutton--level2というmodifierをつけてあげることで、スッキリとCSSを書けてデザインも統一できます。

全体のコードは以下のようになります。

html
<button class="button button--level1">お問い合わせ</button>
<button class="button button--level2">お問い合わせ</button>
css
.button {
  display: inline-block;
  border: none;
  border-radius: 5px;
  border: 1px solid;
  padding: 9px 14px;
  text-align: center;
  font-size: inherit;
  line-height: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.button.button--level1 {
  border-color: #f35;
  background-color: #f35;
  color: #fff;
}

.button.button--level2 {
  border-color: #f35;
  background-color: #fff;
  color: #f35;
}

modifierには差分の色だけを当てて上げればいいので、修正もしやすくなります。
便利!

「デザインの共通化」を意識してみる

今回はボタンを例に挙げましたが、その他にも見出しとか、ラジオボタン、チェックボックス、テキストボックス、アイコンなどなどの「小さいもの」からコーディングをしていくと「パーツ集」を作ることができます。
パーツ集が作れてしまえば、あとはそれの組み合わせでコーディングすることができます。

一旦、<body>の中にパーツだけを作っていってしまって、そのクラス名をあとで使いまわしていくのが良いのかなと思います。
<button class="button button--level1">というのを作っているので、あとはボタンを置きたいときに、このHTMLをコピペしちゃえばOKになります。

もし、コピペをしやすくしたい場合は、parts.htmlというのを仮で作ってしまって、その中にパーツ集を作って、実際のページはindex.htmlの方に書いていけばよいかと思います。(CSSは共通で<link>で引けばOKです。)

「レスポンシブ」に作るべし!

「レスポンシブ」と聞くと、スマホでもPCでも見られるを作る場合のときだけなイメージがあります。
ブラウザの幅を小さくしていくと、「PC→タブレット→スマホ」の順に、それぞれ最適化されたデザインになっていくページを「レスポンシブ」と呼ぶケースも多いと思います。
参考:ミツエーリンクスの企業ページ

ただ、スマホ向けだろうがPC向けだろうが、必ずレスポンシブを意識してコーディングすべきです。

横幅可変を常に心がける

例えば以下のようなデザインがあるとします。
image.png
これは、先ほどのbuttonというblockを使ってコーディングしています。(なのでbuttonのCSSは省略しています。)

html
<div class="inquiryLink">
  <p class="inquiryLink__lead">以下からお問い合わせください!</p>
  <div class="inquiryLink__button">
    <p class="inquiryLink__buttonInner">
      <button class="button button--level1">お問い合わせ</button>
    </p>
  </div>
</div>
css
.inquiryLink {
  margin: 0 auto;
  padding: 30px;
  width: 600px;
  background-color: #f5f5f5;
  text-align: center;
}

.inquiryLink .inquiryLink__lead {
  font-size: 15px;
}

.inquiryLink .inquiryLink__button {
  margin-top: 10px;
}

.inquiryLink .inquiryLink__button .button {
  width: 300px;
}

いい感じに書けていますね。
inquiryLinkというblockの中に要素が2つあるので、inquiryLink__leadinquiryLink__buttonというelementを用意しています。

ただ、一点気になる記述があります。

.inquiryLink .inquiryLink__button .button {
  width: 300px;
}

この部分です。
inquiryLink__buttonの中に入ったbuttonの横幅はwidth: 300pxになるようにしています。

一見、大した問題はなさそうです。

しかし、実は、BEMのルールにはblockの中ですべて完結させるというルールがあります。
理由としては、もしbuttonのCSSが変わってしまったときに、予期せぬ表示崩れを起こす可能性があるからです。

なので、他のblockからスタイルを上書きはしたくありません。

では、このUIのときにどのように解決すべきかというと、、、

ボタンを横幅可変にしてしまえばいい!

わけです!

buttonのCSSを以下のように変えます。

css
.button {
  display: inline-block;
  /* 以下のwidthを追加 */
  width: 100%;
  border: none;
  border-radius: 5px;
  border: 1px solid;
  padding: 9px 14px;
  font-size: inherit;
  text-align: center;
  line-height: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

するとパーツがこうなります。
image.png
びよーーーーーん

ふざけているように見えますが、これで問題ありません!

buttonをこの状態にしておいて、先ほどのinquiryLink__buttonを修正します。

css
.inquiryLink {
  margin: 0 auto;
  padding: 30px;
  width: 600px;
  background-color: #f5f5f5;
  text-align: center;
}

.inquiryLink .inquiryLink__lead {
  font-size: 15px;
}

.inquiryLink .inquiryLink__button {
  margin-top: 10px;
  text-align: center;
}

.inquiryLink .inquiryLink__buttonInner {
  display: inline-block;
  width: 300px;
}

変わった部分は、inquiryLink__buttonInnerにスタイルを追加で当てて、buttonへのスタイルを消した点です。

buttonの横幅が可変になっていることによって、

外側のelementが横幅を決める責任を担える

わけです。

blockに閉じたスタイルだけをかけるようにする

marginborderpaddingといったもので、余白や枠線を指定できます。
toprightbottomleftで表示位置も指定できますね。)
このうち、どれをblockのスタイルにしていいのかを掘り下げていきます。

image.png

Chromeの開発者ツールを使用すると検証をすると上の画像のものを出せます。
54058と書かれているのがwidthheigthになります。

上記の画像をよく見ると、marginborderの線が実線で描かれています。(黒い線が濃く出ています)
この実線より内側のものをblockのスタイルとしてかけるべきです。

ただし、少しややこしいのですが、box-sizing: border-box;を適用している場合は、widthheightで指定した数値は、borderpaddingを含めた値」になります。
(今回は、最初に全要素にbox-sizign: border-boxを適用しています。)

上の画像のケースでは、width: 600pxpadding: 30pxにしているため、box-sizing: border-boxの効果により、実際のwidthの幅 = 600px - 30px * 2 = 540pxとなっています。

つまり、box-sizing: border-boxを適用している場合は、
marginborderの間の実線の位置が、ちょうどwidthheightの値の位置」になります。

なので、私が言った「この実線より内側のものをblockのスタイルとしてかけるべき」という言葉はwidthheightは含めない」ということになります。

なので、blockにかけるべきものはborderpaddingになります。
それよりも外側のものは、それを囲うものに担当してもらうのが良いです。
topleftなども外側の扱いです。)

なので、inquiryLinkは以下のように書き換えたほうが良いです。

css
.inquiryLink {
  padding: 30px;
  background-color: #f5f5f5;
  text-align: center;
}

.inquiryLink .inquiryLink__lead {
  font-size: 15px;
}

.inquiryLink .inquiryLink__button {
  margin-top: 10px;
  text-align: center;
}

.inquiryLink .inquiryLink__buttonInner {
  display: inline-block;
  width: 300px;
}

変わった点は、.inquiryLinkからmarginwidthを削除しました。
削除した部分は、更に外側に来るblockに幅を決めてもらえばよいのです。

px%を使い分けるべし!

「すべてレスポンシブで作れ」と言われると、「すべて%で作るべきかな?」と思いがちです。
しかし%で作ってしまうと、実はデザインが崩れてしまいます。。。

CSSで「余白」を制してデザイナーに好かれよう#グリッドシステムを知る

自分の記事で恐縮ですが、UIを作る上ではグリッドシステムを設計しているケースがあったり、設計はされていなくても余白の縦のラインは気にするケースがあったりすると思います。
この場合、margin%にしてしまうと、一気に崩れてしまいます。

理由はmargin%指定にした場合、自分自身のwidthに対しての百分率になる」からです。

例えば、1カラム表示のときの左余白と2カラム表示したときの左余白は要素の幅が異なることで当然左余白に差分が生まれてしまい、縦の余白のラインが揃わなくなってしまうのは容易に想像できると思います。
せっかくsketchやphotoshopでデザインしても、ここがビシッと揃わないのは本当に嫌ですよね。。。

なので私は、基本的に

「幅のみ可変、それ以外は固定」

という考え方を推奨します。

グリッドリストUIを作る

「幅のみ可変、それ以外は固定」を実証するために、例えば以下のようなUIを実装してみようと思います。
image.png

まず、全体的なHTMLとCSSは以下の通りです。

html
<ul class="productsList">
  <li class="productsList__item">
    <a href="#" class="productsList__itemLink">
      <div class="productCard">
        <p class="productCard__thumbnail"><img src="https://dummyimage.com/200x200" class="productCard__image"></p>
        <p class="productCard__title">タイトル1</p>
        <p class="productCard__date">2019/01/01</p>
      </div>
    </a>
  </li>
  <li class="productsList__item">
    <a href="#" class="productsList__itemLink">
      <div class="productCard">
        <p class="productCard__thumbnail"><img src="https://dummyimage.com/200x200" class="productCard__image"></p>
        <p class="productCard__title">タイトル2</p>
        <p class="productCard__date">2019/01/02</p>
      </div>
    </a>
  </li>
  <li class="productsList__item">
    <a href="#" class="productsList__itemLink">
      <div class="productCard">
        <p class="productCard__thumbnail"><img src="https://dummyimage.com/200x200" class="productCard__image"></p>
        <p class="productCard__title">タイトル3</p>
        <p class="productCard__date">2019/01/03</p>
      </div>
    </a>
  </li>
  <li class="productsList__item">
    <a href="#" class="productsList__itemLink">
      <div class="productCard">
        <p class="productCard__thumbnail"><img src="https://dummyimage.com/200x200" class="productCard__image"></p>
        <p class="productCard__title">タイトル4</p>
        <p class="productCard__date">2019/01/04</p>
      </div>
    </a>
  </li>
</ul>
css
.productCard {
  border: 1px solid #eaeaea;
  padding: 15px;
}

.productCard .productCard__thumbnail {
  text-align: center;
}

.productCard .productCard__image {
  width: auto;
  max-width: 100%;
  height: auto;
}

.productCard .productCard__title {
  margin-top: 10px;
}

.productCard .productCard__date {
  margin-top: 3px;
  font-size: 11px;
  color: #808080;
}

.productsList {
  display: flex;
  flex-wrap: wrap;
  margin-top: -10px;
  margin-left: -10px;
}

.productsList .productsList__item {
  flex: 1 1 auto;
  min-width: 33.33%;
  max-width: 33.33%;
}

.productsList .productsList__itemLink {
  display: block;
  margin-top: 10px;
  margin-left: 10px;
  color: inherit;
  text-decoration: none;
}

まず、一個一個のカード部分をproductCardというblockにしています。
そして、その全体を囲っているリスト部分をproductsListというblockにしています。

前の章の通り、productCardにもproductsListにもwidthが設定されていません。
横幅を決めているのは、各カード全体を囲んでいるproductsList__itemというところで決めています。
(今回は触れませんが、productsListの横幅も、さらに大きなblockに囲われて決まることになります。)

ここで設定している値は33.33%です。(widthではなくmin-widthmax-widthで指定しているのはdisplay: flexで作っているためです。)
これは、productsListの幅に対して33.33%(つまり3分割)という指定になります。

このように、blockに対して、何分割ずつ配置するかが明確な場合は%で指定します。

%で指定しておけば、中身のproductCard自体も可変で作られているため、ずっと3分割で表示されるようになります。
もし画面幅が広いときに4分割にしたければ、@mediaで適当な横幅のときにwidth: 25%にしてあげればOKというわけです。

また、各カードの上側と左側の余白を、productsList__itemLinkmarginで決めています。
このmarginの値はちゃんと%ではなくpxにしています。

こうすることで、余白の数値が確実になりますので、章の冒頭で述べたとおり、productsListの上下に来るblockの余白が合わせやすくなります。

さらに、productsListに書いているmargin-top: -10pxmargin-left: -10pxという指定ができるようになっています。
これは、productsList__itemLinkmarginを相殺しています。
なぜそうしているのかは、こちらも私の記事で恐縮ですが以下の記事を読んでみてください!結構便利です!
flex-boxを使わないでおしゃれなレスポンシブカラムリストを作る#基本はシンプルそして強引に

カラム構成を作る

「幅のみ可変、それ以外は固定」

という考えはもちろん大事なのですが、早速この言葉の反例をご紹介したいと思いますw
それが、タイトルの通りカラム構成を作るときです。
これを作るときは、pxを組み合わせて作ったほうがよいです。

以下の画像のような、左カラムは細くて右カラムは太いページなんかよく目にすると思います。
(有り合わせで作っているので、変なUIですみません。。)
image.png
これは、今回作ったproductCardinquiryLinkをカラム構成を決めるcolumnsというblockで囲んだ形になります。

html
<div class="columns columns--typeA">
  <div class="columns__item">
    <div class="productCard">
      <p class="productCard__thumbnail"><img src="https://dummyimage.com/200x200" class="productCard__image"></p>
      <p class="productCard__title">タイトル1タイトル1タイトル1タイトル1タイトル1</p>
      <p class="productCard__date">2019/01/01</p>
    </div>
  </div>
  <div class="columns__item">
    <div class="inquiryLink">
      <p class="inquiryLink__lead">
        以下からお問い合わせください!
      </p>
      <div class="inquiryLink__button">
        <p class="inquiryLink__buttonInner">
          <button class="button button--level1">お問い合わせ</button>
        </p>
      </div>
    </div>
  </div>
</div>
css
.columns {
  display: flex;
}

.columns.columns--typeA .columns__item:first-child {
  flex: 0 1 auto;
  margin-right: 20px;
  min-width: 200px;
  max-width: 200px;
}

.columns.columns--typeA .columns__item:first-child + .columns__item:last-child {
  flex: 1 1 auto;
}

productCardinquiryLinkのHTMLはコピペなのでCSSは載せていません。

columnsは、3カラムだったり、2カラムだけど右カラムが固定されるケースなどもあるはずなのでcolumns--typeAというmodifierを作って、それに合わせて中のcolumns__itemのスタイルが変えられるようにしてみました。

column__itemにスタイルをあてるためのセレクタの指定が今までよりもちょっと複雑ですが、
.columns.columns--typeA .columns__item:first-child左カラムで、
.columns.columns--typeA .columns__item:first-child + .columns__item:last-child右カラムです。

このような、左カラムが細くて右カラムが太いときのUIを作るときは、

狭い方のカラムを固定にしてしまう

とUIがきれいに見えます。

今回もflexを使っているので、min-widthmax-widthで固定しています。

おそらく左カラムがサブ情報になると思うのですが、左カラムを30%にして右カラムを70%で作ると、画面全体の横幅が広がっていったときに、「左カラムそんなに幅取る!?」という気持ちになると思いますw

左カラムにmax-widthを指定してももちろん良いのですが、今度画面幅が狭くなったときのためにmin-widthを指定したりしないといけなくなってきて、CSSの指定が複雑になってきます。

それなら、どの幅であっても左カラムは固定で取ってしまって、「画面幅が狭くなったら2カラムにするのをやめる」という記述を書いてしまったほうがシンプルにコードが書けます。

なので、狭い方の幅は固定で取ってしまうのをおすすめします。

最後に

いかがだったでしょうか?
最初に「小さいもの」から作るべしと述べてから始まったこの記事ですが、徐々に作るものが大きくなっていき、最後はカラムという大きいものコーディングになっているのに気づいていただけましたか!?笑

なので、小さいものからコーディングしていくのは案外できちゃうっぽいですね。
自分でも記事を書きながら「本当かしら?」と思いながら書いていましたが、大丈夫そうでしたw

実際、どこまでを「小さいもの」として、どこまでを「block」にすべきかを見極めるのは、結構難易度の高い作業だと思っています。
こういう作業は、やはりエンジニアの方が得意なのだと思います。(コンポーネント指向というやつですね。)

なので、非エンジニアの方は、見よう見まねで「小さいもの」を作ってみて、身近にエンジニアがいればアドバイスをもらうのも良いかもしれません。

ただし、「見た目の共通化」というのもとても重要なので、「コンポーネント指向」だけで共通化していくのもちょっと危険かもしれません。
非デザイナーの方は、デザイナーにデザインのコンテキストを聞いた上で共通化していくのも良いかもしれません。

結局のところ、今回私が書いたことは「Atomic Design」の入り口になるのかなーとなんとなく思いました。
まずはこの記事を試していただいて、そこからAtomic Designに触れていくのもアリな気がしました!
(もしAtomic Designをもう少し詳しく知りたい場合は私が書いた以下の記事も読んでみてください!)
Atomic Designってデザイナーには難しくない!?という話

FEという職は、デザインもエンジニアリングも両方分からないと勤まらない、結構難しい職種なのではないかと最近思い始めました。
このデザイナーとエンジニアの「中間」に位置する「FE」という職種の「持つべきスキルが何であるか」をどんどん解明できると、ものづくりがもっと楽しくなるかもですね!

そんな期待を込めて、この記事を締めます!ありがとうございました。
ご指摘やご相談等あれば、ぜひコメント欄にご記入ください〜

70
76
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
76