夢は小さいほどいいと思っているんです。本気になれるから。

夢を持つことが大事なんじゃなく、本気になるのが大事。(糸井重里)

gulp初心者がなんとなく使えるようになるためのまとめ_2(gulpのプラグインを使ったタスクの書き方)

f:id:pbrsk:20170307222121j:plain

この記事の執筆時点のgulpのバージョンは3.9.1です。

gulpが持つ基本的な機能

gulpのタスクはgulpが用意しているAPI(機能)を使って書いていきます。

gulp.task

タスクを作る時に使う関数です。gulp.task('taskName', function)という形式で、タスク名と処理を指定します。

また、gulp.task('taskName', ['beforeTask1', 'beforeTask2', ...], function)というふうに、このタスクの前に実行させたいタスク(依存タスク)を指定することができます。
依存タスクは配列形式で複数指定することができますが、このとき指定されたタスクは並列に実行されます。実行の順番を保証する必要があるタスクを指定する場合には注意が必要です。

gulp.src

タスクで処理(編集)するファイルを指定する関数です。開発用のディレクトリを指定します。主に使うのは次のようなパターンかと。

指定対象表記例
ファイルを直接指定'css/main.css'
フォルダ名と拡張子で指定'css/*.css'
サブフォルダも含めて拡張子で指定'css/**/*.css'
除外したいファイルをフォルダ名と拡張子で指定'!css/exclude/*.css'

.pipe

処理を繋ぐために使う関数です。gulp.srcで作成したストリームを.pipe(function())で繋いでいきます。

gulp.dest

gulp.pipeを使って行ったストリーム(処理した結果)を、指定したフォルダに出力します。指定したフォルダが存在しない場合には自動的に作成します。

gulp.watch

ファイルの変更を監視する関数です。監視するファイルと、変更があったときに実行するタスク、もしくは関数を指定します。

gulp.watch('css/**/*.css', ['css']);

この例は、サブフォルダまで含めたcssフォルダ配下の.cssという拡張子を持つファイルを監視し、変更があればcssというタスクを実行します。

タスクの基本的な流れは、次のようになります。

  1. gulp.srcでファイルを読み込む
  2. .pipeで処理を繋ぐ
  3. gulp.destで出力する

これらの処理をgulp.taskの中に設定し、開発中などはgulp.watchでファイルの変更を監視して、設定したタスクを実行する、といった流れになります。

gulp自体が持っている機能は基本的にこれだけです。実際にファイルに対して行う処理はプラグインや関数の役割となっています。

プラグインを使ったタスクを使えるようにする手順

プラグインをインストールする

下記から目的に合うプラグインを探す。
http://gulpjs.com/plugins/

$ npm install --save-dev プラグイン名

プラグインを使えるように宣言する

gulpfile.jsの中でそのパッケージを使うことを明示的に宣言します。
宣言にはrequireメソッドを使います。書式は次のようになります。

var pluginName = require('plugin-name');

pluginNameの部分は好きな名前を付けられます。plugin-nameの部分はinstallした際に指定した名前を入れます。gulp-stylusを使う場合は次のようになります。

var gulp = require('gulp');
var stylus = require('gulp-stylus')

/**
 * 開発用のディレクトリを指定します。
 */
var src = {
  // 出力対象は`_`で始まっていない`.pug`ファイル。
  'html': ['src/**/*.pug', '!' + 'src/**/_*.pug'],
  // JSONファイルのディレクトリを変数化。
  'json': 'src/_data/',
  'css': 'src/**/*.css',
  'sass': ['src/**/*.scss', '!src/**/_*.scss'],
  'js': 'src/**/*.js',
  'stylus': 'src/styl/**/*.styl',
};

/**
 * 出力するディレクトリを指定します。
 */
var dest = {
  'root': 'dest/',
  'html': 'dest/'
};

