Last active
February 13, 2023 08:04
-
-
Save tairli/aecb41ffd3ffc0c08ba502636461fb97 to your computer and use it in GitHub Desktop.
Tabbed description code for Shopify. "Slice" your description with <H6> elements (which will serve as tab titles) and stop with <H5> element.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% comment %} | |
if combine_pretext is false, the text before the first <h6> will be shown above all tabs, otherwise added to the first tab | |
if stop_on_h5 is true, tabs parsing will stop on first H5 element and the rest will be shown below tabs. | |
What's inside H5 is discarded, but still put something meneningfull there, just in case you switch theme or alike. | |
No multiple H5 elements. | |
{% endcomment %} | |
{% assign combine_pretext = false %} | |
{% assign stop_on_h5 = true %} | |
{% assign description = tabbed-description | default: product.description | replace: ' data-mce-fragment="1"', '' %} | |
{% if description contains "<h6>" %} | |
{% assign tab_heads = '' %} | |
{% assign tab_texts = '' %} | |
{% assign pretext = '' %} | |
{% assign posttext = '' %} | |
{% if stop_on_h5 and description contains "<h5>" %} | |
{% assign posttext = description | split: "</h5>" | last %} | |
{% assign description = description | split: "<h5>" | first %} | |
{% endif %} | |
{% assign chunks = description | strip | split: "<h6>" %} | |
{% for c in chunks %} | |
{% if c contains "</h6>" %} | |
{% assign chunk = c | split: "</h6>" %} | |
{% assign tab_heads = tab_heads | append: ",," | append: chunk.first %} | |
{% assign tab_texts = tab_texts | append: ",," %} | |
{% if pretext != blank and combine_pretext %} | |
{% assign tab_texts = tab_texts | append: pretext | append: "<br>" %} | |
{% assign pretext = '' %} | |
{% endif %} | |
{% assign tab_texts = tab_texts | append: chunk.last %} | |
{% elsif forloop.first %} | |
{% assign pretext = c %} | |
{% endif %} | |
{% endfor %} | |
{% assign tab_heads = tab_heads | remove_first: ",," | split: ",," %} | |
{% assign tab_texts = tab_texts | remove_first: ",," | split: ",," %} | |
{% assign index = 1 %} | |
{% if pretext != blank and combine_pretext == false %} | |
<div class=pretext>{{ pretext }}</div> | |
{% endif %} | |
<div> | |
<ul class="tabs"> | |
{% for head in tab_heads %} | |
<li><a href="#tab-{{- index -}}">{{ head }}</a></li> | |
{% assign index = index | plus: 1 %} | |
{% endfor %} | |
</ul> | |
{% assign index = 1 %} | |
{% for text in tab_texts %} | |
<div id="tab-{{- index -}}">{{ text }}</div> | |
{% assign index = index | plus: 1 %} | |
{% endfor %} | |
</div> | |
{% if posttext != blank %} | |
<div class=posttext>{{ posttext }}</div> | |
{% endif %} | |
<script> | |
document.addEventListener( 'DOMContentLoaded', function () { | |
function findTabContent( link ){ | |
if( link && link.nodeName == "A" ){ | |
var contentID = link.attributes.href.value.replace('#',''); | |
return document.getElementById( contentID ); | |
} | |
else | |
return null; | |
} | |
function hide( element ){ | |
if( element ) | |
element.style.display="none"; | |
} | |
function show( element ){ | |
if( element ) | |
element.style.display=""; | |
} | |
function setActive( element ){ | |
if( element ){ | |
element.classList.add('active'); | |
var c = findTabContent( element ); | |
show(c); | |
} | |
} | |
var tabHeads = document.querySelectorAll('.tabs'); | |
tabHeads.forEach( function( tablist ){ | |
var links = document.querySelectorAll('.tabs a'), | |
tabs = document.querySelectorAll('.tabs li'); | |
if( links.length == 0 ) | |
return; | |
var active = links[0], | |
content = findTabContent( active ), | |
totalWidth = 0, currentMode; | |
setActive( active ); | |
links.forEach( function( el, index ){ | |
if( index > 0 ) | |
hide( findTabContent( el ) ); | |
}); | |
/* event listener for clicking tabs */ | |
tablist.addEventListener( 'click', function(e){ | |
var clicked = e.target; | |
if( clicked.nodeName !== "A" ) | |
return; | |
e.preventDefault(); | |
active.classList.remove('active'); | |
hide( content ); | |
active = clicked; | |
content = findTabContent( clicked ); | |
setActive( clicked ); | |
return false; | |
}); | |
function onResize( e ){ | |
if( e.type == 'load' ){ | |
/* how wide are all our tab headers together? calculate this once, on load */ | |
tabs.forEach( function( el, i ) { | |
totalWidth += el.offsetWidth ; | |
}); | |
} | |
/* will they fit on one line? check on every resize/rotate */ | |
if( tablist.clientWidth > totalWidth ){ | |
if( currentMode !== 'wide' ) { | |
tablist.classList.remove('vertical'); | |
currentMode = 'wide'; | |
} | |
} else{ | |
if( currentMode !== 'narrow' ) { | |
tablist.classList.add('vertical'); | |
currentMode = 'narrow'; | |
} | |
} | |
} | |
window.addEventListener( 'resize', onResize ); | |
window.addEventListener( 'load', onResize ); | |
}); | |
}); | |
</script> | |
<style> | |
ul.tabs { | |
border-bottom: 1px solid #DDDDDD; | |
display: block; | |
margin: 0 0 20px; | |
padding: 0; | |
} | |
ul.tabs li { | |
display: block; | |
float: left; | |
height: 30px; | |
margin-bottom: 0; | |
padding: 0; | |
width: auto; | |
} | |
ul.tabs li a { | |
-moz-border-bottom-colors: none; | |
-moz-border-image: none; | |
-moz-border-left-colors: none; | |
-moz-border-right-colors: none; | |
-moz-border-top-colors: none; | |
background: none repeat scroll 0 0 #F5F5F5; | |
border-color: #DDDDDD !important; | |
border-style: solid; | |
border-width: 1px 1px 0 1px; | |
display: block; | |
font-size: 13px; | |
height: 29px; | |
line-height: 30px; | |
margin: 0; | |
padding: 0 20px; | |
text-decoration: none; | |
width: auto; | |
color: #303030; | |
border-bottom:none !important; | |
} | |
ul.tabs li a.active { | |
background: none repeat scroll 0 0 #FFFFFF; | |
border-left-width: 1px; | |
border-top-left-radius: 2px; | |
border-top-right-radius: 2px; | |
color: #111111; | |
height: 30px; | |
margin: 0 0 0 -1px; | |
padding-top: 4px; | |
position: relative; | |
top: -4px; | |
} | |
ul.tabs li:first-child a.active { | |
margin-left: 0; | |
} | |
ul.tabs li:first-child a { | |
border-top-left-radius: 2px; | |
border-width: 1px 1px 0; | |
} | |
ul.tabs li:last-child a { | |
border-top-right-radius: 2px; | |
} | |
ul.tabs:before, ul.tabs:after { | |
content: " "; | |
display: block; | |
height: 0; | |
overflow: hidden; | |
visibility: hidden; | |
width: 0; | |
} | |
ul.tabs:after { | |
clear: both; | |
} | |
/* update for better mobile look */ | |
ul.tabs.vertical> li { | |
width: 100%; | |
} | |
</style> | |
{% else %} | |
{{ description }} | |
{% endif %} |
Would be amazing to have a Vanilla JS version of this. Shopify's putting a lot of emphasis on page speed, jQuery has fallen out of favor.
Vanilla JS version is here :)
Now you can "stop" tabs.
Modified line 11 to try to get rid of data-mce-fragment="1"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
I am using this code for my shop - works great.
However, when I am changing the styling, e.g. background color when tab active from #FFFFFF to #ff0266 for example, nothing changes.
It seems like something is overwriting my styling - how can I fix this?
Best,
OKAY