HTML
CSS
JavaScript
postcss
cssnext

cssnextから学ぶ次世代CSS

More than 1 year has passed since last update.

Kobito.VVEsP2.png

cssnextとは策定中のCSS仕様を先立って使えるようにするツールのことです。
ひとことで言うとCSS版Babelです。

CSSを変換する仕組みはPostCSSのプラグインとして有志によって作成されています。
cssnextはそのプラグインをまとめたプラグインパックと呼ばれるものです。
※古いブラウザに対応させるためのフォールバック機能を提供するプラグインも含んでいます。

本記事は策定中のCSSの知識をつけることが目的です:smile:

参考リンクなど

cssnext(PostCSS)の背景や使い方は先日記事を書いたので是非見てみてください
Step by Stepで始めるCSSモダン化(PostCSS)

playgroundでcssnextが実際にどのように変換するのかを試せます。

機能一覧

本記事で紹介する機能一覧を出すのに使ったcssnextのページです。
postcss-cssnext features

機能 プラグイン 仕様 Can I use
automatic vendor prefixes autoprefixer
custom properties & var() postcss-custom-properties http://www.w3.org/TR/css-variables/ CSS Variables (Custom Properties)
custom properties set & @apply postcss-apply https://tabatkins.github.io/specs/css-apply-rule
reduced calc() reduce-css-calc https://github.com/MoOx/reduce-css-calc#readme calc() as CSS unit value
custom media queries postcss-custom-media http://dev.w3.org/csswg/mediaqueries/#custom-mq
media queries ranges postcss-media-minmax http://dev.w3.org/csswg/mediaqueries/#mq-ranges
custom selectors postcss-custom-selectors http://dev.w3.org/csswg/css-extensions/#custom-selectors
nesting postcss-nesting http://tabatkins.github.io/specs/css-nesting/
color() function postcss-color-function http://dev.w3.org/csswg/css-color/#modifying-colors
hwb() function postcss-color-hwb http://dev.w3.org/csswg/css-color/#the-hwb-notation
gray() function postcss-color-gray http://dev.w3.org/csswg/css-color/#grays
#rrggbbaa colors postcss-color-hex-alpha http://dev.w3.org/csswg/css-color/#hex-notation
rgba function (rgb fallback) postcss-color-rgba-fallback http://www.w3.org/TR/css3-color/ CSS3 Colors
rebeccapurple color postcss-color-rebeccapurple http://dev.w3.org/csswg/css-color/#valdef-color-rebeccapurple
font-variant property postcss-font-variant http://dev.w3.org/csswg/css-fonts/#propdef-font-variant CSS font-variant-alternates
filter property pleeease-filters http://www.w3.org/TR/filter-effects/ CSS Filter Effects
initial value postcss-initial http://www.w3.org/TR/css3-values/#common-keywords CSS initial value
rem unit (px fallback) node-pixrem http://www.w3.org/TR/css3-values/#rem-unit rem (root em) units
:any-link pseudo-class postcss-pseudo-class-any-link http://dev.w3.org/csswg/selectors/#any-link-pseudo
:matches pseudo-class postcss-selector-matches http://dev.w3.org/csswg/selectors-4/#matches matches() DOM method
:not pseudo-class postcss-selector-not http://dev.w3.org/csswg/selectors-4/#negation selector list argument of :not()
:: pseudo syntax (: fallback) postcss-pseudoelements http://www.w3.org/TR/css3-selectors/#pseudo-elements ::selection CSS pseudo-element
overflow-wrap property (word-wrap fallback) postcss-replace-overflow-wrap https://drafts.csswg.org/css-text-3/#propdef-word-wrap CSS3 Overflow-wrap
attribute case insensitive postcss-attribute-case-insensitive https://www.w3.org/TR/selectors4/#attribute-case Case-insensitive CSS attribute selectors

※2016/09/07時点の機能一覧です。今後増減があると思います。
Can I useが空なのは見つけれなかった。

            