gulp.task('stylus', function() {
  return gulp.src(src.stylus, {base: src.root})
    .pipe(stylus())
    .pipe(gulp.dest(dest.root + 'css/'));
});

このタスクはstylフォルダに入っている.stylファイルをコンパイルし、cssフォルダに出力します。
gulp.srcで処理する対象を指定し、.pipeでstylus()を実行しgulp.destに出力します。
このタスクを実行するには、次のコマンドを実行します。

$ gulp stylus

StylusのコンパイルをしたあとにCSSを結合・圧縮するように変更する

StylusのコンパイルのあとにCSSファイルの結合と圧縮を行うようにタスクを変えてみます。

  • 結合にはgulp-concat
  • 圧縮にはgulp-minify-css

を使います。

また、圧縮したCSSファイルの名前を変えたいのでgulp-renameも合わせて使います。

次のコマンドを実行してプラグインをインストールします。

$ npm i -D gulp-concat gulp-minify-css gulp-rename

*注:複数のパッケージをまとめてインストールする
npm installは空白区切りで複数のパッケージを指定して、まとめてインストールすることができます。

Stylusのコンパイル > CSSの結合 > CSSの圧縮 > ファイルのリネームという順番で実行するように書いてみます。

var gulp = require('gulp');
var stylus = require('gulp-stylus');
var concat = require('gulp-concat');
var minify = require('gulp-minify-css');
var rename = require('gulp-rename');

/**
 * 開発用のディレクトリを指定します。
 */
var src = {
  // 出力対象は`_`で始まっていない`.pug`ファイル。
  'html': ['src/**/*.pug', '!' + 'src/**/_*.pug'],
  // JSONファイルのディレクトリを変数化。
  'json': 'src/_data/',
  'css': 'src/**/*.css',
  'sass': ['src/**/*.scss', '!src/**/_*.scss'],
  'js': 'src/**/*.js',
  'stylus': 'src/styl/**/*.styl',
};

/**
 * 出力するディレクトリを指定します。
 */
var dest = {
  'root': 'dest/',
  'html': 'dest/'
};

gulp.task('stylus', function() {
  return gulp.src(src.stylus, {base: src.root})
    .pipe(stylus())
    .pipe(concat('all.css'))
    .pipe(minify())
    .pipe(rename({extname: '.min.css'}))
    .pipe(gulp.dest(dest.root + 'css/'));
});


次のコマンドを実行すると、Stylusがコンパイルされ、ファイルが分かれていたCSSを1ファイルにして、CSSの圧縮(minify)してファイルのリネーム(.min)される。

$ gulp stylus
  • Stylusのコンパイル
  • ファイルの結合
  • CSSの圧縮(minify)してファイルのリネーム(.min)

それぞれのタスクの後に、destに出力する下記のコマンドを差し込めば

.pipe(gulp.dest(dest.root + 'css/'))
  • Stylusのコンパイルされたファイル
  • ファイルの結合されたファイル
  • CSSの圧縮(minify)してファイルのリネーム(.min)されたファイル

が手に入ります。

全体的なgulpfileは下記

var gulp = require('gulp');
var stylus = require('gulp-stylus');
var concat = require('gulp-concat');
var minify = require('gulp-minify-css');
var rename = require('gulp-rename');

/**
 * 開発用のディレクトリを指定します。
 */
var src = {
  // 出力対象は`_`で始まっていない`.pug`ファイル。
  'html': ['src/**/*.pug', '!' + 'src/**/_*.pug'],
  // JSONファイルのディレクトリを変数化。
  'json': 'src/_data/',
  'css': 'src/**/*.css',
  'sass': ['src/**/*.scss', '!src/**/_*.scss'],
  'js': 'src/**/*.js',
  'stylus': 'src/styl/**/*.styl',
};

/**
 * 出力するディレクトリを指定します。
 */
var dest = {
  'root': 'dest/',
  'html': 'dest/'
};

