From dc6db80fa72286704849ef61ee0e5ccb5841cb09 Mon Sep 17 00:00:00 2001 From: Bradley Taunt Date: Tue, 2 Jul 2024 14:28:49 -0400 Subject: Conversion to barf for testing purposes --- _posts/2019-01-28-tabbed-content.md | 253 ------------------------------------ 1 file changed, 253 deletions(-) delete mode 100644 _posts/2019-01-28-tabbed-content.md (limited to '_posts/2019-01-28-tabbed-content.md') diff --git a/_posts/2019-01-28-tabbed-content.md b/_posts/2019-01-28-tabbed-content.md deleted file mode 100644 index b6a18fd..0000000 --- a/_posts/2019-01-28-tabbed-content.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -layout: post -title: "Tabbed Content Without JavaScript" -date: 2019-01-28 ---- - - -Creating tabs is a fairly trivial and common practice in web design, but many times it requires JavaScript to properly implement. Fortunately it *is* possible to create tabbed content with only using CSS. - -![Tabbed elements with only CSS](/public/images/tabbed-content.png) - -[Live CodePen Example](https://codepen.io/bradleytaunt/pen/abjmayw) - ---- - -
-

Sidenote:

-

While this method is semantic and accessible, you might consider using a pre-existing plugin for tabbed data.

-

This component tends to feel a little "stiff" compared to more fleshed out variations available. This pure CSS version is better suited as a fallback for when users have disabled JavaScript.

-
- -## The HTML - -The skeleton for this component is fairly basic - we just need the following structure: - -1. Parent element for each tab item -2. Default radio input -3. Label linked to corresponding input -4. Inner content associated with each tab item - ---- - - -
- - -
- - - - - - - - -
Content goes here
- -
- -
- - -Full HTML for reference: - - -
- -
- - -
Content goes here
-
- -
- - -
Content goes here
-
- -
- - -
Content goes here
-
- -
- - -## The CSS - -First, we need to set each `input`, `label` and inner content into their own parent containers: - - - /* Main parent that holds all contents */ - .tabs { - height: 100%; - min-height: 250px; - position: relative; - } - - /* Each tab items (includes heading & content) */ - .tab-item { - display: inline; - } - - -Next, we will hide the default `radio` input and design our labels to resemble a basic web tab element. The `z-index` property on the label is important for how we will be stacking our content on the z-axis (labels above inner content for example). - - - /* Hide the default radio inputs */ - .tab-input { - position: absolute; - visibility: hidden; - } - - /* The main tab headings */ - .tab-label { - background: white; - box-shadow: inset 0 -4px 4px rgba(0,0,0,0.02); - color: lightgrey; - cursor: pointer; - display: inline-block; - font-weight: 600; - margin: 0 5px 0 0; - padding: 10px 20px; - position: relative; - text-align: center; - z-index: 0; - } - - -The main inner content of each tab needs to have an `absolute` position set as it's default, since the one currently selected will switch to `relative` on mobile (more on that in a moment): - - - /* The inner tab content */ - .tab-content { - background: white; - bottom: 0; - box-shadow: 0 6px 8px rgba(0,0,0,0.02); - left: 0; - overflow: scroll; - padding: 20px; - position: absolute; - right: 0; - top: 50px; - z-index: 0; - } - - -The final step is just telling the browser to style both the `label` and inner content of the currently selected radio `input`: - - - /* Style the currently selected tab label */ - .tab-input:checked + .tab-label { - border: 1px solid #eee; - border-bottom: 0; - box-shadow: 0 -6px 8px rgba(0,0,0,0.02); - color: #268bd2; - z-index: 2; - } - - /* Show the currently selected tab content */ - .tab-input:checked ~ .tab-content { - border: 1px solid #eee; - z-index: 1; - } - - -It's as simple as that! For reference, here is the entire CSS file for easier access: - - - /* Main parent that holds all contents */ - .tabs { - height: 100%; - min-height: 250px; - position: relative; - } - - /* Each tab items (includes heading & content) */ - .tab-item { - display: inline; - } - - /* Hide the default radio inputs */ - .tab-input { - position: absolute; - visibility: hidden; - } - - /* The main tab headings */ - .tab-label { - background: white; - box-shadow: inset 0 -4px 4px rgba(0,0,0,0.02); - color: lightgrey; - cursor: pointer; - display: inline-block; - font-weight: 600; - margin: 0 5px 0 0; - padding: 10px 20px; - position: relative; - text-align: center; - z-index: 0; - } - - /* The inner tab content */ - .tab-content { - background: white; - bottom: 0; - box-shadow: 0 6px 8px rgba(0,0,0,0.02); - left: 0; - overflow: scroll; - padding: 20px; - position: absolute; - right: 0; - top: 50px; - z-index: 0; - } - - /* Style the currently selected tab label */ - .tab-input:checked + .tab-label { - border: 1px solid #eee; - border-bottom: 0; - box-shadow: 0 -6px 8px rgba(0,0,0,0.02); - color: #268bd2; - z-index: 2; - } - - /* Show the currently selected tab content */ - .tab-input:checked ~ .tab-content { - border: 1px solid #eee; - z-index: 1; - } - - -## Don't forget about mobile - -With only a few extra lines of CSS we can ensure that our custom tabs will stack on top of each other and look solid on mobile devices: - - - @media(max-width:38em) { - .tab-label { - display: block; - width: 100%; - } - .tab-content { - display: none; - } - .tab-input:checked ~ .tab-content { - bottom: auto; - display: block; - position: relative; - top: auto; - } - } - - -## One minor caveat - -Even though I'm a pretty big fan of implementing tabs this way, there is a small drawback: - -The `height` of the inner content doesn't grow dynamically since it defaults as `absolute`, so a `min-height` or `height` value is required on the parent element. This could become a problem in certain situations where you don't have the luxury of setting a static height. - -Other than that, enjoy building some JavaScript-free tabs! -- cgit v1.2.3-54-g00ecf