automatic vendor prefixes

ベンダープレフィックスを自動でつけてくれる機能です。

before
div {
  display:flex;
}
after
div {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
}

custom properties & var()

CSSに変数を導入します。

:root{}で定義して、var()で使います。

before
:root {
  --myColor: red;
}

div {
  background-color: var(--myColor)
}
after
div {
  background-color: red
}

custom properties set & @apply

プロパティごと定義を共通化するものです。

:root{}で定義して、@applyで使います。

before
:root {
  --myBackGroundColor: {
    background-color: red
  }
}

div {
  @apply --myBackGroundColor
}
after
div {
  background-color: red}

reduced calc()

数値計算を行います。

calc()の中に式を書きます。
式に単位が付いていてもOKです。

reduced。。。?一般的な「減らす」の意味じゃないですよね。

「整理して簡単な形に変える、まとめる」というしっくり来る説明を@nyoro_712さんから貰いました。ありがとうございます。

before
div {
  width: calc(10px + 20);
  min-width: calc(10 * 2px);
  height: calc(100px / 2);
  min-height: calc(10 + 20)px;
}
after
div {
  width: 30px;
  min-width: 20px;
  height: 50px;
  min-height: 30px;
}

custom media queries

メディアクエリの定義に名前をつけることができます。

@custom-media --変数名 〜で定義して@media (--変数名)で使用します。

iPadとかデバイス名指定できるの嬉しいですね。

before
@custom-media --iPad only screen (min-device-width: 768px) and (max-device-width: 1024px);

@media (--iPad) {
  /** css for ipad */
}

after
@media only screen (min-device-width: 768px) and (max-device-width: 1024px) {
  /** css for ipad */
}

media queries ranges

不等号を使ってメディアクエリを定義できます。

min, maxに変換してくれます。地味に嬉しい機能。

before
@media (width >= 500px) and (width < 1201px) {
  /* your styles */
}
after
@media (min-width: 500px) and (max-width: 1200px) {
  /* your styles */
}

custom selectors

セレクタを定義することができます。

@custom-selector :--変数名で定義しておいて:--変数名で使用
つなげる事もできます。
大量のセレクタが作れますね。

before
@custom-selector :--header h1, h2, h3, h4;
@custom-selector :--hover :hover;
@custom-selector :--hoge .hoge, .piyo, .fuga;

:--header:--hover:--hoge {
  /* styles */
}
after
h1:hover.hoge,
h2:hover.hoge,
h3:hover.hoge,
h4:hover.hoge,
h1:hover.piyo,
h2:hover.piyo,
h3:hover.piyo,
h4:hover.piyo,
h1:hover.fuga,
h2:hover.fuga,
h3:hover.fuga,
h4:hover.fuga {
  /* styles */
}

nesting

Sassでもおなじみのネスト記法が使えます。

before
a {
  color:red;

  & span {
    color: white;
  }
}
after
a {
  color:red
}
a span {
  color:white
}

color() function

color()関数で色を指定できます。

before
a {
  color: color(red blackness(50%));
}
a:hover {
  color: color(red blackness(50%) whiteness(25%));
}
after
a {
  color: rgb(128, 0, 0);
}
a:hover {
  color: rgb(128, 64, 64);
}

hwb() function

HWB形式で色指定が可能です。

before
body {
  color: hwb(90, 0%, 0%, 0.5);
}
after
body {
  color: rgba(128, 255, 0, 0.5);
}

HSLと似ているので比較

HSL

HSLは色相・彩度・明度(Hue, Saturation, Lightness)

HWB

HWBは色相・白味・黒味(Hue, Whiteness, Blackness)

HWBのが直感的にイメージしやすいと思います。

gray() function

灰色をあらわすための関数が追加。
rgb(),rgba()に変換します。

before
.foo {
  color: gray(85);
}