gulp.task('stylus', function() {
  return gulp.src(src.stylus, {base: src.root})
    .pipe(stylus())
    .pipe(gulp.dest(dest.root + 'css/'))
    .pipe(concat('all.css'))
    .pipe(gulp.dest(dest.root + 'css/'))
    .pipe(minify())
    .pipe(rename({extname: '.min.css'}))
    .pipe(gulp.dest(dest.root + 'css/'));
});

ファイルを監視してタスクを実行(watchタスク)

Stylusのコンパイル > CSSの結合 > CSSの圧縮 > ファイルのリネームという順番で実行するタスクを書いてみましたが、更新(編集を保存する)のたび手作業でタスクを実行(gulp stylus)するのは手間だと思います。ファイルの更新があったときに、自動でタスクを実行してくれるようにしてみましょう。

gulpfileにgulp.watchを使ってファイルを監視するwatchタスクを追加します。

gulp.task('watch', function() {
  gulp.watch(src.stylus, ['stylus']);
});

コマンからwatchタスクを実行すると、監視待機状態になります。

$ gulp watch
[22:16:56] Using gulpfile ~/Dropbox/develop/gulp_test/gulpfile.js
[22:16:56] Starting 'watch'...
[22:16:56] Finished 'watch' after 12 ms

この状態でstylフォルダ以下の.stylファイルを変更して保存するとstylusタスクが実行されます。

gulp初心者がなんとなく使えるようになるためのまとめ_1

f:id:pbrsk:20170307222121j:plain

ある案件で、PHPなどのサーバーサイド言語を使わずに、ヘッダー・フッターなどの共通化ができるツールでコーディングできないか?ということで、教えてもらって使い始めたGulp。
そのお仕事もひと段落したので、なんとなく使ってわかってる気にならず、ここで改めて基礎からしっかり理解して、別の案件でも応用できるようになるために、まとめておきます。

この記事の執筆時点のgulpのバージョンは3.9.1です。

gulpとは

さまざまなファイルの処理作業を自動化してくれるツールです。
Node.jsのStreamAPIを利用してるところが特徴で、そこがGruntとの違いを作ってるみたい。

ファイルの処理をストリームで行う?

Gulpは「.pipe」という、jQueryでいう「メソッドチェーン」を使ってタスクを続けて書くため、見通しがよく記述できます。
Gruntは、JSON形式で書けますが、タスクの量が増えていくとネスト地獄に陥りやすいそうです。

Gulpによる自動化のメリット

  • 効率化
  • 共同開発においてムラが出にくい

sassのコンパイラーであるcompassのwatch機能を利用して変更を監視することもできますが、コンパイル後にブラウザの自動更新もしたいと思った場合、これらの作業もgulpのタスクにし、自動化することで作業を効率的できます。また、CSSやJSのコンパイルや画像の圧縮といった作業のほかにも、プロジェクトごとに合わせた作業を自動化してしまえば人的ミスも防げて成果物を均質化しやすくなります。

環境構築とgulpのインストール

まず、Node.jsをインストールする。

npmによるインストール

Node.jsではnpmによってパッケージのインストールを行います。gulp自体のインストールもですが、gulpで利用するプラグインもnpmコマンドでインストールします。
では、パッケージを管理のための準備をコマンドの例を交えて説明します。これをする事により、同じ環境をすぐに別の案件(プロジェクト)でも構築できるようになります。

まずは任意のところにディレクトリを作成し、ターミナルで作成したディレクトリへ移動します。そして、npmでパッケージをインストールする際には、次のコマンドを実行します。

$ npm install パッケージ名

実行するとnode_modulesフォルダが作られ、そこにパッケージがインストールされます。

ローカルインストールとグローバルインストール

npmではパッケージをローカルとグローバルのどちらにインストールするか、選ぶことができます。ローカルにインストールしたパッケージは、そのプロジェクトのフォルダ内でのみ利用できます。グローバルにインストールした場合は、そのマシン上のどこからでも利用できるようになります。デフォルトでは、ローカルにパッケージがインストールされるようになっています。グローバルにインストールしたい場合には-gオプションを付け、次のように実行します。

