20190829のCSSに関する記事は5件です。

inline要素の改行のスペースが気になったので対策を調べた

これはなに

inline要素内で改行するとスペースが入りこむので、見た目的に気になったりする

https://codepen.io/aokiken/pen/vYBLMyv

例えば、以下のような、文章の途中のリンクなどに困る

<p>
  お問い合わせは
  <a href="#">こちらから</a>
  お願いします
</p>

// 出力結果
// お問い合わせは こちらから お願いします

サンプルはあくまで例だが、前後の文章やaタグにclassやattributeなど、内容によっては1行で表現しづらい

vueのカスタムディレクティブを作って解決してみる

https://www.npmjs.com/package/vue-remove-whitespace

<div v-remove-whitespace>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>

// 出力結果
// 12345

その他の対応策

改行しなければスペースは入らない

<div>
    <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
</div>

閉じタグの>を改行ればスペースは入らない

<div>
  <span>1</span
  ><span>2</span
  ><span>3</span
  ><span>4</span
  ><span>5</span>
</div>

開始タグの<tag以下を改行ればスペースは入らない

<div>
  <span
    >1</span><span
    >2</span><span
    >3</span><span
    >4</span
    ><span
    >5</span>
</div>

コメントアウトを挟めばスペースは入らない

<div>
    <span>1</span><!--
--><span>2</span><!--
--><span>3</span><!--
--><span>4</span><!--
--><span>5</span>
</div>

jsで改行を取り除けばスペースはなくなる(カスタムディレクティブでも同様のことやってる)

<div id="js_remove_nl">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>
<script>
const removeWhiteSpaceDom = document.querySelector('#js_remove_nl')
removeNlDom.innerHTML = removeWhiteSpaceDom.innerHTML.replace(/\s*<("[^"]*"|'[^']*'|[^'">])*>\s*/g, match => match.trim())
</script>

cssでfont-sizeを0にすれば見た目上スペースはなくなる(コピペにスペースは入り込む)

<div class="remove_whitespace">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>
<style>
.remove_whitespace {
  font-size: 0;
}
.remove_whitespace > span {
  font-size: initial;
}
</style>

float: left(コピペにスペースは入り込む)

<div class='float_left'>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>
<style>
.float_left:after {
  content: "";
  display: block;
  clear: both;
}
.float_left > span {
  float: left;
}
</style>

display: flex(コピペに段落は入り込む)

<div class='flex'>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>
<style>
.flex {
  display: flex
}
</style>

余談

英語圏だと、単語の間にスペースが入るのが基本だから、問題視されないのかなーという

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

SPA向けのCSS設計 - COCSS

Component Oriented CSS

CSSをもっと便利に使うための努力

CSSの歴史は、言うまでもなく長いです。
テーブルレイアウトの時代から使われ、テンプレートエンジンの時代を経て、JSが定着した最近はフレームワークやライブラリーなどにテーマが移っています。

もはやウェブ開発者・ウェブデザイナーと言う概念から、FE・BE、細かい場合はマークアップエンジニアなど、専門的かつ細分化になっています。
CSSも、専門のエンジニアが活躍する場合もあるくらいです。

こういう流れとともに、CSSの構造に関しても様々な工夫が行われてきました。

代表的には下記の例があります。

  1. OOCSS
  2. BEM
  3. SMACSS
  4. FLOCSS
  5. RSCSS

各例の概念と、不便なところだけ軽く見てみます。
経験者の方は、共感する部分もあると思います。

既存の設計、これが不便だった

1. OOCSS

コンテナーとコンテンツで分けてコンテンツはコンテナーから独立している。
基本構造と見た目を分けて考える(再利用性向上)。

作業して不便だと思った点

  • コンテナーとコンテンツの基準が主観的。
  • コンテンツがまたコンテンツを持つ場合の判定が難しい。
  • クラス名が被ることが多い。

2. BEM

Block(基となる要素)、Element(Block内の子要素)、Modifier(変化した状態)に分けられる。

