背景
CSSフレームワークは
CSS編集せず HTMLのみで意図されたWEBデザインを構築できる
CSS完成形の一つであり 必然的にリファクタリングされているため
CSS設計を考察するにあたり 命名規則など参考になるので比較してみた。
良記事
-
CSSフレームワーク30選!デザイン含めて一括総まとめ - 2019/8/12 - エンジニアの入り口
- 30にも及ぶ各フレームワークのビジュアル例も載っており分かりやすく素晴らしい!
-
CSSフレームワーク一覧【2018年12月投稿】- Qiita
- GitHub Starでの比較がありシンプルで説得力があります。
- 厳選!軽量で使いやすいCSSフレームワーク10選【2019年最新】- Web Design Trands
- 【2019年度版】ソフトウェア開発に欠かせない軽量で扱いやすい、人気CSSフレームワーク10選 - 2019/3/19 - SeleQt
- レスポンシブで軽量な20のCSSフレームワーク ( 海外記事 ) - 2019/1/8 - UX Milk
- より良いCSSを書くための様々なCSS設計まとめ - 2017/7/27 - UX Milk
- メンテナンス性に優れ、拡張性を備えたCSSを書くために メンテナブルCSS - 2016/4/21 - coliss
- CSSフレームワークを採用するべきかしないべきか、メリットやデメリット等の考察 - 2019/5/11 - high five create
利用ツール
比較
1. Bootstrap 4.3
参考サイト
- Official - https://getbootstrap.com/
- GitHub - SCSS
- GitHub - bootstrap.css - 9354 lines
- CDN - 4.3.1/css/bootstrap.min.css
- 日本語解説 - Bootstrap4 移行ガイド
特徴
- 最も有名で利用されているフレームワーク
- コード量が多く、動作が重い。しかし利用者が多いためドキュメントは豊富
- モバイルファーストで MediaQuery が指定されている。
- マルチクラス
- 利用時は
<div class="container"> <div class="row"> <div class="col">
3つの入れ子htmlから始まり、Flexboxでレイアウト構築している。
.container {
width: 100%;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto
}
@media (min-width:576px) { .container { max-width: 540px }}
@media (min-width:768px) { .container { max-width: 720px }}
@media (min-width:992px) { .container { max-width: 960px }}
@media (min-width:1200px) { .container { max-width: 1140px }}
.row {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px
}
.col-6 {
-ms-flex: 0 0 50%;
flex: 0 0 50%;
max-width: 50%
}
- デフォルトCSSに、12列グリッドを基準に4つのブレイクポイントに合わせ flex が細かく指定されておりレイアウトの変更が容易
- font-size / padding / margin / border-radius は殆ど rem 単位 ( classによって時々 em や px )
- width は % も px も rem も万遍なく使われている
- !important は個別指定class用に、詳細度を極力高くするため殆どファイル後方(6207行目以降)で設定されている。
.align-baseline { vertical-align: baseline!important }
.bg-primary { background-color: #007bff!important }
.border { border: 1px solid #dee2e6!important}
.d-none { display: none!important }
.d-inline { display: inline!important }
.d-inline-block { display: inline-block!important }
.d-block { display: block!important }
.d-flex { display: -ms-flexbox!important;
display: flex!important }
@media (min-width:576px) {
.d-sm-none { display: none!important }
.d-sm-inline { display: inline!important }
.d-sm-inline-block { display: inline-block!important }
.d-sm-block { display: block!important }
.d-sm-flex { display: -ms-flexbox!important;
display: flex!important }
}
-
"-" ハイフン1つ区切りのみ。"--" ハイフン2つや、"_" アンダーバーは使っていない
-
各コンポーネントは、ベースは layout と color が 同じクラス内で定められているが、詳細度(高)の個別指定classを当てることにより、カスタマイズが可能な設計となっている。
例 : button
.btn {
display: inline-block;
font-weight: 400;
color: #212529;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out, background-color .15s ease-in-out,
border-color .15s ease-in-out, box-shadow .15s ease-in-out }
.btn:hover {
color: #212529;
text-decoration: none }
.btn-lg {
padding: .5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: .3rem }
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff }
.btn-primary:hover {
color: #fff;
background-color: #0069d9;
border-color: #0062cc }
breakpoint
- breakpointは4つ ( 576px, 768px, 992px, 1200px )
各解像度に合わせたclass名がある ( sm, md, lg, xl )
.text-left { text-align: left!important }
@media (min-width:576px) { .text-sm-left { text-align: left!important }}
@media (min-width:768px) { .text-md-left { text-align: left!important }}
@media (min-width:992px) { .text-lg-left { text-align: left!important }}
@media (min-width:1200px){ .text-xl-left { text-align: left!important }}
color
rootで各colorが変数化されています。種類は14色。
何故か各classで変数が使われていない理由は不明。
:root {
--blue: #007bff; /* primary */
--indigo: #6610f2;
--purple: #6f42c1;
--pink: #e83e8c;
--red: #dc3545; /* danger */
--orange: #fd7e14;
--yellow: #ffc107;/* warning */
--green: #28a745; /* success */
--teal: #20c997;
--cyan: #17a2b8; /* info */
--white: #fff;
--gray: #6c757d; /* secondary */
--gray-dark: #343a40; /* dark */
--primary: #007bff;
--secondary: #6c757d;
--success: #28a745;
--info: #17a2b8;
--warning: #ffc107;
--danger: #dc3545;
--light: #f8f9fa;
--dark: #343a40;
}
.text-primary { color: #007bff!important }
その他 特徴的個別CSS
.border { border: 1px solid #dee2e6!important}
.border-top { border-top: 1px solid #dee2e6!important}
.border-top-0 { border-top: 0!important}
.border-primary { border-color: #007bff!important}
.rounded-sm { border-radius: .2rem!important}
.rounded { border-radius: .25rem!important}
.rounded-circle { border-radius: 50%!important}
.clearfix::after { display: block; clear: both; content: "" }
.flex-row { -ms-flex-direction: row!important;
flex-direction: row!important }
.flex-column { -ms-flex-direction: column!important;
flex-direction: column!important }
.flex-wrap { -ms-flex-wrap: wrap!important;
flex-wrap: wrap!important }
.flex-grow-1 { -ms-flex-positive: 1!important;
flex-grow: 1!important }
.justify-content-center { -ms-flex-pack: center!important;
justify-content: center!important }
.justify-content-between { -ms-flex-pack: justify!important;
justify-content: space-between!important }
.align-items-center { -ms-flex-align: center!important;
align-items: center!important }
.align-content-center { -ms-flex-line-pack: center!important;
align-content: center!important }
.align-self-center { -ms-flex-item-align: center!important;
align-self: center!important }
.float-left { float: left!important }
.float-right { float: right!important }
.position-static { position: static!important }
.position-relative { position: relative!important }
.position-absolute { position: absolute!important }
.position-fixed { position: fixed!important }
.position-sticky { position: -webkit-sticky!important;
position: sticky!important }
.fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030 }
.fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030 }
.w-50 { width: 50%!important }
.h-100 { height: 100%!important }
.mw-100 { max-width: 100%!important }
.mw-100 { max-width: 100%!important }
.mh-100 { max-height: 100%!important }
.min-vw-100 { min-width: 100vw!important }
.min-vh-100 { min-height: 100vh!important }
.vw-100 { width: 100vw!important }
.vh-100 { height: 100vh!important }
.m-0 { margin: 0!important}
.mt-1, .my-1 { margin-top: .25rem!important}
.mr-2, .mx-2 { margin-right: .5rem!important}
.mb-3, .my-3 { margin-bottom: 1rem!important}
.ml-4, .mx-4 { margin-left: 1.5rem!important}
.m-5 { margin: 3rem!important}
.p-0 { padding: 0!important}
.m-n3 { margin: -1rem!important}
.text-monospace { font-family: SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace!important }
.text-center { text-align: center!important}
.font-weight-bold { font-weight: 700!important}
.font-italic { font-style: italic!important}
.text-white { color: #fff!important}
.text-primary { color: #007bff!important}
a.text-primary:focus, a.text-primary:hover { color: #0056b3!important}
.text-body { color: #212529!important}
.text-black-50 { color: rgba(0, 0, 0, .5)!important}
.text-decoration-none { text-decoration: none!important}
.text-break { word-break: break-word!important;
overflow-wrap: break-word!important}
.text-reset { color: inherit!important}
2. Bulma
参考サイト
- Official - https://bulma.io
- Official - Modifiers Syntax
- GitHub - https://github.com/jgthms/bulma
- GitHub - bulma.css - 10599 lines
- CDN - 0.7.5/css/bulma.css
- GitHub - Sass
特徴
-
jQueryの拡張コンポーネント無し
-
IE11に一部非対応
-
Bootstrap と似ており、マルチクラスかつ、"_" アンダーバーを使わず "-" ハイフン1つで区切っている。
-
構成としては
- Columns : 全体 (縦)
- Basics / Sizes / responsiveness / Nesting / Gap / Options
- Layout : 列 (横)
- Container / Level / Media / Hero / Section / Footer / Tiles
- Components : アイテム
- Breadcrumb / Dropdown / Message / Navbar / Panel / Card / Menu / Modal / Pagination / Tabs
- Elements : 部品
- Box / Content / Icon / Notification / Table / Title / Button / Delete / Image / Progress bars / Tag
- Form : フォーム
- Textarea / Checkbox / File / Input / Select / Radio
- Modifiers : インライン的スタイル
- color / display / size
- Columns : 全体 (縦)
-
Modifiers クラス名 の接頭辞には is- か has- を付ける
.is-size-1 { font-size: 3rem !important;}
.is-size-7 { font-size: 0.75rem !important;}
.is-italic { font-style: italic !important;}
.is-block { display: block !important;}
.is-inline { display: inline !important;}
.is-relative { position: relative !important;}
.has-background-white { background-color: white !important; }
.has-text-black { color: #0a0a0a !important; }
breakpoint
各解像度に合わせた 9 種類 のclass名
- is-flex-mobile : ~ 768px
- is-flex-tablet-only : 769 - 1024px
- is-flex-touch : ~ 1023px
- is-flex-tablet : 769px ~
- is-flex-desktop-only : 1024 - 1215px
- is-flex-desktop : 1024px ~
- is-flex-widescreen-only : 1216 - 1407px
- is-flex-widescreen : 1216px ~
- is-flex-fullhd : 1408px ~
* v0.7.5 からブレイクポイントが上記に変更
.is-flex { display: flex !important;}
@media screen and (max-width: 768px) {
.is-flex-mobile { display: flex !important; }}
@media screen and (min-width: 769px), print {
.is-flex-tablet { display: flex !important; }}
layout
<div class="level"> <div class="level-item">
や
<div class="columns"> <div class="column">
などでFlexboxレイアウト可能。
Expo の作品を見ると .section / .container / .level クラスの利用が多い。
.section { padding: 3rem 1.5rem; }
@media screen and (min-width: 1024px) {
.section.is-medium { padding: 9rem 1.5rem; }
.section.is-large { padding: 18rem 1.5rem; }}
.container { flex-grow: 1; margin: 0 auto; position: relative; width: auto;}
@media screen and (min-width: 1024px) {
.container { max-width: 960px; }
.container.is-fluid { margin-left: 32px; margin-right: 32px; max-width: none; }}
@media screen and (max-width: 1215px) {
.container.is-widescreen { max-width: 1152px; }}
@media screen and (max-width: 1407px) {
.container.is-fullhd { max-width: 1344px; }}
@media screen and (min-width: 1216px) {
.container { max-width: 1152px; }}
@media screen and (min-width: 1408px) {
.container { max-width: 1344px; }}
.level { align-items: center; justify-content: space-between; }
.level.is-mobile { display: flex; }
@media screen and (min-width: 769px), print {
.level { display: flex; }
.level > .level-item:not(.is-narrow) { flex-grow: 1; }
}
.level-item { align-items: center; display: flex; flex-basis: auto; flex-grow: 0;
flex-shrink: 0; justify-content: center; }
.columns { margin-left: -0.75rem; margin-right: -0.75rem; margin-top: -0.75rem; }
.columns.is-mobile { display: flex; }
@media screen and (min-width: 769px), print {
.columns:not(.is-desktop) { display: flex; }}
@media screen and (min-width: 1024px) {
.columns.is-desktop { display: flex; }}
.column { display: block; flex-basis: 0; flex-grow: 1; flex-shrink: 1; padding: 0.75rem; }
<section class="section is-medium">
<div class="container">
<header class="section-header">
<div class="columns"> <!-- flex from 769px -->
<div class="column">1</div>
<div class="column">2</div>
</div>
<div class="columns is-mobile"> <!-- flex allways -->
<div class="column">1</div>
<div class="column">2</div>
</div>
<div class="columns is-desktop"> <!-- flex from 1024px -->
<div class="column">1</div>
<div class="column">2</div>
</div>
color
カラーは 19 種類
white / black / light / dark / primary / info / link / success / warning / danger / black-bis / black-ter / grey-darker / grey / grey-light / grey-lighter / white-ter / white-bis
.has-text-success { color: #23d160 !important; }
.has-background-success { background-color: #23d160 !important; }
.button.is-success { background-color: #23d160; border-color: transparent; color: #fff; }
.notification.is-success { background-color: #23d160; color: #fff; }
.table td.is-success, .table th.is-success { background-color: #23d160; border-color: #23d160; color: #fff; }
.is-success.input, .is-success.textarea { border-color: #23d160; }
.select.is-success select { border-color: #23d160; }
.file.is-success .file-cta { background-color: #23d160; border-color: transparent; color: #fff; }
.help.is-success { color: #23d160; }
.message.is-success { background-color: #f6fef9; }
.message.is-success .message-header { background-color: #23d160; color: #fff; }
.message.is-success .message-body { border-color: #23d160; color: #0e301a; }
.navbar.is-success { background-color: #23d160; color: #fff; }
.hero.is-success { background-color: #23d160; color: #fff; }
その他 特徴的個別CSS
.is-pulled-left { float: left !important; }
.is-pulled-right { float: right !important; }
.is-clipped { overflow: hidden !important; }
.is-size-1 { font-size: 3rem !important; }
.is-size-2 { font-size: 2.5rem !important; }
.is-size-3 { font-size: 2rem !important; }
.is-size-4 { font-size: 1.5rem !important; }
.is-size-5 { font-size: 1.25rem !important; }
.is-size-6 { font-size: 1rem !important; }
.is-size-7 { font-size: 0.75rem !important; }
.title.is-1 { font-size: 3rem; }
.title.is-2 { font-size: 2.5rem; }
.title.is-3 { font-size: 2rem; }
.title.is-4 { font-size: 1.5rem; }
.title.is-5 { font-size: 1.25rem; }
.title.is-6 { font-size: 1rem; }
.title.is-7 { font-size: 0.75rem; }
.has-text-centered { text-align: center !important; }
.is-italic { font-style: italic !important; }
.has-text-weight-bold { font-weight: 700 !important; }
.is-family-primary { font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica",
"Arial", sans-serif !important; }
.is-block { display: block !important; }
.is-flex { display: flex !important; }
.is-inline { display: inline !important; }
.is-inline-block { display: inline-block !important; }
.is-inline-flex { display: inline-flex !important; }
.is-hidden { display: none !important; }
.is-marginless { margin: 0 !important; }
.is-paddingless { padding: 0 !important; }
.button { background-color: white; border-color: #dbdbdb; border-width: 1px;
color: #363636; cursor: pointer; justify-content: center;
padding-bottom: calc(0.375em - 1px); padding-left: 0.75em; padding-right: 0.75em;
padding-top: calc(0.375em - 1px); text-align: center; white-space: nowrap; }
.button.is-small { border-radius: 2px; font-size: 0.75rem; }
.button.is-normal { font-size: 1rem; }
.button.is-medium { font-size: 1.25rem; }
.button.is-large { font-size: 1.5rem; }
.button.is-fullwidth { display: flex; width: 100%; }
.buttons { align-items: center; display: flex; flex-wrap: wrap; justify-content: flex-start; }
.buttons .button { margin-bottom: 0.5rem; }
.buttons:last-child { margin-bottom: -0.5rem; }
.buttons:not(:last-child) { margin-bottom: 1rem; }
.buttons.is-centered { justify-content: center; }
.buttons.is-right { justify-content: flex-end; }
.container { flex-grow: 1; margin: 0 auto; position: relative; width: auto; }
.content h1,.content h2,.content h3,.content h4,.content h5,.content h6 {
color: #363636; font-weight: 600; line-height: 1.125; }
.content h1 { font-size: 2em; margin-bottom: 0.5em; }
.content h1:not(:first-child) { margin-top: 1em; }
.content h2 { font-size: 1.75em; margin-bottom: 0.5714em; }
.content h2:not(:first-child) { margin-top: 1.1428em; }
.content ol { list-style-position: outside; margin-left: 2em; margin-top: 1em; }
.content ul { list-style: disc outside; margin-left: 2em; margin-top: 1em; }
.content ul ul { list-style-type: circle; margin-top: 0.5em; }
.content ul ul ul { list-style-type: square; }
.content dd { margin-left: 2em; }
.content.is-small { font-size: 0.75rem; }
.content.is-medium { font-size: 1.25rem; }
.content.is-large { font-size: 1.5rem; }
.image.is-square, .image.is-1by1 { padding-top: 100%; }
.image.is-3by2 { padding-top: 66.6666%; }
.image.is-16by9 { padding-top: 56.25%; }
.image.is-2by1 { padding-top: 50%; }
.image.is-3by1 { padding-top: 33.3333%; }
.image.is-2by3 { padding-top: 150%; }
.image.is-9by16 { padding-top: 177.7777%; }
.image.is-1by2 { padding-top: 200%; }
.image.is-1by3 { padding-top: 300%; }
.image.is-16x16 { height: 16px; width: 16px; }
.image.is-128x128 { height: 128px; width: 128px; }
.subtitle { color: #4a4a4a; font-size: 1.25rem; font-weight: 400; line-height: 1.25; }
.level { align-items: center; justify-content: space-between; }
.level-item { align-items: center; display: flex; flex-basis: auto;
flex-grow: 0; flex-shrink: 0; justify-content: center; }
@media screen and (min-width: 769px), print {
.level { display: flex; }
.level > .level-item:not(.is-narrow) { flex-grow: 1; }}
.columns.is-mobile > .column.is-narrow { flex: none; }
.columns.is-mobile > .column.is-full { flex: none; width: 100%; }
.columns.is-mobile > .column.is-three-quarters { flex: none; width: 75%; }
.columns.is-mobile > .column.is-9 { flex: none; width: 75%; }
.columns.is-mobile > .column.is-two-thirds { flex: none; width: 66.6666%; }
.columns.is-mobile > .column.is-8 { flex: none; width: 66.66667%; }
.columns.is-centered { justify-content: center; }
.columns.is-gapless { margin-left: 0; margin-right: 0; margin-top: 0; }
.columns.is-gapless > .column { margin: 0; padding: 0 !important; }
.section { padding: 3rem 1.5rem; }
@media screen and (min-width: 1024px) {
.section.is-medium { padding: 9rem 1.5rem; }
.section.is-large { padding: 18rem 1.5rem; }}
Foundation
参考サイト
- Docs - https://foundation.zurb.com/sites/docs/global.html
- CDN - https://cdn.jsdelivr.net/npm/foundation-sites@6.5.3/dist/css/foundation.css - 5577 lines
特徴
breakpoint
color
- Docs - Global Style
- GitHub _global.scss (カラー変数など)