pure cssで作るタブメニュー

input(表示/非表示切り替え) + label(タブ) + div(コンテンツ)
- input radio チェックの有無でコンテンツの表示非表示を切り替え
- input + label + divで1セット増減はセットごとに
親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて
つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
HTML
<div class="tab_01_wrap">
<input id="tab_01_1" type="radio" name="tab_group" checked="checked" />
<label for="tab_01_1">坊ちゃん</label>
<div class="tab-content"><p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて</p></div>
<input id="tab_02" type="radio" name="tab_group" /><label for="tab_02">徒然草</label>
<div class="tab-content"><p>つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。</p></div>
<input id="tab_03_1" type="radio" name="tab_group" /><label for="tab_03_1">Lorem ipsum</label>
<div class="tab-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
</div>
CSS
:root {
interpolate-size: allow-keywords;
}
.tab_01_wrap {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0 2px;
overflow: hidden;
outline: rgb(26, 160, 71) 1px solid;
@media (736px >= width) {
grid-template-columns: 1fr;
grid-template-rows: repeat(3, auto);
}
& label {
cursor: pointer;
font-weight: bold;
padding: 1em;
position: relative;
display: grid;
place-content: center;
background-color: #eee;
transition: all 0.3s ease-out;
@media (736px >= width) {
border-top: solid #fff 1px;
}
&::after {
content: "";
display: inline-block;
background-color: rgb(26, 160, 71);
height: 2px;
position: absolute;
bottom: 0;
opacity: 0;
translate: -100% 0;
transition: all ease-out 0.3s;
width: 100%;
}
@media (736px >= width) {
&::before {
content: "";
display: inline-block;
position: absolute;
top: 50%;
right: 1em;
background-color: #dad;
height: 12px;
width: 12px;
clip-path: polygon(0 45%, 45% 45%, 45% 0, 55% 0, 55% 45%, 100% 45%, 100% 55%, 55% 55%, 55% 100%, 45% 100%, 44% 55%, 0 55%);
translate: 0 -50%;
}
}
&:hover {
&::after {
opacity: 1;
translate: 0 0;
}
}
}
& input[type="radio"]:checked + label::after {
opacity: 1;
translate: 0 0;
}
& .tab-content {
height: 0;
opacity: 0;
transition:
height 0.2s ease-in-out,
opacity 0.4s ease-out;
width: 100%;
@media (737px < width) {
grid-area: 2 / 1 / 3 / 4;
}
& p {
filter: blur(5px);
padding: 1em;
transition: filter 0.3s ease-in-out;
}
}
& input[type="radio"] {
display: none;
&:checked {
& + label {
color: #009102;
background-color: #1aa04733;
@media (736px >= width) {
order: -2;
&::before {
content: none;
}
}
& + .tab-content {
height: auto;
opacity: 1;
order: 1;
@media (736px >= width) {
order: -1;
}
& p {
padding-block: 1em;
filter: blur(0);
}
}
}
}
}
}
input(IDで表示非表示切り替え) + nav label(タブ) + div(コンテンツ)
- input radio チェックの有無でコンテンツの表示非表示を切り替え
- 項目が増えた場合css側の:checked ~を増やす必要あり
親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて
つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
HTML
<div id="tab_03">
<div class="contents">
<input type="radio" name="tab-group" id="tab1-trigger" checked />
<input type="radio" name="tab-group" id="tab2-trigger" />
<input type="radio" name="tab-group" id="tab3-trigger" />
<nav class="tab-menu">
<label for="tab1-trigger">坊ちゃん</label>
<label for="tab2-trigger">徒然草</label>
<label for="tab3-trigger">Lorem ipsum</label>
</nav>
<div class="tab-content" id="content1"><p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて</p></div>
<div class="tab-content" id="content2"><p>つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。</p></div>
<div class="tab-content" id="content3"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
</div>
</div>
CSS
#tab_03 {
input[name="tab-group"] {
display: none;
}
& .tab-content {
display: none;
background-color: #fff;
& p {
padding: 1em;
}
}
& #tab1-trigger:checked ~ #content1,
& #tab2-trigger:checked ~ #content2,
& #tab3-trigger:checked ~ #content3 {
display: block;
}
& #tab1-trigger:checked ~ .tab-menu label[for="tab1-trigger"],
& #tab2-trigger:checked ~ .tab-menu label & #tab3-trigger:checked ~ .tab-menu label[for="tab3-trigger"] {
background-color: #fff;
color: #333;
}
& .tab-menu {
display: flex;
gap: 1px;
background-color: #ccc;
& label {
cursor: pointer;
padding: 1em 2em;
background-color: #2a8146;
color: #fff;
transition: all 0.3s ease-in-out;
&:hover {
filter: invert();
}
}
}
}
:target
- 初期値以外のタブが :target になったら、初期値を非表示に
- 初期値以外のコンテンツの呼び出し空タグを入れる必要あり
- urlにID(ハッシュ以降)が表示される
親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて
つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
HTML
<div id="tab_02">
<nav>
<a href="#tab_02_1">坊ちゃん</a>
<a href="#tab_02_2">徒然草</a>
<a href="#tab_02_3">Lorem ipsum</a>
</nav>
<div class="contents">
<div id="tab_02_2" class="target-anchor"></div>
<div id="tab_02_3" class="target-anchor"></div>
<div id="tab_02_1" class="tab-content"><p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて</p></div>
<div id="tab2-content" class="tab-content"><p>つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、 そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。</p></div>
<div id="tab3-content" class="tab-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
</div>
</div>
CSS
#tab_02 {
outline: 1px solid #333;
& nav {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2px;
& a {
color: #fff;
background-color: #333;
padding: 1em;
display: grid;
place-content: center;
transition: all 0.3s ease-in-out;
&:hover {
filter: invert();
}
&:active {
background-color: #2a8146;
color: #fff;
}
}
}
& .tab-content {
display: none;
background-color: #fff;
padding: 1em 2em;
}
& #tab_02_1 {
display: block;
}
& :target ~ #tab_02_1 {
display: none;
}
& #tab_02_2:target ~ #tab2-content,
& #tab_02_3:target ~ #tab3-content {
display: block;
}
/* アンカー用 場所を取らないようにする */
& .target-anchor {
position: absolute;
}
}