.bar {
  color: gray(10%, 50%);
}
after
.foo {
  color: rgb(85, 85, 85);
}

.bar {
  color: rgba(26, 26, 26, 0.5);
}

#rrggbbaa colors

透明度が追加され、#rrggbbaaの形式で定義できます。

#rgbaでもOK。

before
body {
  background: #9d9c;
  color: #001020ff;
}
after
body {
  background: rgba(153, 221, 153, 0.8);
  color: rgba(0, 16, 32, 1);
}

rgba function (rgb fallback)

rgba()に対応していないIE8のために#rgbに変換します。

これはplaygroundでは有効になっていないみたいです。
rgbaに対応してないのはもうIE8のみみたいなので外したのかも。

before
body {
  background: rgba(153, 221, 153, 0.8);
  border: solid 1px rgba(100,102,103,.3);
}
after
body {
  background: #99dd99;
  background: rgba(153, 221, 153, 0.8);
  border: solid 1px #646667;
  border: solid 1px rgba(100,102,103,.3);
}

rebeccapurple color

レベッカパープルという紫色をあらわす指定が追加されます。
rebeccapurpleがCSS 4 colorに提案された経緯に経緯がまとまっているので見てみてください:cry:

before
body {
  color: rebeccapurple;
}
after
body {
  color: rgb(102, 51, 153);
}

font-variant property

font-variant-xxxfont-feature-settingsの形に変換するらしい。
font-variantはなくなるってことなのかな。ちょっとだけ調べてみましたが良くわからなかった。。

before
h2 {
  font-variant-caps: small-caps;
}

table {
  font-variant-numeric: lining-nums;
}
after
h2 {
  -webkit-font-feature-settings: "c2sc";
          font-feature-settings: "c2sc";
  font-variant-caps: small-caps;
}

table {
  -webkit-font-feature-settings: "lnum";
          font-feature-settings: "lnum";
  font-variant-numeric: lining-nums;
}

filter property

filterに対応していないFirefox35未満でfilterを使えるようにする機能です。

オプションでoldIE:trueを指定すると古いIEでも使えそうな記述あり。

フィルタ自体は以下記事を参照
CSSフィルタことはじめ

before
.blur {
    filter:sepia(100%);
}
after
.blur {
    filter:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><filter id="filter"><feColorMatrix type="matrix" color-interpolation-filters="sRGB" values="0.393 0.769 0.189 0 0 0.349 0.686 0.168 0 0 0.272 0.534 0.131 0 0 0 0 0 1 0" /></filter></svg>#filter');
    -webkit-filter:sepia(100%);
            filter:sepia(100%);
}

initial value

スタイルをリセットする事が可能。

このall: initialは目玉機能だそうな。
どうもCSSに詳しい人には嬉しい機能らしい。