作業して不便だと思った点

  • BlockとElementの区分が主観的。
  • リファクタリングなどでElementがBlockに変わる場合に対応が難しい。
  • Modifierの選定基準が曖昧。
  • ある要素の変化を動作として見なす場合もある。
  • __--などを使って、クラス名が長くなる。

3. SMACSS

Base、Layout、Module、State、Themeに役割を分ける

作業して不便だと思った点

  • プレフィックスなどルールが増える。
  • 階層が増えると、クラス名も長くなる。

4. FLOCSS

Foundation、Layout、Objectで分けます。

作業して不便だと思った点

  • 小規模サイト・サービスでは運用が難しい(パーフォマンスが悪い)。
  • 徹底に守ると、とりあえずファイルが多くなる。
  • プレフィックスと__--などを併用して使うので、クラス名も長くなる。

5. RSCSS

Components、Elements、Variant、Layout、Helpersに役割を分ける

作業して不便だと思った点

Componentsは必ず2単語以上で組み合わせないといけない。
Componentsの中にComponentsが入る場合、Elementsの中にElementsが入る場合わかりづらい。
リファクタリングなどでElementsがComponentsに変わる場合に対応が難しい。

だったら、改善していこう

ファイル構造はシンプルに

概ね下記の4つに分けられます。

  • setting.css(sass)

リセットCSSの役割と、Sassなどだと変数やmixinなどを定義します。

  • style.css(sass)

ヘッダー、フッターなど全領域に渡るパーツで共通的に使うCSSを指定します。

  • font.css(sass)icon.css(sass)svg.css(sass)...

各目的に合わせて外部から持ってくるCSSです。
あまり触ることがないことと、運用の手間を減らすため、ルール外とします。

  • コンポネント内

コンポネント内で影響するCSSは、基本そのコンポネント内でScopeを限定して使います。

クラス名から始めよう

一番解消したいのは、クラス名の短縮と最適化です。
クラス名が長くなったり重複が発生しまうと

  • CSS設計時に構造がわかりにくくなる。
  • 作業時にパーフォマンスが悪い。
  • JSと連携する際に把握しづらい。
  • HTMLコード上で見づらい。

変化に強いかつ単純なルール

作業の大体は、修正や維持補修です。
新規事業の場合でも、何回も仕様は変わります。
やり直す度に構造を意識してしまうと、限った時間内に作業できなくなるので、大体の場合諦めます。
結果、あれでもこれでもない形でリリースされ、下記の二つでの一択です。

  • いいケース:CSSを整理するため、また時間をかけます。
  • 悪いケース:放置でしょう。
  • 最悪のケース:「今回これ使ったからダメだった。。。次回はあれ使おう!」になったら、救いの手は遠がる限りです。

なので、この3つに集中しました。
ついでにコンポネントと言う発想が、ヒントとなりました。

Component Oriented CSS

いよいよ本題に入ります。
CO-CSSと言う概念をご提案します。

・CSS命名規則だけでなく、SPAのコンポネント構造に合わせた概念です。
・リファクタリングに強いです。
・クラス名が極端的に短くなります。

簡単なVue製SPAアプリの構造を想定しましょう。

<template lang="pug">
  section
    div.search
      Routes#from-route
      Routes#to-route
      Calendar
      div.-number-panel
        span.icon.icon-checkin
        div.-number-selectors
          NumberSelector.-hotel
          NumberSelector.-adult
          NumberSelector.-child
          NumberSelector.-baby
      hr.transparent
      Button.-submit(button_text="検索")
</template>

航空券、ホテルを検索する基本的な画面です。
出発地・到着地の入力コンポネントRoutes、日程を決めるコンポネントCalendar、数を決めるコンポネントNumberSelector、パラメタやステータスを保存するコンポネントButtonで構成されています。

ルールはいたって簡単です。

画面(コンポネント)の最上位階層のクラス名

  • アルファベット小文字で始まる
  • 1つの単語で構成する(.date)
  • 2つ以上の単語で構成される場合は-で連結する(.date-today)

最上位以下の階層のクラス名

  • -から始まる
  • 2つ以上の単語で構成される場合は-で連結する