$ npm install -g パッケージ名

例えば、gulpなどは、どこからでも使えるとありがたいと思うので、グローバルインストールしたほうがいいかも。
グローバルにインストールされたgulpは、ローカルにインストールしたgulpを実行するのが役割なので。

$ npm install gulp -g

Macユーザの場合はroot権限での実行を求められるのでsudo npm〜としてください。

プロジェクトごとに利用するパッケージの管理

npmにはインストールしたパッケージを管理する機能も用意されています。パッケージを管理するためにはまずpackage.jsonというファイルを作成する必要があります。
作り方は、例えば前の案件で使用したpackage.jsonファイルを、新たな案件で使用するディレクトリ内に直接コピペする方法でも使用可能です。
また、npm initというコマンドを実行すると、対話形式でプロジェクトの名前や、作成者などの情報を決めた上でpackage.jsonを書き出してくれます。
package.jsonJSONファイルとして解釈できる必要があるので、最低限{}が書かれている必要があります。

installコマンドのオプション

package.jsonでインストールするパッケージの管理をするにはnpm installを実行する際に「--save」または「--save-dev」というオプションを付けます。
「--save」は作成しているプログラム自体にそのパッケージが必要なときに付けます。
gulpやgulpで使うプラグインなど、開発時だけ必要となるものには「--save-dev」を付けるとよいでしょう。

「--save-dev」とつけることで、このパッケージを開発用パッケージとしてインストールすることができます。そして、package.jsonを見るとdevDependecesに記載されています。
package.jsonに記載されたパッケージは次回以降、npm installというコマンドを実行するだけでインストールすることができます。
package.jsonがあれば、いつでも必要なパッケージがすぐにインストールできます。

Gulpで開発をするなら、まずは、これがなくちゃ的なパッケージをすぐ用意してくれる、秘伝のpackage.jsonファイルだけコピペして
そのあと、npm installするといいと思います。

おまけ:npmコマンドにはショートカットがある

npmではinstallや「--save-dev」などを短く表記するためのショートカットが用意されています。
installはiと一文字で表記することができてnpm iと短縮できます。
「--save-dev」は-D、
「--save」は-Sと短縮できます。
合わせると以下のように短縮できて手間をかなり減らすことができます。

$ npm i -D パッケージ名
ていうか、まずnpmとは?

npmはnode.jsのpackageを管理するためのツールです。macOS でいうところのHomebrewみたいなやつです。
node.js自体はJavaScriptで作られたWebサーバーですが、タスクランナー的なツールもたくさんあります。

gulpのインストール

するために

package.jsonを作成する
  • npm init で質疑応答する感じで、package.jsonを作成する方法
  • 他の案件からのコピペ

がある。今回は、勉強のため、任意をディレクトリ内にnpm initしてpackage.jsonを作成した

できたpackage.jsonの中身が下記

{
  "name": "gulptest_for_study",
  "version": "1.0.0",
  "description": "studying_for_gulp",
  "main": "index.js",
  "scripts": {
    "test": "gulp"
  },
  "repository": {
    "type": "git",
    "url": "git"
  },
  "keywords": [
    "gulp",
    "pug"
  ],
  "author": "ryosuke_shimizu",
  "license": "MIT"
}
npmでgulpをインストールする

グローバルにgulpをインストールします。

$ npm install -g gulp

そして、

$ npm install --save-dev gulp

を実行すると、node_modulesファイルと、package.jsonのdevDependenciesの中に、
"gulp": "^3.9.1"という記述が追加されます。

package.json

{
  "name": "gulptest_for_study",
  "version": "1.0.0",
  "description": "studying_for_gulp",
  "main": "index.js",
  "scripts": {
    "test": "gulp"
  },
  "repository": {
    "type": "git",
    "url": "git"
  },
  "keywords": [
    "gulp",
    "pug"
  ],
  "author": "ryosuke_shimizu",
  "license": "MIT"
  "devDependencies": {
    "gulp": "^3.9.1"
  }
}

