ボム君.com

流行りの UI プレースホルダーを HTML と CSS で作る方法

最近は facebookinstagram などを中心に多くのアプリでも見るようになってきた、読み込み時に表示される UIプレースホルダー。(スケルトンデザインとも言うよう)

ページ読み込み時のユーザーの体感速度を高めるための一つとして有効な手段です。 そんな UI プレースホルダーを HTML と CSS のみで作成しました。

最終的にはこれを作ります

f:id:sottar:20170530003707g:plain

コードは github で確認できます。

GitHub - sottar/ui-placeholder

STEP1

まずは UIプレースホルダー を作成するための箱を作ります

f:id:sottar:20170530003738p:plain

HTML

<div class="placeholder-wrapper">
  <div class="placeholder-item">
  </div>
</div>

CSS

.placeholder-item {
  background: #fff;
  border: 1px solid;
  border-color: #e5e6e9 #dfe0e4 #d0d1d5;
  border-radius: 3px;
  padding: 15px;
  margin: 0 auto;
  max-width: 480px;
  min-height: 156px;
  box-sizing: border-box;
}

ui-placeholder/step1 at master · sottar/ui-placeholder · GitHub

STEP2

css の background で animation させる背景を設定します。 css3 のグラデーションを使い濃淡をつけます。

f:id:sottar:20170530003752p:plain

HTML

<div class="placeholder-wrapper">
  <div class="placeholder-item">
    <div class="animated-background">
    </div>
  </div>
</div>

CSS

...