これで、各コンポネントの領域がHTMLソースでもわかりやすくなります。
コンテナーやコンテンツなど、主観的な概念を徹底に排除しました。
CSSの設計に終わらず、コードの構造もシンプルに反映できるので連携がしやすいです。
-は、Sassなどでも良い区切りになります。

構造と独立したパーツのクラス名

  • アルファベット小文字で始まる
  • 1つの単語で構成する(.transparent)
  • 2つ以上の単語で構成される場合は-で連結する(.icon-checkin)

単体に使うパーツは、コンポネントに拘束されないので、独立したクラス名を使います。icomoonなど外部のアイコンライブラリーを使う時に、他の設計だと、構造に合わせて名前を変えたりしないといけないですが、COCSSだとそのまま実装できるので、手軽に適用できます。

ID名

  • アルファベット小文字で始まる
  • 2つ以上の単語で構成される場合は-で連結する

IDは、CSSで拘束しないことを原則にしているので厳しい規則は決めてないです。
ただ、他のクラス名などと違和感がないかつクラス名と区分するくらいで決めます。
IDは関数内で変数名として再指定して使う場合が多いので、特にJSの命名規則に揃わなくてもいいはずです。
むしろ変数名と職別できるので間違いする可能性は低くなります。

変則的にコンポネントが追加された場合を考えてみましょう。
上記の場合では、部屋数や年齢別の人数を調整するため、NumberSelectorと言うコンポネントを追加しています。

<template lang="pug">
  div.number
    table
      tbody
        tr
          td.-title {{ title }}
          td
            button.-minus -
          td.-amount
            p {{ result }} {{ type }}
          td
            button.-plus +
    input
</template>

このコンポネントでも、最上位階層はアルファベットの小文字で始まっています。
なので、これが独立したコンポネントであることがコード上で明らかになります。

結論

いくら有名なルールでも、いくら人気があるルールでも、今の自分の作業環境に合ってなかったらむしろ作業に悪影響します。
少人数で速くルールを熟知して短期間に成果を出したいと思いましたら、試してみたはいかがでしょうか?

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

サイズがバラバラな画像をレスポンシブで縦横比を揃えて表示させる

やりたいこと

  • サイズがバラバラな複数枚の画像を表示サイズを合わせて表示したい。
  • レスポンシブで縦と横の比率も揃えたい。
  • 画像のトリミングは縦方向も横方向も中央部分が表示できれば良い。

CSS で画像をトリミングする方法

CSS で画像をトリミングするには…で思いつくのは2パターン。
ただしどちらも今回のやりたいことが達成できない:sob:

object-fit を使う方法

object-fit - CSS: カスケーディングスタイルシート | MDN

CSS の object-fit プロパティは、置換要素、例えば <img><video> などの中身を、コンテナーにどのようにはめ込むかを設定します。

今やりたいものだと以下のように書く。

img {
  object-fit: cover;
  width: 200px;
  height: 150px;
}

cover という値は、縦横比を維持したまま要素のボックスに収まるように拡大縮小されるとのこと(上記 MDN より)

  • 決められたサイズではみでた部分を非表示にはできる。
  • 縦も横もピクセル数で指定する必要があるのでレスポンシブにならない。

親要素で囲う方法

.image-trim {
  position: relative;
  overflow: hidden;
  padding-top: 60%; /* 比率 */
}
.image-trim img {
  width: 100%;

  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: auto;
  transform: translate(-50%, -50%);
}
  • 親要素で縦方向(高さ)を横方向(幅)の何パーセントと指定することでレスポンシブできる
  • 縦長画像はボックスいっぱいにできる。
  • ただし、横長画像は上下方向に余白ができてしまう。

こんな感じ(薄グレーの地が親要素のボックスのサイズです)
スクリーンショット 2019-08-30 5.28.29.png

解決方法は上記2パターンをかけ合わせ

こんな感じ。