コマンド実行後、インストールが正しく完了していることを確認するために、次のコマンドを実行します。

shimizuryousuke-no-MacBook-Pro:gulp_test r.shimizu$ gulp -v
[18:32:50] CLI version 3.9.1
[18:32:50] Local version 3.9.1

コマンド実行後に上記のような結果がコンソールに表示されればインストール完了です。[ ]内は実行時の時間を表しています。

gulpのバージョン管理

glupのバージョンを固定せずにnpm installした際には、インストールするパッケージの最新のバージョンがインストールされます。これによってローカルとグローバルのgulpのバージョンに相違が出てしまうかもしれません。なので、グローバルにインストールしたパッケージは適宜アップデートする必要があります。

もしローカルとグローバルのバージョンの管理が面倒だと思う方は、npm runなどを使ってローカルにあるgulpを実行するように設定しておくとよいでしょう。

タスクを実行してみる

gulpのタスクはgulpfile.jsというファイルに書きます。

var gulp = require('gulp');

gulp.task('hello1',function() {
  console.log('hello gulp ryo!');
});

gulp.task('default',['hello1']);

gulp.taskに渡している第一引数hello1がタスク名です。helloはコマンドライン上に「hello gulp ryo!」と表示するだけのタスクです。
defaultタスクは、gulpコマンドを実行する際に、タスク名を指定しなかったときに実行される開発に使うタスクです。(実行タスク)
gulp.task('default', ['hello1']);とした場合、`hello1`タスクが実行されます。
上記コードの保存後、コマンドラインからgulpコマンドを実行して、次のような結果が得られれば成功です。

shimizuryousuke-no-MacBook-Pro:gulp_test r.shimizu$ gulp
[20:49:42] Using gulpfile ~/Dropbox/develop/gulp_test/gulpfile.js
[20:49:42] Starting 'hello1'...
hello gulp ryo!
[20:49:42] Finished 'hello1' after 109 μs
[20:49:42] Starting 'default'...
[20:49:42] Finished 'default' after 13 μs

HTMLのviewportについてわかりやすく書いてみた

この記事は下記URLにお引越ししました!

http://diet-dev.com/2017/05/23/html-viewport/

CSS | marginの相殺とは

http://magnusbenoni.com/content/images/2016/01/margin_collapsing.png

marginの相殺とは?

まず、marginの相殺とはなんなのか、(気取って)MDN の概要を見てみましょう。

ブロックの top と bottom のマージンは結合される(折り畳まれる (collapsed))ことがあり、結合されるマージンのうち大きなほうのサイズを持った一つのマージンになります。この動作は マージンの相殺 (margin collapsing) として知られています。

f:id:pbrsk:20160914151656j:plain

あんま、よくわかんないっすね。

では、噛み砕いて説明してみます。

marginには相殺(margin collapsing)と呼ばれる独特のルールがあり、
発生条件は

  • ブロックレベルの要素で、かつ
  • margin と margin の間に何も無い場合で、かつ
  • 上下のmargin同士が直接触れ合っている場合に

相殺が起きます。

この場合、どちらか幅の大きいmarginだけが残り、小さい方は相殺されます(反映されません)。
同じ幅なら片方だけのマージン幅になります。
繰り返しますが、相殺は「上下マージンだけ」「ブロックレベル要素だけ」の場合に起こります。

相殺が起こらないケース

いろいろな場合がありますので、主なものを見ていきましょう。

左右のマージンは相殺されません

https://gyazo.com/78a4f564ddac1930836c1231e03326af

上記を見てもわかるように、左右のマージンが相殺されるなら margin-left が10pxでも、margin-right が 20pxなので、margin-left 10pxは相殺されます。ですが、10pxにしたら横幅が増えるので、左右のマージンは相殺されないということがわかります。

