SUN CREO

SUN CREO

Blog

Everylayout

Tech2025/05/12

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);
}