.image-trim {
  position: relative;
  overflow: hidden;
  padding-top: 60%; /* 比率 */
}
.image-trim img {
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

サンプル

サンプルとしてサイズがばらばらな画像を用意してみた。

スクリーンショット 2019-08-29 16.53.27.png

(ありえないほどめちゃくちゃだ……)
しかし、縦長の画像も横長の画像も小さいサイズだってご覧のとおり!

スクリーンショット 2019-08-29 16.56.01.png

小さいサイズの画像も拡大されてガビガビに。
レスポンシブかどうかは以下の Codepen でブラウザのウインドウ幅を変えてみてください。

See the Pen responsive trimming image by Beco (@becolomochi) on CodePen.

なぜそうなるのか

よく考えてみれば簡単な話で、

  • img に object-fit:cover を指定し、縦横100%を指定することで親要素の大きさ依存でトリミングできる。
  • 親要素の大きさの指定がレスポンシブになっている。
  • 位置を絶対値指定することで枠内に収まる。

トリミング位置を変えたい場合は

「トリミング位置を中央じゃなくて他がいい!」というときは、 object-position で変えることができる。

object-position - CSS: カスケーディングスタイルシート | MDN

object-position: left top; /* 左上 */
object-position: 100px 50px; /* 横方向100px 縦方向50px */

初期値が 50% 50% ということで特に指定しなければ縦方向横方向ともに中央になる。

参考

解決の糸口になったCodepen (ありがとうございます…)
Responsive image with picturefill and object-fit

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

Djangoの入力フォームにCSSを適用する方法

はじめに

Djangoのtemplateで入力フォームを

{{ form.username }}

のように作る時、入力フォームにCSSを適用する方法が分からず、調べてみたのでまとめてみたいと思います。

入力フォームにCSSを適用したい

例えば、ユーザー登録をするフォームを作るために、views.pyでUserCreationFormをformという名前でtemplateに渡してフォームの画面を作るとします。
usernameを記入する欄を

{{ form.username }}

のように作ると、class名をつけることができず、CSSを適用することができません。

CSSを適用させる方法

CSSを適用するための方法を解説します。
まず、仮想環境で

$ pip install django-widgets-improved

というコマンドを実行します。

次に、プロジェクトのsettings.pyで

INSTALLED_APPS = [
    ...
    'widget_tweaks',
    ...
]

のように追加します。

そして、templateの最初の方に以下を追加します。

{% load widget_tweaks %}

そしたら、

{{ form.username|add_class:'class-name' }}

のように書くことでclass名を設定できます。
あとはCSSで自由に装飾してください。

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

Top画面の早く表示、頑張るぜ!!

pagespeed_insights.png

Top画面の表示速度が直帰率と関係が深いらしく、以下のサイト(ほとんどGoogle提供・方針)で現在会社で担当している開店ポータルのチェックを行ったところが思ったより点数及び速度がイマイチでした。

https://testmysite.withgoogle.com/intl/ja-jp
https://developers.google.com/speed/pagespeed/insights/

大きく対応するべき内容は以下の物

  • 画像の適切なサイズ、Format
  • レンダリングを妨げるリソースの除外
  • 使用していない CSS の遅延読み込み
  • テキスト圧縮の有効化
  • その他

一旦会社の運営しているサーバーなので、勝手に試すのも出来ないしテストサーバーはIP等の制限で確認出来ないので、以前から運営している個人サイトで試してみました。経験もない上家に帰って少しずつ進んだので相当時間がかかりましたが、insightsサイトで40位の点数が90位になりました。対応内容は以下の通りです。
complete.png

画像の適切なサイズ、Format
・個人のサイトは画像はあまり使用してないので対応なし

レンダリングを妨げるリソースの除外
・Critical CSSの分割
・CSSのpreload化(「https://github.com/filamentgroup/loadCSS」を利用)

使用していない CSS の遅延読み込み
・ChromeのCoverageで分析
・Chromeの拡張機能:CSS used(https://chrome.google.com/webstore/detail/css-used/cdopjfddjlonogibjahpnmjpoangjfff)を利用

テキスト圧縮の有効化
・ApacheのGzip
・Cloudflareの利用(Apacheの対応は要らなかった。CDN上でBrotliで圧縮されていた)

※ 「レンダリングを妨げるリソースの除外」部分が専門分野でもないので一番難しいかった。
※ 違う分野で面白く、やりがいがあった。

※ 結局、最終的にはサーバーのランクアップでした。
complete-02.png

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