親の要素に特定のCSSを適用することで、子の相殺が発生しません。

  • border (marginが指定されている方向)

https://gyazo.com/2dc700dc86c11900dbd086570b6c1dc3

  • padding (marginが指定されている方向)

https://gyazo.com/d48bb4b8307a06c00a0cbb95422b6291

  • overflow:hidden, scroll (auto, visibleは適用されない)

https://gyazo.com/81d764e868f06cd8f8ed419d30769c92
親要素に overflow: scroll を当てても同じ挙動をします。

  • position:absolute, fixed (relative, staticは適用されない)

https://gyazo.com/a4d81a1e75e5c52cd16b7727846a665f
(親要素に position:fixed を当てても同じ挙動をします。)

さらに上記以外にも、floatによって相殺が発生しない場合がたくさんあります。

margin と float の関係

marginとfloatは、密接な関係にありますので、合わせて見ていきましょう。

marginのかかっている要素に、floatを指定した場合

親、子に関わらずmarginを指定している要素に、floatを適用すると相殺をしなくなります。floatが指定されると、marginのautoは、必ず数値が0になります。

margin: auto;とfloatを指定した例
https://gyazo.com/44f0ebc42540b2883616bb59219d688e

  • 親か子のどちらかでもfloatを指定すると、親子での相殺が起こらない。
  • floatが指定されると、margin:auto; は絶対的に0になる。
  • 兄弟同士にfloatが指定されていると、相殺が起こらない。

floatを使用すると、その要素のmarginはpaddingのような挙動を行います。
https://gyazo.com/aa2814c3ac9f78256b5d5d3f28cfb8b5

marginのかかっている要素に、floatが隣接している場合

floatが親、子の要素にかかると相殺が発生しません。ただfloatが隣接しているだけなら、marginとfloatで相殺が発生します。以下はその基本的な条件です。

  • floatに隣接
  • 隣接している要素に、marginが指定されている
  • 隣接している要素に、floatが指定されていない

上の条件が全てではありません。様々な影響により、相殺が発生する場合としない場合があるので割愛します。

以下、marginとfloatの相殺の例です。

https://gyazo.com/d41cd8ccfa825faee383b5d0a3541d2e

float: left; にコメントアウトをすると、testクラスのmargin top: 96px;が効くようになります。

img のスタイルに float:left; をコメントアウトすると、floatが無くなるために、
testクラスのdivの margin-topの幅は、写真の底辺から、divまでの幅ということになります。

このfloatとmarginの相殺は、floatを解除するclearプロパティにも関係してきます。

clearは、floatを解除するものではない

「floatを解除する」とよく説明されるclearプロパティですが、clearは、marginの相殺を抑制し、floatの底辺に要素がつくように、margin-topの値を自動調整するような振る舞いを行います。
clear:none;の場合は、通常通りに振舞います。

以下、実例です。

https://gyazo.com/1653ffd61ecb9c43de7dc937b330836d

.clearにmargin-topに100pxも指定しています。本来なら、100pxの間隔が空くはずですが、float:leftを指定したimgの底辺にくっついてしまっています。

これはclearによる仕様です。clear:left;を指定したことによって、margin-topが自動調整されて、float:left;の指定された要素の後ろにつきます。
仮に、.clearにmargin-topに1000pxを指定しても、何も変わりません。

さらに、float:right;を指定したピンクの.rightの底辺(marginを含む)には、.clear-rightの上辺が重なっています。この場合、ピンクの.rightの上辺から底辺までのmargin-topを調整している訳ではなく、.clearから.rightの底辺までの距離で、margin-topを調整しています。

clearとmargin-topを同時に適用すると、clearプロパティが優先されるので気をつけて下さい。

相殺を見込んで シンプルな CSSを書けるようになれば、とっても便利ですので、ぜひいろんな事例を覚えましょう。

CSS3 の 要素 box-sizing: border-box; とは?