.animated-background {
  background: #f6f7f8;
  background: linear-gradient(to right, #eee 8%, #ddd 18%, #eee 33%);
  background-size: 800px 104px;
  height: 135px;
  position: relative;
}

ui-placeholder/step2 at master · sottar/ui-placeholder · GitHub

STEP3

STEP2 で設定した背景を animation を使って動かします。

f:id:sottar:20170530003815g:plain

CSS

...

.animated-background {
  animation-duration: 1s;
  animation-fill-mode: forwards;
  animation-iteration-count: infinite;
  animation-name: placeHolderAnimation;
  animation-timing-function: linear;
  background: #f6f7f8;
  background: linear-gradient(to right, #eee 8%, #ddd 18%, #eee 33%);
  background-size: 800px 104px;
  height: 135px;
  position: relative;
}

@keyframes placeHolderAnimation{
  0% {
    background-position: -400px 0
  }
  100% {
    background-position: 400px 0
  }
}

animation の細かい設定方法は以下で確認してください。

CSS の @keyframe, animation 属性の使い方 - Live in the moment

ui-placeholder/step3 at master · sottar/ui-placeholder · GitHub

STEP4

コンポーネントではない部分(アニメーションさせたくない部分)を隠していくように div を配置していきます。 下の画像の黒い枠で囲まれているところに背景の白い div を配置していくイメージです。

f:id:sottar:20170530003839p:plain

HTML

  <div class="placeholder-wrapper">
    <div class="placeholder-item">
      <div class="animated-background">
        <div class="background-masker head-top"></div>
        <div class="background-masker head-left"></div>
        <div class="background-masker head-right"></div>
        <div class="background-masker head-bottom"></div>
      </div>
    </div>
  </div>

CSS

...

.background-masker {
  background: #fff;
  position: absolute;
}

.background-masker.head-top,
.background-masker.head-bottom {
  top: 0;
  left: 70px;
  right: 0;
  height: 5px;
}

.background-masker.head-bottom {
  top: 25px;
  height: 10px;
}

.background-masker.head-left,
.background-masker.head-right {
  top: 5px;
  left: 70px;
  height: 20px;
  width: 15px;
}

.background-masker.head-right {
  left: 325px;
  width: 123px;
}

ui-placeholder/step4 at master · sottar/ui-placeholder · GitHub

最終STEP

後はひたすら div の位置を調整しながら目的の形を作っていきます。

f:id:sottar:20170530003707g:plain

HTML

  <div class="placeholder-wrapper">
    <div class="placeholder-item">
      <div class="animated-background">
        <div class="background-masker head-top"></div>
        <div class="background-masker head-left"></div>
        <div class="background-masker head-right"></div>
        <div class="background-masker head-bottom"></div>
        <div class="background-masker subhead-left"></div>
        <div class="background-masker subhead-right"></div>
        <div class="background-masker subhead-bottom"></div>
        <div class="background-masker content-top"></div>
        <div class="background-masker content-first-end"></div>
        <div class="background-masker content-second-line"></div>
        <div class="background-masker content-second-end"></div>
        <div class="background-masker content-third-line"></div>
        <div class="background-masker content-third-end"></div>
      </div>
    </div>
  </div>

CSS

...

.background-masker.content-top,
.background-masker.content-first-end,
.background-masker.content-second-line,
.background-masker.content-third-line,
.background-masker.content-second-end,
.background-masker.content-third-end {
  top: 70px;
  left: 0;
  right: 0;
  height: 15px;
}

.background-masker.content-first-end {
  top: 85px;
  left: 380px;
  height: 12px;
}

.background-masker.content-second-line {
  top: 97px;
  height: 8px;
}

.background-masker.content-second-end {
  top: 105px;
  left: 320px;
  height: 10px;
}

.background-masker.content-third-line {
  top: 115px;
  height: 9px;
}

.background-masker.content-third-end {
  top: 124px;
  left: 440px;
  height: 11px;
}

その他

作り終わった後にアニメーションする部分の高さなどを変えたりしようとすると、一つ一つの div の位置を変更しないといけないので、とてもめんどくさいです。 まずは sketch や photoshop などでデザインカンプをつくって高さなどを決めてから実装に入ったほうが賢明です。

各 STEP ごとのコードは github で確認できます。

github.com

いい感じに画像をリサイズしてくれる React Component を作ってみた

こんな感じで画像の縦横比を変えずに指定したサイズにリサイズする React Component を作りました。

横長画像の場合 縦長画像の場合
f:id:sottar:20170521164609p:plain f:id:sottar:20170521164604p:plain

画像の長辺を枠に合わせ縦横比を変えずに画像全体が枠内に収まるようにリサイズするものです。

画像の縦横比を保ったままのリサイズは object-fitbackgound-size でも可能ですが、 IE で対応してなかったり背景画像でしか使用できないので自作しました

github.com

github の README にもありますが、使い方は簡単で画像のパスと width, height を指定するだけでリサイズ済みの画像を返してくれます。 また、画像取得できなかった場合(404を想定)用の画像パス noImageSrc や、画像に当てる CSS などを props で指定できるようにしてます。

プロダクトでも使用していて、いい感じで動いてくれてます。

よかったら使ってみてください。 要望とかバグとかいつでもお待ちしております。

npm の module も初めて公開しました。 このページを参考に思っていたよりも簡単に公開できました。

badge.fury.io

CSS の @keyframe, animation 属性の使い方

@keyframe を使ってCSSだけで背景画像を作成しました

animation と @keyframe を使用するとCSSで簡単にアニメーションが実装できます。
このサイトを作成する際に animation と @keyframe を使用したのでその使い方を紹介します。

Elastic | A collection of background image created by CSS only

@keyframeとは

詳しくはこちらに書かれていますが、簡単に説明すると CSS animation の流れの中間地点を制御することができます。

developer.mozilla.org

ダンブラウザには全て対応しており、IEも10以降には対応しています。

Can I use... Support tables for HTML5, CSS3, etc

使いかた例

.css {
  animation: spin 10s linear infinite;
}
@keyframes spin {
  0% {
    wigth: 50px;
    transform: rotate(0deg);
  }
  50% {
    wigth: 100px;
    transform: rotate(120deg);
  }
  100% {
    wigth: 200px;
    transform: rotate(360deg);
  }
}

css のanimation属性で指定したアニメーション名と@keyframesの識別子を合致させて使用します(上の例だとspin)
10s かけて 0% から 100% まで 識別子spin がアニメーションします。

オプション一覧

animation属性には以下のオプションをつけられます。
※()内はデフォルトの値

animation-name 必須(none)
アニメーション名を指定する

animation-duration 必須(0)
アニメーション一回分の時間の長さを指定する

animation-timing-function(ease)
アニメーションのタイミング・進行割合を指定する

animation-delay(0)
アニメーションがいつ始まるかを指定する

animation-iteration-count(1)
アニメーションの繰り返し回数を指定する
infiniteを指定すると無限に再生を繰り返す

animation-direction(normal)
アニメーションを交互に反転再生させるかどうかを指定する

animation-play-state(running)
アニメーションを一時停止したり、再開したりさせる
マウスオーバー時に動きを止めたい時に使用できます

animation-fill-mode(none)
アニメーションの実行前や実行後にどのようなスタイルを適用するかを設定する

これらのオプションと @keyframes 内のパーセントの値を駆使することで複雑なアニメーションも比較的簡単に実装できます。

  animation: spin 10s linear infinite;

この例だと
animation-name が spin
animation-duration が 10秒
animation-timing-function が linear
animation-iteration-count が infinite
それ以外がデフォルトの値になっています

背景画像に@keyframe, animationを使用するサンプルサイトを作成したので実際に動きを確認してみてください。

www.sottar.net

CSSだけでインタラクティブなボタンを作る

HTMLとCSSだけで作成したインタラクティブなボタンをまとめたサイトを作成しました。

HTMLとCSSのみで作れるボタン集 | CSS Buttons f:id:sottar:20161222172453p:plain

個人的に使いやすいと思ったものや面白いものをまとめています。 デザインやアニメーションは全てCSSのみで実装しているものです。

IEは10以降に対応しています。

使い方

使いたいボタンをクリックするとそのボタンのコードが表示されます。

表示されたコードをコピペするだけで使えるようになってます。

以下のスタイルをベースとして設定してあります。ボタンのサイズや色のなどは各自で変更をお願いします。

.button {
    display: block;
    width: 200px;
    height: 40px;
    text-align: center;
    text-decoration: none;
    line-height: 40px;
}
.button::before,
.button::after {
    position: absolute;
    z-index: -1;
    display: block;
    content: '';
}
.button,
.button::before,
.button::after {
    -webkit-transition: all 0.3s;
    transition: all 0.3s;
}

github.com

CSSだけで複雑な背景画像を作ってみる

CSS3で追加された線形グラデーション linear-gradient と円形グラデーション radial-gradient を使用すれば、さまざまなパターンを表現することが可能です。 これに background-size プロパティを組み合わせれば、CSSだけで背景画像を作成することができます。

CSS3をサポートするブラウザが増えてきている現在では、ほとんどのパターンがCSSだけで作成可能になっています。

今回は下記の背景画像を作成してみます。

  • pattern1 f:id:sottar:20161221115842p:plain
  • pattern2 f:id:sottar:20161221115905p:plain

まずはそれぞれの仕様についてです

linear-gradient

書式

linear-gradient(開始位置と角度, 開始色, 途中色, 終了色);

角度 (省略可能)

角度は deg を単位として指定します。 0deg を指定すると下から上への方向となります。正の数値は時計回りの回転を示します。 デフォルトは 180deg で、上から下への方向となります。

方向 (省略可能)

角度のかわりに方向をキーワードで指定できます。 キーワードとしては、 left, right, top, bottom の4つになります。 斜めの方向を示すには、 left top right bottom などと指定します。

最新仕様では必ず to をつけて記述します。

開始色 位置 / 終了色 位置

カラーコードやカラーネームで色を指定します。 開始色の位置を示す 0% 、終了色の位置を示す 100% は省略可能です。

開始色に位置を指定した場合は、その位置までは開始色がそのまま描画されます。 終了色に位置を指定した場合は、その位置からは終了色がそのまま描画されます。

経過色 / 位置 (複数指定可能)

開始色と終了色の間に経過色を入れる場合は、開始点からの距離を示す位置とともに指定します。

経過色の位置は単位を %px で指定しますが省略可能です。省略したときは両隣の色の中間に配置されます。

radial-gradient

書式

radial-gradient(形状 サイズ at <ポジション>, 色 位置 [, 色 位置]+ );

形状 (省略可能)

円を示す circle か、楕円を示す ellipse のいずれかを指定できます。 デフォルトは ellipse です。

ポジション (省略可能)

グラデーションを開始するポイントです。 pxや%での数値指定と、キーワード指定ができます。 キーワードは、left, right, top, bottom, center があります。 デフォルトは 'center' です。

サイズ (省略可能)

px% での数値指定と、キーワード指定ができます。 キーワードは以下の4つがあります。

キーワード 説明
closest-side 中心から最も近い辺に接するように外円が描かれます。
farthest-side 中心から最も遠い辺に接するように外円が描かれます。
closest-corner 中心から最も近い角の点を通るように外円が描かれます。
farthest-corner 中心から最も遠い角の点を通るように外円が描かれます。

デフォルトは farthest-corner です。

色 / 位置 (複数指定可能)

色はカラーコードやカラーネームで2色以上指定します。 位置はpxや%で数値指定します。

今回はこの linear-gradientradial-gradient を使用して背景画像を作成していきます。

それでは pattern 1 を作成します

コード

.pattern1 {
  background-color: #3cc;
  background-image:
    radial-gradient(rgba(255, 255, 255, 0.1) 40%, transparent 40%),
    radial-gradient(rgba(255, 255, 255, 0.1) 20%, transparent 20%);
  background-position: 0 0, 40px 40px;
  background-size: 80px 80px;
}

radial-gradient の一行目の方では40%の大きさの円をrgba(255, 255, 255, 0.1)色で表示し、40%以降は透明( ''' transparent ''' )になっています。そのため、円の周りは背景色である#3ccが表示されます。
2行目は1行目と同様に20%の円を作成しています。 background-position では 0, 0radial-gradient の1行目で作成した40%の円の位置を決めており、40px, 40pxで2行目の円の位置を決めています。

続いて pattern 2 を作成します

repeating-linear-gradient

上で紹介した radial-gradient を使用してもストライプを作成できるのですが、 repeating-linear-gradient を使うと簡単にストライプを作成できます。

repeating-linear-gradient(ストライプの角度, 色1 始点, 色1 終点, 色2 始点、色2 終点[, 色3 始点, 色3 終点, …])

第1引数にストライプの角度を指定し、その後はストライプを作るボーダーの色とその始点と終点を続けて指定していきます。それぞれの色の始点と終点は、グラデーションの開始位置からの距離を指定します。色は何色でも指定できます。色の指定が終わった所で、再び最初に指定した色からボーダーが繰り返し表示されます。

コード

.pattern2 {
  background-color: #e9d4b9;
  background-image: 
    repeating-linear-gradient(45deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 120px, rgba(11, 36, 45, 0.5) 120px, rgba(11, 36, 45, 0.5) 140px),
    repeating-linear-gradient(135deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 140px, rgba(11, 36, 45, 0.5) 140px, rgba(11, 36, 45, 0.5) 160px);
}

repeating-linear-gradientで色を複数指定することで複雑なストライプ柄も簡単に実装することができます。

サイト作成しました

色々なパターンを作成しまとめたサイトを作成しました。 よかったら見てみてください。

Elastic | A collection of background image created by CSS only

f:id:sottar:20161221131609p:plain

react で 「Warning: It looks like you're using a minified copy .....」のwarningを消す方法

warning内容

以下のwarningの消し方に結構詰まったので共有。

Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See https://fb.me/react-minification for more details.

webpackbrowserify を使っている場合だと、公式サイトに対応方法が書いてあるが、 grunt を使っていて、対処法が載っていなく困った。

その公式サイトはここ

facebook.github.io

要するにproduction 用のbuildをしろと言うことなので、 いろいろ調べた結果、grunt-env というプラグインをいれて設定すれば解決できた。

手順

1, grunt-envのインストール

npm install --save-dev grunt-env

2, gruntfile.js でタスクを読み込む

grunt.loadNpmTasks('grunt-env');

3, gruntfile.js に記述を追加

grunt.initConfig({

...

env: {
    production: {
        NODE_ENV: 'production'
    }
},

...

});

4, gruntfile.js でタスクを登録する

grunt.registerTask('default', ['env:production', 'browserify']);

browserifyのタスクの前に実行する必要がある。

これでgruntを動かし直したら production 用のビルドになり、warningが消えました。

webpack で react, scss のコンパイルと ESLint を設定する方法

webpackとは

http://webpack.github.io

webpackは依存関係のあるJSやCSSなどを、まとめてくれるビルドツールです。

webpackにはLoaderという仕組みがあり、ソースコードに適用する処理を柔軟に設定することができ、 そのLoaderを使うことで、scssやJSXなどで書かれたファイルを変換することができます。

ここでは、react (jsx) , scss のコンパイルと、javascriptの構文をチェックしてくれるツールの ESLint をwebpackで行えるように設定します。

構成

今回は、以下のようなディレクトリ構成を想定し、
src の中の react と scss ファイルをdestディレクトリ内に配置することを考えます。

src
 ├─ react
 └─ scss
dest
 ├─ js
 └─ css
package.json
node_modules
webpack.config.js

gitを使用する場合は、node_modules をバージョン管理の対象外にしたいため、
src や dest と同じ階層に.gitignore を作成し、下記を記載します。

// .gitignore
node_modules/

webpackのインストール

package.jsonの作成

まずはprojectのpackageを管理するためのファイルである、
package.json を作成するために以下のコマンドを実行します。

$ npm init -y

-y オプションは聞かれる質問に全て yes でファイルを作成するというものです。
今回は全てyesで問題ないため、このオプションを実行します。

webpackのインストール

次に今回ビルドツールとして使用する webpack をインストールします。

$ npm install -D webpack

-D オプションは開発時にのみ必要なライブラリをインストールしつつ、
packpage.json に依存関係を記述してくれるオプションです。

scssのコンパイル設定

続いて scss のコンパイルのための設定を行います。

パッケージのインストール

$ npm install -D style-loader css-loader sass-loader node-sass extract-text-webpack-plugin

scssのコンパイルcssファイルとして出力する場合には extract-text-webpack-plugin というプラグインが必要になります。

webpack.config.js でビルド設定を書く

まずはwebpackの内容を記述するファイル webpack.config.js を作成し、
タスクを書いていきます。

// webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: {
    common: './src/scss/common.scss' // コンパイル対象ファイルのpath
  },
  output: {
    path: './dest/css/', // コンパイル後に出力するpath
    filename: '[name].css' // [name] には entry の key の値が入る(今回では common )
  },
  module: {
    loaders: [
      { 
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader?minimize!sass-loader")
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('[name].css')
  ]
}

"css-loader?minimize!sass-loader"?minimizeを外すと
ビルド結果がminifyされてない形で生成されます。

コンパイル実行

これで src/scss/common.scss を作成し、

$ ./node_modules/.bin/webpack -w

を実行すれば dest/css/common.css にビルド結果が生成されます。

reactのコンパイル設定

続いて react (JSX) のコンパイルの設定を行います。

babelのインストール

babelを使ってjsxファイルをトランスパイルします。

$ npm install -D babel-core babel-loader babel-preset-es2015 babel-preset-react

「babel-xxxxxx」というプラグインが多いですが、
babel-preset-xxxxx は、es2015 や JSX を変換するためのプリセットが babel 本体と分離しているので、個別にインストールする必要があります。

reactのインストール

実際に react をインストールします。

$ npm install -S react react-dom

-S オプションは、アプリケーションに必要なライブラリを、 packpage.json に追加しつつインストールをします。

webpack.config.js でビルド設定を書く

上で書いた webpack.config.js に reac tのビルドタスクを追加していきます。

// webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = [{
  // ここから react のコンパイルタスク
  entry: {
    app: './src/react/index.jsx',
  },
  output: {
    path: './dest/js/',
    filename: '[name].js'
  },
  module: {
    loaders: [
      { // babelの対象ファイルの指定
        test: /\.(js|jsx)$/,
        loader: 'babel',
        exclude: /node_modules/, // node_modules配下のファイルは対象外にする
        query: {
          presets: ["es2015", "react"],
        }
      },
    ]
  },
},{
  // ここから scss のコンパイルタスク
  entry: {
    common: './src/scss/common.scss'
  },
  output: {
    path: './dest/css/',
    filename: '[name].css'
  },
  module: {
    loaders: [
      { 
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader?minimize!sass-loader")
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('[name].css')
  ]
}]

コンパイル実行

これで src/react/index.jsx を作成し、

$ ./node_modules/.bin/webpack -w

を実行すれば dest/js/ に js のビルド結果が、 dest/css/css のビルド結果が生成されます。

ESLintを導入する

ESLintの設定方法についてはこちらに書いてあるので、参考にしてください。

ReactでESLintを使う - Live in the moment

ここでは、ESLintの設定は完了していることを前提とし、
webpackでのビルド時にESLintを実行させる設定を行います。

ライブラリのインストール

まずはwebpackでESLintを使用するためのnpmのライブラリをインストールします

$ npm install -D eslint-loader

webpack.config.jsに記述

ESLintの組み込みもこれまでと同様に webppack.config.js 内に書いていきます。

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = [{
  entry: {
    app: './assets/javascripts/app.jsx',
  },
  output: {
    path: '../app/assets/javascripts/',
    filename: '[name].js',
  },
  // eslint の設定ファイルの読み込み
  eslint: {
    configFile: './.eslintrc.json',
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel',
        exclude: /node_modules/,
        query: {
          presets: ["es2015", "react"],
        }
      },
      // esLintの対象ファイルの指定
      {
        test: /\.(js|jsx)$/,
        loader: 'eslint',
        exclude: /node_modules/, // node_modules配下のファイルは対象外にする
      }
    ]
  },
},{
  .....

実行

実行コマンドはこれまでと同様、以下になります。

$ ./node_modules/.bin/webpack -w

Lintに引っかかった場合にはerrorログが表示されます。

サンプル

今回のサンプルはこちらにあります。参考にしてください。
GitHub - sottar/react_scss_compile_on_webpack_sample