Scrolling tabs HTML and CSS only
Solution 1
So this would probably be better done using JavaScript, but a solution does exist in CSS, if you're willing to allow certain constraints on widths and heights and where the scrollbar ends up.
The basic idea is to make the tabs themselves be inline-block
, and have their container have overflow-x: auto
. That will put a horizontal scrollbar on the container when the tabs get too big.
That said, that requires the container to have a fixed size, and you have to force the content to have a fixed size too if you're going to keep the content elements inside each of the tabs' div
s. I wouldn't want to build it this way if I could avoid it, but this is a pure HTML-and-CSS solution.
A runnable snippet, derived from your original, is below. I set the width on the container specifically to 300px
so you can see what the horizontal overflow looks like.
.tabs {
position: relative;
min-height: 200px;
clear: both;
margin: 0;
padding-top: 15px;
width: 300px;
white-space: nowrap;
overflow-x: auto;
}
.tab {
display: inline-block;
vertical-align: top;
}
.tab label {
background: #eee;
padding: 10px;
border: 1px solid #ccc;
margin-left: -1px;
cursor:pointer;
position: relative;
left: 1px;
}
.tab [type=radio] {
display: none;
}
.tab .content {
position: fixed;
white-space: normal;
top: 50px;
left: 0;
background: white;
height: 100px;
right: 0;
bottom: 0;
padding: 20px;
width: 266px;
border: 1px solid #ccc;
}
.tab [type=radio]:checked ~ label {
background: white;
border-bottom: 1px solid white;
z-index: 2;
}
.tab [type=radio]:checked ~ label ~ .content {
z-index: 1;
}
<div class="tabs">
<div class="tab">
<input name="tab-group-1" id="tab-1" type="radio"/>
<label for="tab-1">Tab One</label>
<div class="content">
Content 1
</div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-2" type="radio"/>
<label for="tab-2">Tab Two</label>
<div class="content"> Content 2 </div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-3" type="radio"/>
<label for="tab-3">Tab Three</label>
<div class="content"> Content 3 </div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-4" type="radio"/>
<label for="tab-4">Tab Four</label>
<div class="content"> Content 4 </div>
</div>
</div>
Update: Per request, here's a way to have the horizontal scrollbar sandwiched between the tabs and the content. Bear in mind that this is even hackier than the above solution, really abusing overflow and height control, but it's doable. Just don't try to put anything below the content divs, because that definitely won't work well.
.tabs {
position: relative;
clear: both;
margin: 0;
padding-top: 15px;
width: 300px;
height: 45px;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
}
.tab {
display: inline-block;
vertical-align: top;
}
.tab label {
background: #eee;
padding: 10px;
border: 1px solid #ccc;
margin-left: -1px;
cursor:pointer;
position: relative;
left: 1px;
}
.tab [type=radio] {
display: none;
}
.tab .content {
position: fixed;
white-space: normal;
top: 70px;
left: 0;
background: white;
height:100px;
right: 0;
bottom: 0;
padding: 20px;
width: 266px;
border: 1px solid #ccc;
}
.tab [type=radio]:checked ~ label {
background: white;
border-bottom: 1px solid white;
z-index: 2;
}
.tab [type=radio]:checked ~ label ~ .content {
z-index: 1;
}
<div class="tabs">
<div class="tab">
<input name="tab-group-1" id="tab-1" type="radio"/>
<label for="tab-1">Tab One</label>
<div class="content">
Content 1
</div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-2" type="radio"/>
<label for="tab-2">Tab Two</label>
<div class="content"> Content 2 </div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-3" type="radio"/>
<label for="tab-3">Tab Three</label>
<div class="content"> Content 3 </div>
</div>
<div class="tab">
<input name="tab-group-1" id="tab-4" type="radio"/>
<label for="tab-4">Tab Four</label>
<div class="content"> Content 4 </div>
</div>
</div>
Solution 2
This can be done by moving the labels into a separate div
and using the focus
hack to highlight the tabs. Here is a working JSFiddle.
<head>
<title>Test Page</title>
<style>
.wrapper
{
width:800px;
margin-left:auto;
margin-right:auto;
}
.tab-radio
{
display:none;
}
.tabs
{
font-size: 0;
margin: 0;
}
.labels
{
overflow-y: auto;
white-space: nowrap;
}
.labels .tab-label
{
background: #eee;
border: 1px solid #ccc;
display: inline-block;
font-size: 1rem;
left: 1px;
margin-left: -1px;
padding: 5px;
position: relative;
vertical-align: bottom;
}
.tabs .tab-panel
{
position: fixed;
display: inline-block;
overflow: hidden;
position: relative;
height: 0;
width: 0;
}
.tabs .tab-content
{
display: block;
float: left;
font-size: 1rem;
width: 100%;
white-space: normal;
}
span:focus
{
outline: none;
}
span:focus > .tab-label
{
background: white;
}
.tabs .tab [type="radio"]:checked ~ .tab-panel
{
display: inline;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="labels">
<span tabindex="0">
<label class="tab-label" for="tab-tab1">Tab Caption 1</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-0">Tab Caption 2</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-1">Tab Caption 3</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-2">Tab Caption 4</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-3">Tab Caption 5</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-4">Tab Caption 6</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-5">Tab Caption 7</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-6">Tab Caption 8</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-7">Tab Caption 9</label>
</span>
<span tabindex="0">
<label class="tab-label" for="tab-tab2-8">Tab Caption 10</label>
</span>
</div>
<div class="tabs">
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab1" name="tabs-main" checked>
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 1</h2>
<p>A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text. A long piece of text.</p>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-0" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 2</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-1" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 3</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-2" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 4</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-3" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 5</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-4" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 6</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-5" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 7</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-6" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 8</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-7" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 9</h2>
</div>
</div>
</div>
<div class="tab">
<input class="tab-radio" type="radio" id="tab-tab2-8" name="tabs-main">
<div class="tab-panel">
<div class="tab-content">
<h2>Tab 10</h2>
</div>
</div>
</div>
</div>
</div>
</body>
Related videos on Youtube
David Kris
Updated on June 04, 2022Comments
-
David Kris almost 2 years
I was wondering if there is anyway to create scrolling tabs without using JavaScript. I've been assigned a task to strictly use HTML and CSS, that's it. The code below is the best solution I could find to create tabs without using anything else besides HTML and CSS. I've found some code for scrolling tabs online, but again it uses JavaScript. So, is it possible to do scrolling tabs with just HTML and CSS? Anything helps, thanks!
.tabs {position: relative; min-height: 200px; clear: both; margin: 25px 0;} .tab {float: left;} .tab label {background: #eee; padding: 10px; border: 1px solid #ccc; margin-left: -1px; cursor:pointer; position: relative; left: 1px; } .tab [type=radio] {display: none;} .content {position: absolute; top: 28px; left: 0; background: white; height:100px; right: 0; bottom: 0; padding: 20px; border: 1px solid #ccc;} [type=radio]:checked ~ label {background: white; border-bottom: 1px solid white; z-index: 2;} [type=radio]:checked ~ label ~ .content {z-index: 1;}
<div class="tabs"> <div class="tab"> <input name="tab-group-1" id="tab-1" type="radio"/> <label for="tab-1">Tab One</label> <div class="content"> Content 1 </div> </div> <div class="tab"> <input name="tab-group-1" id="tab-2" type="radio"/> <label for="tab-2">Tab Two</label> <div class="content"> Content 2 </div> </div> </div>
-
David Kris about 7 yearsI found this for scrolling HTML and CSS only. Anyway to incorporate this to what I have? w3schools.com/howto/howto_css_menu_horizontal_scroll.asp
-
b2ok about 7 yearsIf it is what you look for, let use that.
-
David Kris about 7 yearsNot quite, I need tabs so different tab headings display different content in the box, but if I have too many tab headings the scroll bar pops up. That's a nav bar linked to different pages. It has the scrolling function I'm looking for but I couldn't find a way to use it in my code.
-
b2ok about 7 yearsWhat about drop-down, select option, option, etc? Maby is posible all tabs incorporate like options in select element?
-
David Kris about 7 yearsIs there anyway to have the scrollbar underneath the tab headings, but above the display box?
-
Sean Werkema about 7 yearsWell, yes, and I've updated the answer with a solution that does that (with no shortage of caveats to it), but we're getting into really hacky CSS territory here. I would not reasonably expect other markup on the page to play nicely around those tabs. But what you're asking is at least possible.
-
Dan Bray over 6 yearsIt should be
white-space: normal
for thecontent
class, instead ofwhite-space: wrap
. -
Sean Werkema over 6 yearsOh, good point, and I don't know how I missed that when I wrote my answer. I've updated it with the fix.
-
Wayne Barron almost 2 yearsI was using the code that Dan Bray provided in one post above but ran into some strange issues under Google Chrome in Windows 10. So, I looked back at this code, your second option here, and it works without the weird behavior.
-
Wayne Barron almost 2 yearsIt seems there is an issue with your code Dan, in Google Chrome on Windows 10, to where if you have a textarea embedded in the tab at a width larger than 30% would cause a scrollbar to appear at the bottom of the container.