この記事は下記URLにお引越ししました!

http://diet-dev.com/2017/05/28/box-sizing/

::after ::before 擬似要素の基本から実際の使い方まで1から理解しよう

f:id:pbrsk:20160816152344p:plain

疑似要素ってありますよね。僕は技術書で初めて見ました。

最初見た時、「え、なんだ、これ?」って思いませんでしたか?

ですが覚えると、とっても便利なのでさっそく使いこなしましょう!

擬似要素とは

MDNのガイドラインには、下記のように書いてあります。

疑似要素 (英:Pseudo-elements) はセレクタに追加して記述するものですが、:after の様な、特別な状態を記述するだけのものではありません。疑似要素は、ドキュメントの特定のパーツをスタイル付けします。例えば ::first-line 疑似要素は、セレクタで指定された要素の最初の行だけを対象にします。

構文

selector:pseudo-element {
  property: value;
}

developer.mozilla.org

定義上は上記のようになります。平たく言うと
::before ::afterを使用すると、指定要素(divタグなど)の前後にテキストやアイコンを挿入することができ、HTMLコード上は存在させず擬似的にスタイルをあてることができます。
ということです。

beforeとafterの関係はなんとなくわかりますよね

  • ::before は擬似要素内の最初に配置され
  • ::after は擬似要素内の最後に配置されます

f:id:pbrsk:20160816165207p:plain:w500
画像引用:参考書籍 HTML5/CSS3モダンコーディング フロントエンドエンジニアが教える3つの本格レイアウト スタンダード・グリッド・シングルページレイアウトの作り方 p103

つまりは、こんな関係でしょうか。
f:id:pbrsk:20160816170111p:plain:w500

豆知識

CSS2までは「:before」のようにコロンが1つだったのですが、CSS3になってからは、擬似要素は「::before」というようにコロンを2個付けるようになりました。理由は、擬似要素と擬似クラスを区別するためです(擬似クラスは以前と同じく:は一つで記述します)。

では、擬似クラスとは?

例を示すとわかるかと思います。よく使われる疑似クラスは以下の3つですかね。

  • a:link{ }
  • a:hover{ }

最も有名なのが、おなじみの aタグ ではないでしょうか。

またnth-child(n)も覚えておくとなにかと便利ですね。これは、以前書いたnthとかも擬似クラスなので、見てみてください!
pbrsk.hatenablog.com

疑似要素で出来ることとは?

ざっくり言うと以下の3つです。

  • 前後に何かくっつける...(::before や ::after)
  • リストの装飾で特定行だけ指定できる...(::first-letterとか)
  • floatの解除(いわゆるclearfixですね)


2番目の、「リストの装飾で特定行だけ指定できる」に関しては、参考になるリンクがありますので、そちらをご確認ください。
wp.yat-net.com

3番目の、「floatの解除」に関しても、以前のブログをご確認ください。
pbrsk.hatenablog.com

ということで、今回は「前後に何かくっつける」だけを見てみましょう。

前後に何かくっつける

擬似要素を正しく理解し、使い方をマスターするためには多くの実例を自分で実装するのが一番だと思います。

また、疑似要素の種類は多くありますが、デザインで使えそうなモノは、まずは::beforeと::afterではないでしょうか。

そして、::beforeと::afterの場合、擬似要素を存在させるためには、CSSで擬似要素の中身を指定するcontentプロパティの指定が必要です。

ということで実例を見てみましょう。

:beforeと:afterで具体的にデザインできること

実装例1_文字を前後に入れる

before と after の基本的な使い方というのは、単純に、指定した場所の前後に好きな文字を挿入することです。まずは例としてこんな文章を用意しました。HTMLもただ単にpタグを入れているだけです。

See the Pen 20160816pseudo-elements_1 by r.shimizu (@r_shimizu) on CodePen.

まさに、これでしょ!?
f:id:pbrsk:20160816170111p:plain:w400