before
div {
  all: initial; /* use initial for ALL PROPERTIES in one shot */
}
after
div {
  -webkit-animation: none 0s ease 0s 1 normal none running;
          animation: none 0s ease 0s 1 normal none running;
  -webkit-backface-visibility: visible;
          backface-visibility: visible;
  background: transparent none repeat 0 0 / auto auto padding-box border-box scroll;
  border: medium none currentColor;
  border-collapse: separate;
  -o-border-image: none;
     border-image: none;
  border-radius: 0;
  border-spacing: 0;
  bottom: auto;
  box-shadow: none;
  box-sizing: content-box;
  caption-side: top;
  clear: none;
  clip: auto;
  color: #000;
  -webkit-columns: auto;
     -moz-columns: auto;
          columns: auto;
  -webkit-column-count: auto;
     -moz-column-count: auto;
          column-count: auto;
  -webkit-column-fill: balance;
     -moz-column-fill: balance;
          column-fill: balance;
  -webkit-column-gap: normal;
     -moz-column-gap: normal;
          column-gap: normal;
  -webkit-column-rule: medium none currentColor;
     -moz-column-rule: medium none currentColor;
          column-rule: medium none currentColor;
  -webkit-column-span: 1;
     -moz-column-span: 1;
          column-span: 1;
  -webkit-column-width: auto;
     -moz-column-width: auto;
          column-width: auto;
  content: normal;
  counter-increment: none;
  counter-reset: none;
  cursor: auto;
  direction: ltr;
  display: inline;
  empty-cells: show;
  float: none;
  font-family: serif;
  font-size: medium;
  font-style: normal;
  font-variant: normal;
  font-weight: normal;
  font-stretch: normal;
  line-height: normal;
  height: auto;
  -webkit-hyphens: none;
      -ms-hyphens: none;
          hyphens: none;
  left: auto;
  letter-spacing: normal;
  list-style: disc outside none;
  margin: 0;
  max-height: none;
  max-width: none;
  min-height: 0;
  min-width: 0;
  opacity: 1;
  orphans: 2;
  outline: medium none invert;
  overflow: visible;
  overflow-x: visible;
  overflow-y: visible;
  padding: 0;
  page-break-after: auto;
  page-break-before: auto;
  page-break-inside: auto;
  -webkit-perspective: none;
          perspective: none;
  -webkit-perspective-origin: 50% 50%;
          perspective-origin: 50% 50%;
  position: static;
  right: auto;
  -moz-tab-size: 8;
    -o-tab-size: 8;
       tab-size: 8;
  table-layout: auto;
  text-align: left;
  -moz-text-align-last: auto;
       text-align-last: auto;
  text-decoration: none;
  text-indent: 0;
  text-shadow: none;
  text-transform: none;
  top: auto;
  -webkit-transform: none;
          transform: none;
  -webkit-transform-origin: 50% 50% 0;
          transform-origin: 50% 50% 0;
  -webkit-transform-style: flat;
          transform-style: flat;
  -webkit-transition: none 0s ease 0s;
  transition: none 0s ease 0s;
  unicode-bidi: normal;
  vertical-align: baseline;
  visibility: visible;
  white-space: normal;
  widows: 2;
  width: auto;
  word-spacing: normal;
  z-index: auto;
  all: initial; /* use initial for ALL PROPERTIES in one shot */
}

rem unit (px fallback)

remに対応していないIE8のためにpxを追加してくれます。

rem自体は以下記事を参照
remってなに?

before
h1 {
  font-size: 1.5rem;
}
after
h1 {
  font-size: 24px;
  font-size: 1.5rem;
}

:any-link pseudo-class

:link, :visitedを1つの定義で可能にします。

before
nav :any-link {
  background-color: yellow;
}
after
nav :link,nav :visited {
  background-color: yellow;
}

:matches pseudo-class

セレクタをグルーピングできます。

before
p:matches(:first-child, .special) {
  color: red;
}
after
p:first-child, p.special {
  color: red;
}

:not pseudo-class

matchesの:not版です。

before
p:not(:first-child, .special) {
  color: red;
}
after
p:not(:first-child):not(.special) {
  color: red;
}

:: pseudo syntax (: fallback)

IE8のために:::に変換します。

IE8はもう死んだんだ。

before
a::before {
}
after
a:before {
}

overflow-wrap property (word-wrap fallback)

overflow-wrapword-wrapに変換します。

before
body {
  overflow-wrap: break-word;
}
after
body {
  word-wrap: break-word;
}

attribute case insensitive

大文字小文字を無視する属性セレクタのオプションiが追加。

before
[attr=abc i] {
  border-style: solid none;
}
after
[attr=abc],[attr=Abc],[attr=aBc],[attr=ABc],[attr=abC],[attr=AbC],[attr=aBC],[attr=ABC] {
  border-style: solid none;
}

あとがき

Sassだ、LESSだ、Stylusだ、Compassだ、cssnextだ、とCSS界隈もかなり混沌としている気がします:sweat:
いつかCSSだけで済む日が来るといいですね:smile: