Blog
Everylayout
github:https://github.com/ying3789/everylayout
common.css
* ,
*::before,
*::after{
box-sizing:border-box;
}
/* 例外)センターレイアウトではコンテンツ自身のサイズが重要になる。 */
.center-l {
box-sizing: content-box;
}
:root {
/* カスタムプロパティ */
--font-plain: Helvetica Neue,Helvetica,Arial,sans-serif;
--font-special: Barlow Condensed,Helvetica,sans-serif;
--font-mono: Menlo,Courier,Courier New,Andale Mono,monospace;
--color-dark: hsl(0,0%,0%);/*#050505;*/
--color-darkish: hsl(0,0%,25%);/* #404040; */
--color-lightish: hsl(0,0%,90%);/* #e6e6e6; */
--color-light: hsl(0,0%,98%);/* #fafafa; */
--color-mid: grey;
--ratio: 1.4;
--s-5: calc(var(--s0)/var(--ratio)/var(--ratio)/var(--ratio)/var(--ratio)/var(--ratio));
--s-4: calc(var(--s0)/var(--ratio)/var(--ratio)/var(--ratio)/var(--ratio));
--s-3: calc(var(--s0)/var(--ratio)/var(--ratio)/var(--ratio));
--s-2: calc(var(--s0)/var(--ratio)/var(--ratio));
--s-1: calc(var(--s0)/var(--ratio));
--s0: 1rem;
--s1: calc(var(--s0)*var(--ratio));
--s2: calc(var(--s0)*var(--ratio)*var(--ratio));
--s3: calc(var(--s0)*var(--ratio)*var(--ratio)*var(--ratio));
--s4: calc(var(--s0)*var(--ratio)*var(--ratio)*var(--ratio)*var(--ratio));
--s5: calc(var(--s0)*var(--ratio)*var(--ratio)*var(--ratio)*var(--ratio)*var(--ratio));
--measure: 65em;
/* 65ch;英語の場合は0の横幅のch。 */
--line-height: var(--ratio);
--line-height-small: calc(0.8*var(--ratio));
--border-thin: var(--s-5);
--border-thick: var(--s-2);
line-height: var(--ratio);
/* font-size: calc(.333vw + 1em); 最小値を確保できる*/
/* font-size:calc(1rem + 0.33vw); */
font-size: 62.5%;/* いつものやり方 */
font-family: var(--font-plain);
background-color: var(--color-light);
color: var(--color-dark);
}
body {
font-size: 1.6rem;
}
/* ↓ Backslash で colon をエスケープ */
.font-size\:base {
font-size: 1rem;
}
.font-size\:biggish {
font-size: 1.75rem;
}
.font-size\:big {
font-size: 2.25rem;
}
html,body,div,header,nav,main,footer {
max-width: none;
}
Stack
<div class="stack">
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
</div>
.stack {
/* フレックスコンテキスト */
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.stack > * {
/* 既存の垂直マージンを削除 */
margin-top: 0;
margin-bottom: 0;
}
.stack > * + * {
/* 連続する要素だけに上方向のマージンを適用 */
margin-top: var(--space, 1.5rem);
}
.stack-false {
margin-bottom: auto;
/* https://every-layout.dev/demos/stack-split/ の例のように、
高さの決まったCover要素がある時、後ろの要素がボックスの下部にまとめる */
}
Box
<div class="box">
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
</div>
<div class="box invert">
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
</div>
.box {
--color-light:hsl(0,0%,80%);/* #eee; */
--color-dark:hsl(0,0%,20%);/* #222; */
color:var(--color-dark);
background-color: var(--color-light);
padding: var(--s1);
border: var(--border-thin) solid;
/* 常に透明のアウトラインを適用することでハイコントラストモードに備える */
outline: var(--border-thin) transparent;
outline-offset: calc(var(--border-thin) * 1);
}
.box * {
/* ボックスの背景を変えた時に、
判読性を保つためにcolorの変更も必要になる。それを簡単に行う */
color:inherit;
}
.box.invert {
/* 暗い色は明るい色に、明るい色は黒井色に変わる */
color:var(--color-light);
background: var(--color-dark);
/* or グレースケールでは以下で実現できる(colorはhslで宣言) */
/* filter:invert(100%); */
}
Center
<div class="center">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla laborum illum vero quibusdam. Eos earum, ducimus eligendi cum, tempora tenetur at inventore unde dolore, laboriosam nisi consequuntur odio magnam accusamus!
<button>子要素がcenterのflexによって中央揃えになる</button>
</div>
.center {
max-width:60ch;
margin-left: auto;
margin-right: auto;
box-sizing: content-box;/* 60chを確保するため */
padding-left:var(--s1);
padding-right:var(--s1);
/* 内在的な中央揃え 子要素が幅にかかわらず中央揃えになる */
display: flex;
flex-direction: column;
align-items: center;
}
Cluster
<div class="cluster">
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
</div>
<p>↓外側はspace-between、内側はflex-start</p>
<div class="cluster space-between">
<p class="test">LOGO</p>
<div class="cluster">
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
<div class="test">子要素</div>
</div>
</div>
.cluster {
display: flex;
flex-wrap: wrap;
gap:var(--space,1rem);/* 1remはフォールバック値 */
background: pink;
justify-content: center;/* 主軸の位置揃え */
align-items: center;/* 交差軸の位置揃え */
}
.space-between{
justify-content: space-between;
}
.test {
padding: var(--s1);
background-color: rgb(255, 253, 152);
font-size: 3rem;
}
Sidebar
<div class="with-sidebar">
<div class="sidebar">
<img src="https://placehold.jp/350x150.png" alt="">
</div>
<div class="not-sidebar">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic repellendus ipsa rerum laborum, pariatur facilis sed quaerat, itaque adipisci est doloribus reprehenderit! Assumenda dolores quas illo ratione, doloribus amet mollitia.
</div>
</div>
<hr>
<div class="with-sidebar">
<div class="not-sidebar">
<input style="width:100%" type="text">
</div>
<div class="sidebar">
<button style="width:100%">search</button>
</div>
</div>
.with-sidebar {
display: flex;
flex-wrap: wrap;
/* gap: var(--gutter,var(--s1)); */
/* stretchがdefaultなので高さが揃う。flex-startにすれば高さは揃わない */
/* align-items: flex-start; */
}
.sidebar {
/* サイドバーたりうる幅 */
flex-basis: 20rem;
flex-grow:1;
background-color: pink;
}
.not-sidebar {
/* 0から伸長する */
flex-basis:0;
flex-grow:999;
/* 要素の幅が等しくなった場合に折り返す */
min-width:50%;
background: purple;
}
Switcher
<div class="switcher">
<div>子要素1(必要に応じてmax-width:100%をつける)</div>
<div>子要素2</div>
<div>子要素3</div>
<div>子要素4</div>
<!-- <div>子要素5</div>
<div>子要素6</div> -->
</div>
.switcher {
display: flex;
flex-wrap: wrap;
gap: var(--gutter,var(--s1));
/* レイアウトの分岐点となる幅 */
--threshold: 30rem;
}
.switcher > * {
/* 子要素の伸長を許可 */
flex-grow: 1;
/* ↓コンテナの現在の幅100% 指定された30remのブレイクポイント
コンテナがthresholdの30remより狭ければ正、ひろければ負の値。*999で非常に大きな正、負の値を生成する。
flex-basisでは負の値は無効のため無視され、0になる。 */
flex-basis: calc((var(--threshold) - 100%) * 999);
background-color: pink;
}
/* 他の兄弟要素の2倍になる */
.switcher > :nth-child(2) {
flex-grow:2;
background: purple;
}
/* 4つ以上の子要素が存在すれば垂直方向の配置に切り替え */
.switcher > :nth-last-child(n+5),
.switcher > :nth-last-child(n+5) ~ * {
flex-basis: 100%;
}
Cover
<div class="cover">
<p>headerコンテンツ</p>
<h1>テスト</h1>
<p>footerコンテンツ</p>
</div>
.cover {
--space: var(--s1);
display: flex;
flex-direction: column;
padding: var(--space);
/* ビューポートの高さを基準にして最小の高さを設定 */
min-height:100vh;
}
/* 各子要素に最小のmarginを設定 */
.cover > * {
margin-top: var(--space);
margin-bottom: var(--space);
}
/* 中央に配置したいコンテンツ */
.cover > h1 {
margin-top: auto;
margin-bottom: auto;
}
.cover > :first-child:not(h1) {
margin-top: 0;
}
.cover > :last-child:not(h1){
margin-bottom: 0;
}
Grid
<div class="grid">
<div>子要素1</div>
<div>子要素2</div>
<div>子要素3</div>
<div>子要素4</div>
</div>
.grid {
display: grid;
grid-gap: 1rem;
--minimum: 20ch;
}
@supports(width:min(var(--minimum),100%)){
.grid {
/* min()関数によって複数カラムになるように強化 */
grid-template-columns: repeat(auto-fit,minmax(min(var(--minimum),100%),1fr));
}
}
Frame
<div class="frame">
<img src="https://placehold.jp/350x150.png" alt="">
</div>
<p>↓original size</p>
<img src="https://placehold.jp/350x150.png" alt="">
img {
max-width: 100%;
}
.frame {
--n :9;/* 高さ */
--d :16;/* 幅 */
padding-bottom: calc(var(--n) / var(--d) * 100%);
position: relative;
}
.frame * {
overflow: hidden;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
/* クロップ */
.frame > img,
.frame > video {
width: 100%;
height: 100%;
object-fit: cover;
}
Reel
<div class="reel">
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
<div>子要素</div>
</div>
.reel {
/* 調整しやすくするためのカスタムプロパティ */
--space:1rem;
--color-light:#fff;
--color-dark:#000;
--reel-height:auto;
--item-width:25ch;
display: flex;
height:var(--reel-height);
/* ↓はみ出しの設定 水平方向のスクロールのみ */
overflow-x: auto;
overflow-y: hidden;
/* ↓firefox用 */
scrollbar-color: var(--color-light) var(--color-dark);
}
.reel::-webkit-scrollbar {
/*
↓代わりに、スクロールバーの高さを変数にすることもできる
*/
height: 1rem;
}
.reel::-webkit-scrollbar-track {
background-color: var(--color-dark);
}
.reel::-webkit-scrollbar-thumb {
background-color: var(--color-dark);
/* ↓線形グラデーションによって黒いバーの中に白いつまみを挿入する */
background-image:linear-gradient(
var(--color-dark) 0,
var(--color-dark) 0.25rem,
var(--color-light) 0.25rem,
var(--color-light) 0.75rem,
var(--color-dark) 0.75rem
);
}
.reel > * {
/*
↓デフォルトではflex-shrink:1が適応されているためwidthの宣言だけではうまく機能しない
*/
flex: 0 0 var(--item-width);
}
.reel > img {
/* ↓画像のリセット */
height: 100%;
flex-basis: auto;
width: auto;
}
.reel > * + * {
margin-left: var(--space);
}
.reel.overflowing:not(.no-bar) {
/* ↓スクロールバーがある場合にのみ適用(jsを参照) */
padding-bottom: var(--space);
}
/* ↓no-barクラスでスクロールバーを削除 */
.reel.no-bar {
scrollbar-width: none;
}
.reel.no-bar::-webkit-scrollbar {
display: none;
}
Imposter
<div style="position: relative;">
<p>スタティックなコンテンツ</p>
<div class="imposter">
<p>重ね合わされるコンテンツ</p>
</div>
</div>
.imposter {
/* ↓左上の角を中央に配置 styleでpositioningを上書きできる */
/* position: var(--positioning),absolute; */
position: absolute;
top: 50%;
left: 50%;
/* ↓要素の中央が位置指定コンテンツの中央になるように位置変更 */
transform: translate(-50%,-50%);
}
/* containを使用するとはみ出しに対応 */
.imposter.contain {
--margin: 0px;
/* ↓はみ出しをふせぐ/2remにより位置指定コンテナとの余白をつくる */
max-width: calc(100% - var(--margin) * 2);
max-height: calc(100% - var(--margin) * 2);
/* ↓スクロールバー */
overflow: auto;
}
Icon
<span class="with-icon">
<svg class="icon">
<use href="symbols.svg#telBtn-icon"></use>
</svg>
<span>close</span>
</span>
.icon {
height:0.75em;
height:1cap;
width: 0.75em;
width: 1cap;
}
.width-icon{
display: inline-block;
align-items: center;
}
.width-icon .icon {
margin-inline-end:var(--space,0.5em);
}