How to apply a class to a div based on div width? - javascript

I am trying to add a class to a specific div based on its width, so it is dynamically added or removed as the overall window (and therefore the div, which has a percentage width) resizes.
I've tried using javascript querySelector and offsetWidth to identify the div, but so far it's not working. My method is inspired by this codepen (which gets the window width, so slightly different from what I'm trying to do).
Here's what I have so far:
var addWideClass = function() {
var width = document.querySelector('.v65-productGroup-product').offsetWidth;
if (width < 141) {
$('.v65-productGroup-product').removeClass('wide');
} else if (width >= 415) {
$('.v65-productGroup-product').addClass('wide');
};
};
$(window).resize(function(){
addWideClass();
});
addWideClass();
What do I need to change to have .wide added to .v65-productGroup-product when .v65-productGroup-product > 414px wide?

The offsetWidth may be cashed or have missed a reflow. Browser vendors may choose how to handle DOM calculations like offsetWidth.
As you say: the overall window (and therefore the div, which has a percentage width) resizes. You can change this row to detect window width instead of div width:
var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || screen.width
Then you can have typical device breakpoints. If you really need it to change when div is 141 and 415 pixels you need to use yor mathematic skills to calculate how wide the window has to be from one of these values added to the rest of widths and procentual factors you know of the neigbouring elements.

maybe this pen helps:
https://codepen.io/anon/pen/zQXMoz
I basically modified the pen you referred to and added the functionality you wanted to. change the page size to see the effect.
P.S. in your own code, did you mean:
if (width < 414) {
instead of
if (width < 141) {
?
additionally, if you just want to toggle the class on 414px, then this should suffice:
if (width < 414) {
// remove class
}
else {
// add class
}

I made this demonstration: See it in full page view and change browser width
"use strict";
console.clear();
const addWideClass = function() {
Array.from(document.getElementsByTagName('span')).forEach(el => {
const w = el.offsetWidth
el.style.setProperty('--w', `'${w}'`);
if (w < 141) {
el.classList.remove("wide");
} else if (w >= 415) {
el.classList.add("wide");
}
})
};
window.addEventListener('resize', addWideClass)
addWideClass()
div {
display: flex;
}
div span {
box-sizing: border-box;
padding: 10px;
--w: '213232';
}
div span:nth-child(1) {
flex-grow: 2;
flex-basis: 0;
background-color: gold;
}
div span:nth-child(2) {
flex-grow: 3;
flex-basis: 0;
background-color: silver;
}
div span:nth-child(3) {
flex-grow: 4;
flex-basis: 0;
background-color: goldenrod;
}
div span.wide {
border: 10px solid #000;
}
div span:before {
content: var(--w);
display: block;
}
<div>
<span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora similique vitae accusantium repellat nobis architecto unde, exercitationem soluta placeat voluptatum nostrum beatae tenetur ad deleniti voluptate quia quis officia voluptatem.</span>
<span>At ex velit eligendi ipsam doloribus doloremque laudantium, minus mollitia dicta quis sit nostrum commodi incidunt autem provident vero! Rem distinctio, optio harum deserunt aperiam corporis. Quod maxime eos porro!</span>
<span>Quaerat, quo adipisci voluptas dolores odio maxime maiores obcaecati repellendus ducimus a cupiditate placeat, fugiat nostrum distinctio quidem nemo rem error laborum ipsam eos dicta corrupti. Nobis iure suscipit saepe.</span>
</div>
P.S. you might want to consider a debounce on the resize event (I used a second as debounce delay to make the effect more ovious. You would rather want a debounce delay of 100 milliseconds or the like)
"use strict";
console.clear();
const addWideClass = function() {
Array.from(document.getElementsByTagName('span')).forEach(el => {
const w = el.offsetWidth
el.style.setProperty('--w', `'${w}'`);
if (w < 141) {
el.classList.remove("wide");
} else if (w >= 415) {
el.classList.add("wide");
}
})
};
// From: https://davidwalsh.name/javascript-debounce-function
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
window.addEventListener('resize', debounce(addWideClass, 1000))
addWideClass()
div {
display: flex;
}
div span {
box-sizing: border-box;
padding: 10px;
--w: '213232';
}
div span:nth-child(1) {
flex-grow: 2;
flex-basis: 0;
background-color: gold;
}
div span:nth-child(2) {
flex-grow: 3;
flex-basis: 0;
background-color: silver;
}
div span:nth-child(3) {
flex-grow: 4;
flex-basis: 0;
background-color: goldenrod;
}
div span.wide {
border: 10px solid #000;
}
div span:before {
content: var(--w);
display: block;
}
<div>
<span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora similique vitae accusantium repellat nobis architecto unde, exercitationem soluta placeat voluptatum nostrum beatae tenetur ad deleniti voluptate quia quis officia voluptatem.</span>
<span>At ex velit eligendi ipsam doloribus doloremque laudantium, minus mollitia dicta quis sit nostrum commodi incidunt autem provident vero! Rem distinctio, optio harum deserunt aperiam corporis. Quod maxime eos porro!</span>
<span>Quaerat, quo adipisci voluptas dolores odio maxime maiores obcaecati repellendus ducimus a cupiditate placeat, fugiat nostrum distinctio quidem nemo rem error laborum ipsam eos dicta corrupti. Nobis iure suscipit saepe.</span>
</div>

Related

Find element that's on the middle of the visible screen (viewport) to target another element

What I am aiming to achieve is something that looks like this. you can see it in action on this URL, if you scroll a bit.
I was thinking at first to try using inViewport, and every time a heading or a paragraph is in viewport to show one image and hide the previous. but my problem is that the elements are in viewport in conjunction
This is the initial code I was using:
$.fn.isInViewport = function () {
let elementTop = $(this).offset().top;
let elementBottom = elementTop + $(this).outerHeight();
let viewportTop = $(window).scrollTop();
let viewportBottom = viewportTop + window.innerHeight; // <-- here
return elementBottom > viewportTop && elementTop < viewportBottom;
};
$(window).scroll(function () {
if ($('.heading1 ').isInViewport()) {
// Use .blogcard instead of this
$('.img1').addClass('show');
} else {
// Remove class
$('.img1').removeClass('show');
}
if ($('.heading2 ').isInViewport()) {
// Use .blogcard instead of this
$('.img2').addClass('show');
} else {
// Remove class
$('.img2').removeClass('show');
}
});
I have found this answer but have no idea on how can I use is to my benefits.
I have also stumbled upon this solution, which looks even smarter, but the code adds the classes to the selector in viewport and not to a different element.
This is the code applied there:
ar getElementsInArea = (function(docElm){
var viewportHeight = docElm.clientHeight;
return function(e, opts){
var found = [], i;
if( e && e.type == 'resize' )
viewportHeight = docElm.clientHeight;
for( i = opts.elements.length; i--; ){
var elm = opts.elements[i],
pos = elm.getBoundingClientRect(),
topPerc = pos.top / viewportHeight * 100,
bottomPerc = pos.bottom / viewportHeight * 100,
middle = (topPerc + bottomPerc)/2,
inViewport = middle > opts.zone[1] &&
middle < (100-opts.zone[1]);
elm.classList.toggle(opts.markedClass, inViewport);
if( inViewport )
found.push(elm);
}
};
})(document.documentElement);
////////////////////////////////////
// How to use:
window.addEventListener('scroll', f)
window.addEventListener('resize', f)
function f(e){
getElementsInArea(e, {
elements : document.querySelectorAll('div'),
markedClass : 'highlight--1',
zone : [20, 20] // percentage distance from top & bottom
});
getElementsInArea(e, {
elements : document.querySelectorAll('div'),
markedClass : 'highlight--2',
zone : [40, 40] // percentage distance from top & bottom
});
}
Would love all the help I could get. Cheers
Using the IntersectionObserver API
It should be quite simple by using the IntersectionObserver API to watch for your elements intersecting the viewport, or any other (Options root) ancestor.
To detect an element reaches the viewport vertical center can be done by passing the Option rootMargin where the bottom and top values are set at -50%, with an Option threshold set to 0 (as soon as one pixel enters that intersecting area)
// Utility functions:
const EL = (sel, par) => (par || document).querySelector(sel);
const ELS = (sel, par) => (par || document).querySelectorAll(sel);
// App:
const ELS_pictures = ELS(".picture");
const switchPicture = (EL_entry) => {
const EL_picTarg = EL(EL_entry.dataset.reveal);
ELS_pictures.forEach(EL_pic => EL_pic.classList.toggle("is-active", EL_pic === EL_picTarg));
};
// In Viewport
const inViewport = (entries, observer) => entries.forEach(entry => entry.isIntersecting && switchPicture(entry.target));
// Assign observer to all Elements with data-reveal attribute (Articles)
ELS("[data-reveal]").forEach(el => {
const observer = new IntersectionObserver(inViewport, {
// root: (by default is Document),
rootMargin: "-50% 0px -50% 0px", // set the root intersecting area as a tiny line in the vertical center
threshold: 0, // 0 = as soon as 1px intersects
});
observer.observe(el);
});
/* QuickReset */
* {
margin: 0;
box-sizing: border-box;
}
body {
font: 18px/1.5 sans-serif;
}
.stickers {
display: grid;
grid-template-columns: 2fr 3fr;
max-width: 1000px;
margin: 0 auto;
}
/* Article Component */
.articles {
display: flex;
flex-direction: column;
}
.article {
margin: 100px 0;
padding: 30px;
}
.pictures {
position: sticky;
display: flex;
top: 0px;
right: 0;
height: 100vh;
background: #444;
}
.picture {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
margin: auto;
transition: 0.3s opacity, 0.5s transform;
opacity: 0;
transform: scale(0.8);
}
.picture.is-active {
opacity: 1;
transform: scale(1);
}
<p style="height: 80vh;">Scroll down...</p>
<div class="stickers">
<div class="articles">
<div class="article" data-reveal="#picture_1">
<h1>Many cats</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio laudantium perferendis eius iusto vitae eaque, eligendi ullam, rerum maiores, totam velit! Debitis repudiandae aliquam placeat, minus. Facere nihil aspernatur nam!</p>
</div>
<div class="article" data-reveal="#picture_2">
<h1>Little cat</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p>
</div>
<div class="article" data-reveal="#picture_3">
<h1>Snowcat</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur perferendis possimus asperiores deleniti voluptatum amet nostrum ratione odio, a perspiciatis suscipit ab nulla repellat laudantium praesentium adipisci! Nihil ex, quos!</p>
</div>
<div class="article" data-reveal="#picture_4">
<h1>Cat</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut recusandae doloribus laboriosam, quasi aspernatur modi illum voluptate dicta alias optio, omnis qui deserunt. Quisquam, beatae dolores cum nostrum sint minima!</p>
</div>
</div>
<div class="pictures">
<img class="picture is-active" id="picture_1" src="https://placekitten.com/380/300" alt="Catz!">
<img class="picture" id="picture_2" src="https://placekitten.com/460/400" alt="Catz!">
<img class="picture" id="picture_3" src="https://placekitten.com/400/450" alt="Catz!">
<img class="picture" id="picture_4" src="https://placekitten.com/500/450" alt="Catz!">
</div>
</div>
<p style="height: 180vh;">Etc...</p>
Use data-* Attribute on your articles Elements where the value should match the selector of the related picture.
Toggle a class i.e: .is-active using classList that will determine the active styles for the matching picture Element
To make the fixed effect use position: sticky on your pictures parent element.

Scroll up after click a href in page

I have a footnote system. When I click sup number it scroll down to footnote. But It didn't show because of sticky header.
I need to scroll up around 60px after href scrolling.
I tried to add window.scrollBy(0, 60); in onclick of "sup a" object. It didn't work when I add it as function as well.
Full code:
$(document).ready(function() {
// make a link out of any <sup> with class .footnoted
$('sup').each(function(i){
var superscript = i+1;
$(this).html('<a>' + superscript + '</a>');
});
// give <sup class="footnoted"> an id to scroll back to
$('sup').each(function(i){
this.id = "reading-position-"+(i+1);
});
// tell the superscripts where to go
$('sup a').each(function(i){
this.href = "#footnote-"+(i+1);
});
// set a target for the superscripts to scroll to
// if you're not using a list for your footnotes, change li to the correct selector
$('ol li').each(function(i){
this.id = "footnote-"+(i+1);
});
// add return to reading position link at the end of the footnote
$('ol li').append('<a rel="nofoot"> ↑ Okuma Alanına Geri Dön</a>');
// give the return to position url an href of the target ID
$('ol li a').each(function(i){
this.href = "#reading-position-"+(i+1);
});
// make a back to top link at the end of your footnotes
// if you're not using a list for your footnotes, change li to the correct selector
// smooth scroll between reading position and footnotes
$('sup a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top - 60
}, 500, 'swing', function () {
window.location.hash = target;
});
// remove class and link to previous reading position from other <li> if you scrolled to a footnote previously
{#$('.current-footnote span').remove();#}
{#$('ol li').removeClass('current-footnote');#}
// add return to reading position link and give the current footnote a class for additional styles
$(target).addClass('current-footnote');
$('.current-footnote span').css('display', 'inline');
});
scrollBy(0, 60) scrolls down, not up. You need to use negative numbers to reverse the direction. So, window.scrollBy(0, -60).
If that still doesn't work, something is probably wrong with how you're registering the click handler. It would be useful if you could show your full code.
You can create references using the DATA attribute.
Example link: <span class="reference" data="#one">ONE</span>
This script will collect all elements with class class="reference" and add a listener to them. When the element is clicked, the script will take the DATA information which is the ID of the element to which the page should be scrolled.
In this line you can change the value 60 so that the information remains in the visible part
window.scrollTo(0, top - 60);
In this example, 60px is the height of the sticky navigation
var navLinks = document.querySelectorAll('.reference');
for (let i = 0; i < navLinks.length; i++) {
navLinks[i].addEventListener("click", function () {
var elId = this.getAttribute('data');
var top = document.querySelector(elId).offsetTop;
window.scrollTo(0, top - 60);
});
}
body {
margin: 0px;
}
nav {
height: 60px;
background: orangered;
position: fixed;
width: 100%;
top: 0px;
}
.reference {
cursor: pointer;
color: orangered;
}
#wrap {
margin-top: 60px;
}
<nav>Navigation...</nav>
<div id="wrap">
<div>
Lorem ipsum dolor, <span class="reference" data="#one">ONE</span> sit amet consectetur adipisicing elit. Cum nihil vero voluptatibus tempora repellendus <span class="reference" data="#two">TWO</span> aperiam quidem debitis, totam consequuntur ex aspernatur quasi quod molestias rem quibusdam? Facilis adipisci asperiores iste. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum nihil vero voluptatibus tempora repellendus aperiam quidem debitis, totam consequuntur ex aspernatur quasi quod molestias rem quibusdam? Facilis adipisci asperiores iste. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum nihil vero voluptatibus tempora repellendus aperiam quidem debitis, totam consequuntur ex aspernatur quasi quod molestias rem quibusdam? Facilis adipisci asperiores iste.
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
<p id="one">
ONE - Reference One
<br><br><br><br><br><br><br><br><br><br><br>
</p>
<p id="two">
TWO - Reference Two
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</p>
</div>

Javascript page enter event

I want an event this should load everytime the site is typed in the browser example : http://localhost/ is typed in the url and the first page should show is my overlay. After they read the information they can close it but if they wanna read it again they can click the button. Also if the site is getting refreshed the overlay should be popup again.
My current code and where I stuck :
const doc = document;
const menuOpen = doc.querySelector(".menu");
const menuClose = doc.querySelector(".close");
const overlay = doc.querySelector(".overlay");
menuOpen.addEventListener("click", () => {
overlay.classList.add("overlay--active");
});
menuClose.addEventListener("click", () => {
overlay.classList.remove("overlay--active");
});
to do this in javascript you can achieve this using window.load like this:
window.onload = function() {myFunction()};
function myFunction() {
overlay.classList.add("overlay--active");
}
but for the best solution i would think adding the overlay--active by default as #Keith mentioned would be nicer as this requires less javascript for the webpage.
You could do it by using if-else structure in javascript. Like the code I posted here. In this method you don’t need the “onload” event. And the “overlay” popped up again when the page is refreshed.
var menuOpen = document.getElementById("menu");
var overlay = document.querySelector(".overlay");
menuOpen.addEventListener("click", () => {
if(overlay.classList.contains("active")){
overlay.classList.add("deactive");
overlay.classList.remove("active");
menuOpen.innerHTML = "show";
} else {
overlay.classList.add("active");
overlay.classList.remove("deactive");
menuOpen.innerHTML = "hide";
}
});
.active {
opacity: 1;
}
.deactive {
opacity: 0;
}
#menu {
margin-top: 15px;
margin-left: 100px;
width: 100px;
height: 60px;
background-color: #fff;
border: 1px solid #5522dd;
color: #5522dd;
cursor: pointer;
}
#menu:hover {
color: #fff;
background-color: #5522dd;
}
.overlay {
border: 2px solid #000;
margin-top: 25px;
-webkit-transition: 2s;
transition: 2s;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Javascript page enter event</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="overlay active">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui modi quasi, quam deleniti, placeat expedita nostrum quae quaerat? Id, velit iste saepe dolore, consequuntur vel quis iure excepturi ut aut fugit dignissimos ea magni repudiandae nihil, assumenda deleniti nostrum tenetur minima aperiam doloribus. Quaerat sunt nam distinctio! Suscipit nostrum vel, sunt, eos esse fugit.
</div>
<button id="menu">hide</button>
<script src="javasc.js"></script>
</body>
</html>
You can use jquery and use it in the loading of document.
like
document.ready(()=>{
$(".overlay").addClass("overlay--active");
})

How can i decrease font size to fit a fixed height container for DOM elements within an array?

I have a project which is pulling content from contentful and displays news stories in a grid.
I'm trying to write a script to decrease the font size on the header tag until the text fits its parent.
I'm using a while loop in the snippet below but it only seems to decrease the size of the element once as it loops over.
How can i continue to decrease this value for every iteration ? or does anyone know a better way to achieve this result ?
I previously tried to use FitText.js only it seemed to change all the elements to the same font size.
window.onload = resize_to_fit();
function resize_to_fit() {
const CONTAINERS = document.querySelectorAll(".headline-container");
const HEADLINETEXTS = document.getElementsByClassName('headline');
for (i = 0; i < CONTAINERS.length; i++) {
var headline = HEADLINETEXTS[i];
var containerHeight = CONTAINERS[i].offsetHeight;
var headlineHeight = HEADLINETEXTS[i].offsetHeight;
var headlineLength = HEADLINETEXTS[i].innerHTML.length;
var style = window.getComputedStyle(HEADLINETEXTS[i], null).getPropertyValue('font-size');
var fontSize = parseFloat(style);
var count = 15;
while (headlineHeight > containerHeight && count > 0) {
//This only seems to happen once;
headline.style.fontSize = fontSize - 1 + "px";
count--;
}
}
}
window.onload = resize_to_fit();
function resize_to_fit() {
const CONTAINERS = document.querySelectorAll(".headline-container");
const HEADLINETEXTS = document.getElementsByClassName('headline');
for (i = 0; i < CONTAINERS.length; i++) {
var headline = HEADLINETEXTS[i];
var containerHeight = CONTAINERS[i].offsetHeight;
var headlineHeight = HEADLINETEXTS[i].offsetHeight;
var headlineLength = HEADLINETEXTS[i].innerHTML.length;
var style = window.getComputedStyle(HEADLINETEXTS[i], null).getPropertyValue('font-size');
var fontSize = parseFloat(style);
var count = 15;
while (headlineHeight > containerHeight && count > 0) {
// this only seems to happen once.
headline.style.fontSize = fontSize - 1 + "px";
count--;
}
}
}
.headline-container {
height: 50px;
width: 200px;
}
h4.headline {
font-size: 30px;
}
<div class="headline-container">
<a href="">
<h4 class="headline">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veritatis laudantium maiores culpa eaque eius fuga officia, in nihil nostrum nesciunt porro enim aut, sit quod suscipit repellat quisquam fugit corporis.</h4>
</a>
</div>
<div class="headline-container">
<a href="">
<h4 class="headline">Porro non culpa saepe libero est cumque, quasi, temporibus id optio inventore ut incidunt quaerat a, maiores eaque dignissimos debitis quis. Suscipit facilis beatae tempore iste culpa, dolores dolor quo!</h4>
</a>
</div>
<div class="headline-container">
<a href="">
<h4 class="headline">Ullam asperiores nobis ea, dolor voluptas, consequuntur repellat possimus deserunt quia fuga hic, optio similique sunt delectus autem voluptatem inventore tenetur nulla voluptatum ab nemo culpa. Provident dignissimos veritatis et?</h4>
</a>
</div>
<div class="headline-container">
<a href="">
<h4 class="headline">Eveniet sed explicabo tempore dolorum nesciunt sapiente quasi vel quam consequuntur error, velit ullam quaerat, voluptatibus nobis voluptates, expedita vitae molestias natus laudantium architecto similique odio alias sit magnam! Fugit.</h4>
</a>
</div>
Your cached values were not changing on each iteration of the inner loop, which means that you are comparing all of the same values each time, and you would always end up with the same result.
If you don't cache values that you don't need to cache, use the values that you do need to cache (i.e. headline and container were never used in your code), and access the values directly from the inner loop, you shouldn't have a problem.
As a final note, best practices are usually fairly subjective and open to interpretation so I'm not going to tell you how you should do simple things, but whatever you do... please be consistent.
const containers = document.getElementsByClassName('headline-container');
const headlines = document.getElementsByClassName('headline');
for (i = 0; i < containers.length; i++) {
const headline = headlines [i];
const container = containers[i];
let count = 15;
while (headline.offsetHeight > container.offsetHeight && count > 0) {
const fontSize = parseInt(window.getComputedStyle(headline).fontSize);
headline.style.fontSize = fontSize - 1 + "px";
count--;
}
}
.headline-container { height: 30px; overflow: hidden; border: 1px solid } h1 { margin: 0 }
<div class="headline-container"><h1 class="headline">Hello World</h1></div>

Javascript Tabs Accordion Issue

I have created a tabs accordion which is working properly. However their behaviour is not as i want it to be. At the current tabs accordion when i press one of the tabs it will show the content inside it, and when i press another tab it will open also. What i would like to have happen is when i click one of the tabs to be the only one that is showing and the rest of the tabs to be closed. Hope someone can help me to add that extra code that i need to make it work.
var tabsContainer = document.getElementById("tabsContainer");
var tabUl = document.getElementById("tabs-ul");
var tabOne = document.getElementById("tab-one");
var tabTwo = document.getElementById("tab-two");
var tabThree = document.getElementById("tab-three");
var tabOneContent = document.getElementById("tab-one-content");
var tabTwoContent = document.getElementById("tab-two-content");
var tabThreeContent = document.getElementById("tab-three-content");
function openTabOne() {
if (tabOneContent.className == "toggleTab") {
tabOneContent.className = "";
} else {
tabOneContent.className = "toggleTab";
}
}
function openTabTwo() {
if (tabTwoContent.className == "toggleTab") {
tabTwoContent.className = "";
} else {
tabTwoContent.className = "toggleTab";
}
}
function openTabThree() {
if (tabThreeContent.className == "toggleTab") {
tabThreeContent.className = "";
} else {
tabThreeContent.className = "toggleTab";
}
}
tabOne.addEventListener("click", openTabOne);
tabTwo.addEventListener("click", openTabTwo);
tabThree.addEventListener("click", openTabThree);
* {
padding: 0px;
margin: 0px;
}
body {
font-family: sans-serif;
font-weight: 14px;
background: silver;
}
#tabsContainer {
width: 50%;
margin: 0 auto;
border: 3px solid #a70d89;
padding: 20px;
box-shadow: 2px 2px 10px rgba(85, 85, 85, 0.77);
;
}
ul {
list-style: none;
}
li {
display: inline-block;
padding: 5px 20px;
background: #4c99ac;
color: #7910c6;
cursor: pointer;
}
#tabsContainer > div {
margin: 20px 0px;
display: none;
}
#tab-one-content.toggleTab,
#tab-two-content.toggleTab,
#tab-three-content.toggleTab {
display: block;
}
<div id="tabsContainer">
<ul id="tabs-ul">
<li id="tab-one">Tab One</li>
<li id="tab-two">Tab Two</li>
<li id="tab-three">Tab Three</li>
</ul>
<div id="tab-one-content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
<div id="tab-two-content">
Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
<div id="tab-three-content">
Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
</div>
You need to remove the class from the tabs that you don't want open anymore, here is a possible way to do it.
var tabsContainer = document.getElementById("tabsContainer");
var tabUl = document.getElementById("tabs-ul");
var tabOne = document.getElementById("tab-one");
var tabTwo = document.getElementById("tab-two");
var tabThree = document.getElementById("tab-three");
var tabPanels = [
document.getElementById("tab-one-content"),
document.getElementById("tab-two-content"),
document.getElementById("tab-three-content")
];
function showTab(tabIndex) {
for(var i = 0; i < tabPanels.length; i++) {
tabPanels[i].className = i == tabIndex ? 'toggleTab' : '';
}
}
function openTabOne() {
showTab(0);
}
function openTabTwo() {
showTab(1);
}
function openTabThree() {
showTab(2);
}
openTabOne();
tabOne.addEventListener("click", openTabOne);
tabTwo.addEventListener("click", openTabTwo);
tabThree.addEventListener("click", openTabThree);
* {
padding:0px;
margin:0px;
}
body {
font-family: sans-serif;
font-weight: 14px;
background:silver;
}
#tabsContainer {
width:50%;
margin:0 auto;
border:3px solid #a70d89;
padding:20px;
box-shadow: 2px 2px 10px rgba(85, 85, 85, 0.77);;
}
ul {
list-style: none;
}
li {
display: inline-block;
padding:5px 20px;
background:#4c99ac;
color:#7910c6;
cursor: pointer;
}
#tabsContainer > div {
margin: 20px 0px;
display: none;
}
#tab-one-content.toggleTab, #tab-two-content.toggleTab, #tab-three-content.toggleTab {
display: block;
}
<div id="tabsContainer">
<ul id="tabs-ul">
<li id="tab-one">Tab One</li>
<li id="tab-two">Tab Two</li>
<li id="tab-three">Tab Three</li>
</ul>
<div id="tab-one-content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
<div id="tab-two-content">
Placeat quam nesciunt, architecto earum! Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
<div id="tab-three-content">
Beatae explicabo voluptatum rem odit sint dolorem, voluptatem, est iure quia ab voluptates excepturi ratione debitis praesentium.
</div>
</div>

Categories

Resources