ちなみに、擬似要素で生成されたtextは、ホバーしてもtextとして認識されません。PCで見てる方は、code penのやつで試してみてください。
普通のtextとは違って文字として認識されないので、Googleからも認識されません。
重要なキーワードをここに入れてもSEO的には意味ないので、注意してくださいね。

とはいえ、擬似要素を使うメリットは装飾をCSSで出来るだけでなく、見た目を再現するためだけの空のdivなどHTMLの文章構造上は不要なタグを無くし、綺麗で見やすいHTMLを保つことができるというマークアップ的な利点があります。なので、装飾的なtextや画像やその他のデザインを追加したい場合に、擬似要素はもってこいなのです。

この擬似要素を利用して、前後に画像を入れることも可能です。
例はこのリンクをご覧ください
[CSS] 擬似要素「before」「after」の基本から使い方までを徹底紹介!! | ヨッセンス

便利な擬似要素 ::before と ::after ですが、できないこともあります。
1つは、画像の大きさを変更すること、
もう1つは、出現させた画像やテキストにaタグを付けてリンクを貼ることはできません。
あくまで実態のないモノという位置づけということですね。

実装例2_吹き出しを入れる

代表的なサンプルを実装してみましょう。

f:id:pbrsk:20160816184056p:plain

吹き出しの下の三角形は擬似要素で生成されています。

See the Pen 20160816pseudo-elements_2 by r.shimizu (@r_shimizu) on CodePen.

この青い部分が擬似要素で生成された部分です。

なぜ、borderで指定してるだけなのに三角形ができるのかわからなかったのですが、これを見て超勉強になりました。
liginc.co.jp

また、::before ::after擬似要素のdisplayプロパティのデフォルトはインラインです。なので、高さや幅を指定したい場合には、displayプロパティにblockやinline-blockの指定が必要です。

さいごに

疑似要素でできることは、画像を使ったりJavaScriptで実装してしまえばできてしまうので、ちゃんと理解する機会はそんなに無いかと思います。
ですが、理解さえしていれば効率的なコーディングができる場面もあると思いますので、この際に是非覚えておくといいかと思います。

JavaScriptの基本的な書き方 日付 / 時刻データを操作する Dateオブジェクト

Date オブジェクトを生成する

Dateオブジェクトの生成には必ずコンストラクタを経由する必要があります。Dateオブジェクトのコストラクタには以下の構文などがあります。

See the Pen 20160815DateObject by r.shimizu (@r_shimizu) on CodePen.


Date オブジェクトのメンバ

Date オブジェクトで利用可能なメンバは、下記のリンクをご確認ください。
developer.mozilla.org

以下のサンプルで、主要なメンバの挙動を確認してください。

See the Pen 20160815DateObject_2 by r.shimizu (@r_shimizu) on CodePen.


日付 / 時刻データを加算・減算する

Dateオブジェクトは、日付 / 時刻を直接、足したり、引いたりできません。計算したい場合は、下記の手順を踏む必要があります。

  • getXxxxメソッド現在の日付 / 時刻要素を取得しておく
  • 取得した値に加算 / 減算をする
  • さらにsetXxxxxメソッドに設定をし直す

具体的には下記のコードを見てみましょう。

See the Pen 20160815DateObject_3 by r.shimizu (@r_shimizu) on CodePen.


日付 / 時刻の差分を求める

もうひとつ、よくある処理として、日付や時刻の差を求めるような処理です。これもまた、Dateオブジェクトは直接機能を提供していないので、
以下のようなコードを記述する必要があります。

See the Pen 20160815DateObject_4 by r.shimizu (@r_shimizu) on CodePen.

経過ミリ秒を取得するのは getTimeメソッドです。ミリ秒のを日付に変換するために

ミリ秒 ÷ (1000 ミリ秒 × 60秒 × 60分 × 24時間)

という計算をしてました。決まり決まったコードとして覚えておきましょう。