combine tabs and grid layout - javascript

I'm currently learning, please bear with me. I try to make a holy grail layout using grid while making tabs to change middle content (and maybe left one in the future).
I used this suggestion I found here to make the tabs : https://jsfiddle.net/a2fh8n4e/
$(document).ready(function () {
var previousActiveTabIndex = 0;
$(".tab-switcher").on('click', function (event) {
if (event.type === "click") {
var tabClicked = $(this).data("tab-index");
if(tabClicked != previousActiveTabIndex) {
$("#allTabsContainer .tab-container").each(function () {
if($(this).data("tab-index") == tabClicked) {
$(".tab-container").hide();
$(this).show();
previousActiveTabIndex = $(this).data("tab-index");
return;
}
});
}
}
});
});
html {
background-color: #aaaaaa;
font-size: 16px;
font-family: "alegreya", serif;
}
body {
min-width: 550px;
margin: 0;
padding: 0 20px 20px 20px;
display: grid;
grid-template-columns: 15% auto 15%;
grid-template-areas: "header header header" "left middle right" "footer footer footer";
}
#header {
border-width: 2px, 2px, 0, 2px;
border-color: #ccc;
border-style: solid;
margin-top: 10px;
}
#left {
border-width: 4px, 1px, 0px, 2px;
border-color: #ccc;
border-style: solid;
}
#middle {
border-width: 0, 1px, 2px, 1px;
border-color: #ccc;
border-style: solid;
}
#right {
border-width: 0, 2px, 2px, 1px;
border-color: #ccc;
border-style: solid;
padding-left: 3px;
}
#footer {
background: #ccc;
height: 40px;
padding-top: 10px;
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: right;
}
.tab-switcher {
display: inline-block;
cursor: pointer;
margin-right: 25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- HEADER AND TABS -->
<div style="grid-area: header" id="header">
<ul>
<li class="tab-switcher" data-tab-index="0" tabindex="0">Collecte</li>
<li class="tab-switcher" data-tab-index="1" tabindex="0">Journal</li>
</ul>
</div>
<!-- CONTENT ZONE -->
<div id="allTabsContainer">
<div class="tab-container" data-tab-index="0">
<!-- TAB1 -->
<div style="grid-area: left" id="left">
<p>Wood : <span id="Wood"></span></p>
</div>
<div style="grid-area: middle" id="middle">
<button class="Collect" id="But_wood">Pick wood</button>
<button class="Collect" id="But_tree">Cut a tree</button>
</div>
</div>
<div class="tab-container" data-tab-index="1" style="display:none;">
<!-- TAB2 -->
<div style="grid-area: left" id="left">
<p>Stone : <span id="Stone"></span></p>
<p>Grass : <span id="Grass"></span></p>
</div>
<div style="grid-area: middle" id="middle">
<button class="Collect" id="But_stone">Collect stone</button>
<button class="Collect" id="But_grass">Collect grass</button>
</div>
</div>
<!--div class="tab-container" data-tab-index="2" style="display:none;">
Some content for Tab - 3
</div-->
</div>
<!-- LOGS & CHAT SHOULD BE ALWAYS ACTIVE -->
<div style="grid-area: right" id="right">
<p>Logs</p>
<p id="log">...</p>
</div>
<!-- FOOTER SHOULD BE ALWAYS ACTIVE -->
<div style="grid-area: footer" id="footer">
<p>contenu relatif au site et à l'auteur</p>
</div>
<!-- MISC. & SCRIPTS -->
<script src="scripts/main.js"></script>
I tried to combine the two but can't reach something where it works as intended with the correct layout. I can not combine style="grid-area: xxx within the selected tabs https://jsfiddle.net/j6cemskg/35/
=> I want the buttons to be in the middle column, while having ressources amount on a left panel, and both should change according to tab chosen.
Also, if anyone can give insight on how to avoid the trouble to have multiple ID like "left0","left1", etc. for each and every tab (maybe class attribute ? Can I have multiple classes assigned to a same element ?)
I would gladly take any advice concerning those troubles, thank you.

One approach is as follows, but I've changed quite a bit of your code to simplify things.
Basically, I've adjusted your HTML so that the grid display is based on the #allTabsContainer element, and made all elements that make up areas of that grid siblings in order that they can be placed in the grid defined on the #allTabsContainer element.
I've also removed the jQuery entirely, and revised the approach used to toggle the display of the various grid-elements.
Explanatory comments for changes, and functionality, are in the code below:
// defining a named function using Arrow syntax, to which a reference to the
// Event Object is passed (automatically) from EventTarget.addEventListener():
const updateToggle = (evt) => {
// we retrieve the element that has triggered the function-call to
// which the function was bound:
let switched = evt.currentTarget,
// from that element we use the HTMLElement.dataset API to
// retrieve the value of the named attribute; we use camelCase
// to access attributes that include hyphens; so 'data-tab-index'
// is accessed as below:
toShow = switched.dataset.tabIndex,
// from the switched element we navigate to the closest ancestor
// that contains a 'data-tab-show' attribute:
toggleDispatch = switched.closest('[data-tab-show]');
// with that Element we - again - utilise the HTMLElement.dataset
// API to set the the 'data-to-show' attribute-value to the value
// we retrieved from the clicked ('switched') element:
toggleDispatch.dataset.tabShow = toShow;
},
// here we retrieve the elements that will serve as switches, the
// li.tab-switcher elements:
toggles = document.querySelectorAll('li.tab-switcher');
// we use NodeList.prototype.forEach() to iterate over the NodeList:
toggles.forEach(
// here we use an Arrow function to bind the updateToggle() function
// (note the deliberately omitted parentheses) as the event-handler
// for the 'click' event on the elements of the NodeList:
(el) => el.addEventListener('click', updateToggle)
);
/* simple reset to ensure that all elements are using the same
box-sizing algorithm, font, list-style-type, margin and padding */
*, ::before, ::after {
box-sizing: border-box;
font: normal normal 1rem / 1.5 sans-serif;
list-style-type: none;
margin: 0;
padding: 0;
}
#allTabsContainer {
display: grid;
/* setting a 0.5em gap between adjacent elements,
whether vertically, or horizontally, adjacent: */
gap: 0.5em;
grid-template-areas:
"header header header"
"left middle right"
"footer footer footer";
/* there are differences between 'auto' and '1fr'
but they're minor, and your intent seems to be
to use the entirety of the space available, so
I chose to replace 'auto' with '1fr': */
grid-template-columns: 15% 1fr 15%;
/* using grid-template-rows to specify the heights
of the various rows: */
grid-template-rows: min-content 1fr 50px;
/* setting a margin on the block-axis of the element
to 0 (this is implicit from the 'reset' above; but
if it needs to be changed I like it to be explicitly
stated for ease of changing) the 'block-axis' is
top-to-bottom in English and left-to-right languages: */
margin-block: 0;
/* I put a margin of 20px on the inline-axis (the axis of
writing-flow, left-to-right in English): */
margin-inline: 20px;
/* this makes the minimum height of the element 100 viewport-units
tall, but allows it to expand if the content demands it: */
min-height: 100vh;
}
#allTabsContainer > div {
/* placing a border on all elements taking part in the grid: */
border: 2px solid #ccc;
}
#header {
/* positioning the grid-element in the named grid-area: */
grid-area: header;
}
#header ul {
/* using flex-layout to arrange the elements to flow in the
inline axis: */
display: flex;
/* placing a 1em gap between adjacent elements: */
gap: 1em;
/* vertically aligning the child elements: */
align-content: center;
/* aligning the child elements to the start of the inline-flow
(to the left in a left-to-right language such as English): */
justify-content: start;
}
.tab-switcher {
cursor: pointer;
/* setting the defaults for the text-decoration
(not using 'text-decoration' shorthand): */
text-decoration-color: transparent;
text-decoration-line: underline;
text-decoration-thickness: 0.1em;
/* transitioning all properties: */
transition: all 0.3s linear;
}
/* selects all .tab-switcher elements when they match
any of the supplied pseudo-classes listed in the :is()
pseudo-class: */
.tab-switcher:is(:hover, :active, :focus) {
color: rebeccapurple;
text-decoration-color: currentColor;
text-decoration-line: underline;
text-decoration-thickness: 0.2em;
}
/* positioning elements in the named grid-areas: */
.tab-container.left {
grid-area: left;
}
.tab-container.middle {
grid-area: middle;
}
#right {
grid-area: right;
}
#footer {
background-color: #ccc;
grid-area: footer;
padding-inline: 1em;
/* again using CSS logical properties, here we align the text
to the end of the inline-axis (the right, in a left-to-right
language such as English): */
text-align: end;
}
/* here we select all element(s) which are not a '.tab-switcher'
element which have a data-tab-index attribute and are a
descendant of an element(s) with a data-tab-show attribute: */
[data-tab-show] [data-tab-index]:not(.tab-switcher) {
/* we visually hide those elements (this may be imperfect for
use in non-visual media, such as screen-readers; please check): */
opacity: 0;
visibility: hidden;
}
/* here we undo the hiding of those elements, by selecting elements which
are not '.tab-switcher' elements, that have a data-tab-index
attribute-value equal to 0 (or 1) which is a descendant of an element(s)
that have a data-tab-show attribute-value of 0 (or 1): */
[data-tab-show="0"] [data-tab-index="0"]:not(.tab-switcher),
[data-tab-show="1"] [data-tab-index="1"]:not(.tab-switcher) {
opacity: 1;
visibility: visible;
}
button {
/* adding padding to the <button> elements, purely for aesthetic purposes: */
padding-block: 0.2em;
padding-inline: 0.4em;
}
<!-- the grid display is now specified on the following element, and all elements taking part
in the grid are now siblings; this is so that they're all 'aware' of the grid in their
parent element and can be positioned in those areas.
You'll note that there is a new data-* attribute, the "data-tab-show" attribute with a
value set to 0 on page-load (this is modified in the JavaScript that handles the
toggling: -->
<div id="allTabsContainer" data-tab-show="0">
<!-- HEADER AND TABS -->
<div id="header">
<ul>
<li class="tab-switcher" data-tab-index="0" tabindex="0">Collecte</li>
<li class="tab-switcher" data-tab-index="1" tabindex="0">Journal</li>
</ul>
</div>
<!-- CONTENT ZONE -->
<!-- I've also removed the id for the #middle0, #middle1, #left0, #left1...
elements, since it did nothing particularly useful and made it more
awkward to position those elements; instead I added a class to make
it easier ('middle' and 'left') to allow for positioning within
the grid: -->
<div class="tab-container middle" data-tab-index="0">
<!-- TAB1 -->
<button class="Collect" id="But_wood">Pick wood</button>
<button class="Collect" id="But_tree">Cut a tree</button>
</div>
<div class="tab-container middle" data-tab-index="1">
<!-- TAB2 -->
<button class="Collect" id="But_stone">Collect stone</button>
<button class="Collect" id="But_grass">Collect grass</button>
</div>
<div class="tab-container left" data-tab-index="0">
<p>Wood : <span id="Wood"></span></p>
</div>
<div class="tab-container left" data-tab-index="1">
<p>Stone : <span id="Stone"></span></p>
<p>Grass : <span id="Grass"></span></p>
</div>
<!-- LOGS & CHAT SHOULD BE ALWAYS ACTIVE -->
<div id="right">
<p>Logs</p>
<p id="log">...</p>
</div>
<!-- FOOTER SHOULD BE ALWAYS ACTIVE -->
<div style="grid-area: footer" id="footer">
<p>contenu relatif au site et à l'auteur</p>
</div>
</div>
<!-- MISC. & SCRIPTS -->
<!-- commented out as it causes a GET error in the console on sites
where this script doesn't exist (and while I'm looking at the
console for errors it's distracting to have an expected error
there:
<script src="scripts/main.js"></script>
-->
JS Fiddle demo.
References:
CSS:
align-content.
Attribute-selectors [attr], [attr="value"].
box-sizing.
display.
font.
gap.
grid-area.
grid-template-areas.
grid-template-columns.
grid-template-rows.
:is().
justify-content.
Logical properties.
:not().
text-align.
JavaScript:
Arrow functions.
document.querySelectorAll().
HTMLElement.dataset API.
NodeList.prototype.forEach().

Here I will concentrate on the layout using the grid with 4 areas.
I will then show how to handle clicks of the tabs and some actions related to that using a "target" data attribute.
I will leave the style of color etc. to you but put borders on to illustrate each area.
$(function() {
$(".tab-switcher").on('click', function(event) {
let tabClicked = $(this).data("tabTarget");
let lastTab = $(this).closest(".tab-switcher-list").data("last-clicked");
$("#allTabsContainer .tab-container").hide().filter(tabClicked).show();
}).first().trigger('click');
});
html {
/* background-color: #aaaaaa; out just because I dislike gray for visually challenged people reasons */
font-size: 16px;
font-family: "alegreya", serif;
}
body {
/* min-width: 550px; */
margin: 0;
padding-top: 0;
padding-right: 1em;
padding-left: 1em;
padding-bottom: 1em;
border: solid 1px lime;
}
.page-container {
display: grid;
grid-template: auto 1fr auto / auto 1fr auto;
}
.container-header {
padding: 1rem;
grid-column: 1 / 4;
}
.container-left {
grid-column: 1 / 2;
}
.container-main {
grid-column: 2 / 3;
}
.container-right {
grid-column: 3 / 4;
}
.container-footer {
grid-column: 1 / 4;
}
.container-header {
border: solid red 1px;
}
.page-pane {
/* base style for all panes */
border-color: #CCCCCC;
border-style: solid;
border-top-width: 0.125em;
border-left-width: 0.125em;
border-bottom-width: 0.125em;
border-right-width: 0.125em
}
.container-left {
border-right-width: 0.0625em;
border-color: cyan;
}
.container-main {
min-height: 20rem;
}
.container-right {
border-right-width: 0.0625em;
border-color: magenta;
padding-left: 0.5em;
}
.container-footer {
grid-column: 1 / 4;
text-align: right;
align-self: end;
}
.tab-switcher-container {
display: flex;
justify-content: center;
border: solid orange 0.0875em;
height: 2.5rem;
}
nav .tab-switcher-list {
display: flex;
justify-content: center;
list-style-type: none;
border-bottom: 0.25em solid #444444;
height: 1.25em;
}
.tab-switcher {
flex: auto;
margin: 0.25em;
background-color: #EEEEEE;
cursor: pointer;
border: 1px solid #44ddCC;
height: 1.25rem;
padding-left: 0.25em;
padding-right: 0.25em;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="page-container">
<div class="container-header page-pane">
<div>I am the header pane</div>
<nav class="tab-switcher-container">
<ul class=tab-switcher-list>
<li class="tab-switcher" data-tab-target=".tab-1">Collecte</li>
<li class="tab-switcher" data-tab-target=".tab-2">Journal</li>
<li class="tab-switcher" data-tab-target=".tab-cheese">Cheese</li>
</ul>
</nav>
</div>
<div class="container-left page-pane">
<div>I am the left pane</div>
<div id="allTabsContainer">
<div class="tab-container tab-1" data-tab-index="0">
<div>
<p>Wood:<span>I am wood, get wood</span></p>
</div>
</div>
<div class="tab-container tab-2" data-tab-index="1">
<div>
<p>Stone:<span>I am stone, get stone</span></p>
<p>Grass:<span>Grass I am - why am in in stone?!</span></p>
</div>
</div>
<div class="tab-container tab-cheese" data-tab-index="1">
<div>
<p>Cheese:<span>I am cheese!</span></p>
<p>Flavor:<span>Cheddrer Cheese!</span></p>
</div>
</div>
</div>
</div>
<div class="container-main page-pane">
<div>I am the main pane</div>
<button class="Collect get-wood">Pick wood</button>
<button class="Collect cut-tree">Cut a tree</button>
<button class="Collect get-stone">Collect stone</button>
<button class="Collect get-grass">Collect grass</button>
<p>Here I am make me happy</p>
<p>Here I am make me happy</p>
<p>Here I am make me happy</p>
</div>
<div class="container-right logs-container page-pane">
<div>I am the right page pane</div>
<p>Logs</p>
<p id="log">...</p>
</div>
<div class="container-footer page-pane">
<div>I am the footer pane</div>
<div>
<p>contenu relatif au site et à l'auteur</p>
</div>
</div>
</div>

Related

Is there a way to have multiple dropdowns on one page?

I wanted to put a lot of dropdowns on one page, and I could easily get them there. The problem is that when I click on the second one, it displays what's on the first, despite having different contents. Is there a solution for this?
Code because it wouldn't fit here:
https://jsfiddle.net/ne720zps/
Send the button that was clicked to myFunction. Get the appropriate dropdown from the button's relative position to that dropdown (the dropdown is the next element after the button in your code). Delete the duplicated IDs on the dropdown divs.
<button onclick="myFunction(this)">
and
function myFunction(button) {
// the dropdown is the next element after the button that was clicked
button.nextElementSibling.classList.toggle("show");
}
Here's a restructuring of that HTML, with ID tags removed and an example on how to target elements based on their proximity/relationship to the button.
// let the page load...
document.addEventListener('DOMContentLoaded', () => {
// assign the button click
document.querySelectorAll('.dropbtn').forEach(btn => {
btn.addEventListener('click', e => {
// first close all
document.querySelectorAll('.dropdown-content').forEach(div => div.classList.remove('show'))
// open the one you want which is CLOSEST
e.target.closest('.dropdown').querySelector('.dropdown-content').classList.add('show');
})
})
// catch the click outside
document.addEventListener('click', e => {
if (e.target.classList.contains('dropbtn')) return;
document.querySelectorAll('.dropdown-content').forEach(div => div.classList.remove('show'))
})
})
body {
background: black;
color: white;
}
.dropbtn {
background-color: #ffffff;
color: black;
padding: 10px;
font-size: 20px;
border: none;
cursor: pointer;
width: auto;
margin-bottom: 0;
font-weight: 600;
}
/* Dropdown button on hover & focus */
.dropbtn:hover,
.dropbtn:focus {
background: linear-gradient(90deg, #00ffa8, #2300ff);
color: white;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
display: inline-block;
text-align: center;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
text-align: left;
background-color: black;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
width: 30%;
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: center;
background: white;
}
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {
display: block;
}
#center {
text-align: center;
}
<div class="center">
<div class="dropdown">
<button class="dropbtn">Embedded Browser</button>
<div class="dropdown-content">
<b><i>Unblocked browser that won’t show up in your history. Doesn’t work with a lot of websites, so you can mostly just search.
</i></b>
</div>
</div>
</div>
<div class="center">
<div class="dropdown">
<button class="dropbtn">Fullscreen Browser</button>
<div class="dropdown-content">
<b><i>Same as the last one, but takes up your whole screen.
</i></b>
</div>
</div>
</div>

Using CSS Transitions on Auto Height Dimensions

I'm making a collapsible panel and the issue is with the [data-panel] not keeping the css transition when it's set to height: 100%. it works fine for fixed height i.e. height: 150px , but it's important to keep height dynamic since I don't know the available space of the content inside. i'd prefer not modifying the html or js but i'm open to suggestions...
Codepen: issue on line 44 in css
https://codepen.io/oneezy/pen/bGBpXaW
function activeLinks() {
document.addEventListener('click', e => {
let linkEl = e.target.closest('[data-link]');
if (linkEl) {
let url = linkEl.dataset.link;
let linkEls = document.querySelectorAll('[data-link]');
let ActivelinkEls = document.querySelectorAll(`[data-link="${url}"]`);
// remove "active" class from all links
Array.from(linkEls).forEach( (el) => {
el.classList.remove('active');
});
// add "active" class to all matching links
Array.from(ActivelinkEls).forEach( (el) => {
let prevLink = el.parentElement.previousElementSibling;
let prevPrevLink = el.parentElement.parentElement.previousElementSibling;
el.classList.add('active');
if (prevLink && prevLink.dataset.link) {
prevLink.classList.add('active');
prevLink.parentElement.classList.add('active');
}
if (prevPrevLink && prevPrevLink.dataset.link) {
prevPrevLink.classList.add('active');
prevPrevLink.parentElement.classList.add('active');
}
});
}
});
}
activeLinks();
/* Reset
*********************************/
* { margin: 0; padding: 0; box-sizing: border-box; font-family: roboto; }
html, body { height: 100%; overflow-x: hidden; }
a { text-decoration: none; display: block; }
/* Layout
*********************************/
#page { display: grid; grid-template-columns: 160px 1fr; gap: 3rem; height: 100%; }
#nav { background: black; display: block; align-items: start; align-content: start; justify-content: stretch; padding: 2rem 1rem; }
#main { display: flex; justify-content: space-around; padding: 2rem 5rem 0 0; }
/* Navigation
*********************************/
/* Sections */
#nav .link-level__one { margin: 1rem 0; }
#nav .link-level__two { }
#nav .link-level__three { position: relative; }
#nav .link-level__three::after { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; width: 100%; background: gray; }
/* Links */
#nav .link-level__one a { padding: .25rem .5rem; color: gray; font-weight: 900; }
#nav .link-level__one a.active { color: white; }
#nav .link-level__two a { padding: .25rem .5rem; color: gray; font-weight: normal; }
#nav .link-level__two a.active { color: white; }
#nav .link-level__three a { padding: .25rem .5rem; color: gray; }
#nav .link-level__three a.active { color: white; font-weight: normal; }
/* Main
*********************************/
#main section { }
#main a { color: black; padding: 1rem .5rem; }
#main a.active { background: blue; color: white; }
/* Panel
*********************************/
[data-panel] { height: 0; overflow: hidden; transition: .22s .22s ease-in-out; }
.active ~ [data-panel] { height: 150px; } /* I NEED THIS TO BE DYNAMIC HEIGHT! */
<div id="page">
<nav id="nav">
<!-- LINK 1
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- LEVEL 1 -->
<section class="navigation-links__wrapper link-level__one">
Link 1
<!-- LEVEL 2 -->
<section class="link-level__two" data-panel>
Link 1a
<!-- LEVEL 3 -->
<section class="link-level__three" data-panel>
Link 1a-1
Link 1a-2
Link 1a-3
</section>
</section>
</section>
<!-- LINK 2
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- LEVEL 1 -->
<section class="navigation-links__wrapper link-level__one">
Link 2
<!-- LEVEL 2 -->
<section class="link-level__two" data-panel>
Link 2a
<!-- LEVEL 3 -->
<section class="link-level__three" data-panel>
Link 2a-1
Link 2a-2
Link 2a-3
</section>
</section>
</section>
<!-- LINK 3
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- LEVEL 1 -->
<section class="navigation-links__wrapper link-level__one">
Link 3
<!-- LEVEL 2 -->
<section class="link-level__two" data-panel>
Link 3a
<!-- LEVEL 3 -->
<section class="link-level__three" data-panel>
Link 3a-1
Link 3a-2
Link 3a-3
</section>
</section>
</section>
</nav>
<main id="main">
<section>
<h2>Link Level 1</h2>
Link 1
Link 2
Link 3
</section>
<section>
<h2>Link Level 2</h2>
Link 1a
Link 2a
Link 3a
</section>
<section>
<h2>Link Level 3</h2>
Link 1a-1
Link 1a-2
Link 1a-3
Link 2a-1
Link 2a-2
Link 2a-3
Link 3a-1
Link 3a-2
Link 3a-3
</section>
</main>
</div>
It's a duplicate question that has been answered here:
How can I transition height: 0; to height: auto; using CSS?
You can use a max-height greater than it will ever be to accomplish this.
#menu #list {
max-height: 0;
transition: max-height 1s ease-out;
overflow: hidden;
background: #d5d5d5;
}
#menu:hover #list {
max-height: 1000px;
transition: max-height 1s ease-in;
}
I've somewhat came up with a solution I'm proud of; however, it's not perfect. The main trick in getting this to work was giving the [data-panel] a line-height: 0 and transitioning it when it becomes active (THE LINE-HEIGHT ONLY). Also you'll need to make sure the contents of the [data-panel] don't have any margin or padding (until the panel becomes active) or it will completely throw off the UI.
https://codepen.io/oneezy/pen/bGBBEmp
/* Panel
*********************************/
[data-panel] {
overflow: hidden;
line-height: 0;
opacity: 0;
pointer-events: none;
transition: line-height .22s ease-in-out;
}
.active + [data-panel] {
line-height: 1.4;
opacity: 1;
pointer-events: auto;
}
I'm answering my own question; however, I'm not accepting it as the chosen answer. I'd love to see more unique solutions added to this thread.
The short answer is that you can't. Height transitions will only work on elements that use a unit based value for their height property.
Here's an article detailing different techniques to achieve the same outcome: https://css-tricks.com/using-css-transitions-auto-dimensions/

Tooltips show / hide on click with JavaScript / CSS

Trying to make my tooltips show and hide on click. I managed to do it with the first tooltip but this doesn´t work for the others.
I know that the problem might be with the code document.getElementById but I don´t know with which code I have to replace that, so that every tooltip gets triggered one after the other when clicked.
How can I manage that all the tooltips are shown and hidden as the first one?
Thanks for your support! ;)
//Showing the tooltip on click
document.getElementById("website-tooltip-container").addEventListener("click", function() {
var element = document.getElementById("test");
element.classList.add("website-tooltiptext-visible");
});
//Removing tooltip when clicked outside tooltip container or outside tooltip itself
document.addEventListener('mouseup', function(e) {
var container = document.getElementById('test');
if (!container.contains(e.target)) {
container.classList.remove("website-tooltiptext-visible");
}
});
/* Tooltip Container */
.website-tooltip {
position: relative;
display: flex;
justify-content: center;
cursor: pointer;
font-family: Roboto;
font-size: 18px;
font-weight: 400;
color: #666;
}
/* Tooltip text */
.website-tooltip .website-tooltiptext {
visibility: hidden;
max-width: 350px;
font-family: open sans;
font-size: 13px;
line-height: 22px;
background-color: #FFFFFF;
color: #666;
text-align: left;
padding: 11px 15px 11px 15px !important;
border-radius: 3px;
box-shadow: 0px 5px 10px -2px rgba(0, 0, 0, 0.5);
/* Position the tooltip text */
position: absolute;
z-index: 1;
top: 100%;
margin: 0px 0px 0px 0px;
}
/* Show the tooltip text when you mouse over the tooltip container */
.website-tooltip:hover .website-tooltiptext {
visibility: visible;
}
/* Hide when hovering over tooltip div */
div.website-tooltiptext:hover {
display: none;
}
/* Toggle this class to show Tooltip on click via Javascript */
.website-tooltiptext-visible {
visibility: visible !important;
display: block !important;
}
<div id="website-tooltip-container" class="website-tooltip"><span class="dottedunderline">Tooltip 1</span>
<div id="test" class="website-tooltiptext">Blabalabalbalablablabla.
</div>
</div>
<div id="website-tooltip-container" class="website-tooltip"><span class="dottedunderline">Tooltip 2</span>
<div id="test" class="website-tooltiptext">Blabalabalbalablablabla.
</div>
</div>
<div id="website-tooltip-container" class="website-tooltip"><span class="dottedunderline">Tooltip 3</span>
<div id="test" class="website-tooltiptext">Blabalabalbalablablabla.
</div>
</div>
<div id="website-tooltip-container" class="website-tooltip"><span class="dottedunderline">Tooltip 4</span>
<div id="test" class="website-tooltiptext">Blabalabalbalablablabla.
</div>
</div>
Thanks for your help!
This question got answered in a similar question I made.
Here the link to the question also in stackoverflow
There you will find deeper insights and possible solutions for tooltips via JavaScript or :hover pseudo class.

Using CSS Tooltips in a Multiple-Column DIV

I need to display tooltips for specific terms in a multiple-column div, and I need them to work across multiple browsers. I began with the w3schools CSS Tooltip example, which works great in a normal (single-column) container. But with multiple columns, Chrome has some serious (perhaps not deal-breaking) formatting issues, and Safari fails badly, cropping the tooltip to the column in which it should appear. Firefox works properly.
Firefox:
Chrome:
Safari:
I thought perhaps Safari was treating overflow as though it were set to hidden, but if so, I couldn't find any way to change its behavior. And I couldn't find any existing questions that address tooltip formatting problems in multi-column layouts.
Now I'm worried that I may have to bite the bullet and write the custom javascript to detect hover, grab the text of the tooltip, stuff the text into a div that floats above the content of my page, reveal the div properly positioned in relation to the link, and hide it again when the mouse moves off the link. Obviously, it would be a lot easier if I could make the w3schools tooltip code work with multiple columns. (Using a table or grid in place of multiple columns is not an for this project.)
Has anyone else encountered (and hopefully solved) this issue?
Here's my code; if you run the snippet you'll see that the upper div shows a normal single-column div that works fine across browsers; the lower div is the two-column div that generated the screenshots above.
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 150px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px;
border-radius: 6px;
/* Position the tooltip text */
position: absolute;
z-index: 1;
top: 160%;
left: 50%;
margin-left: -75px;
/* Use half of the width (150/2 = 75), to center the tooltip */
}
.tooltip .tooltiptext::after {
/* Add an arrow */
content: " ";
position: absolute;
bottom: 100%;
/* At the top of the tooltip */
left: 50%;
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: transparent transparent black transparent;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
.contentDiv {
margin-left: 50px;
padding: 5px;
width: 100px;
border: 1px solid black;
}
.contentDiv p {
margin: 0;
}
.contentDiv.twoColumn {
width: 210px;
column-count: 2;
-moz-column-count: 2;
-webkit-column-count: 2;
column-rule: 1px solid black;
-moz-column-rule: 1px solid black;
-webkit-column-rule: 1px solid black;
}
<div class="contentDiv">
<p>
<span class="tooltip">Hover 1
<span class="tooltiptext">Tooltip text for Hover #1.</span>
</span>
</p>
<p>
<span class="tooltip">Hover 2
<span class="tooltiptext">Tooltip text for Hover #2.</span>
</span>
</p>
</div>
<div style="clear:both;"></div>
<br>
<div class="contentDiv twoColumn">
<p>
<span class="tooltip">Hover 3
<span class="tooltiptext">Tooltip text for Hover #3.</span>
</span>
</p>
<p>
<span class="tooltip">Hover 4
<span class="tooltiptext">Tooltip text for Hover #4.</span>
</span>
</p>
</div>
Link to JsFiddle
.tooltip .tooltiptext {
-webkit-column-break-inside: avoid;
-webkit-backface-visibility: hidden;
}
This can fix for the overflow part but i notice that the last item of the column, the tooltip will still go up instead of below it.
Feel like column overflow issue still haven't fix for chrome yet, maybe can try to use flex.
The incompatibilities among browsers have defeated my effort to find a css-only solution, so I bit the bullet, added a bit of javascript, and provide below a solution that works for me. This solution supports both text tooltips (which can include html markup) and picture tooltips.
$(function() {
var $tip;
function makeTip () {
$(document.body).append ("<div id='tooltip'></div>");
$tip = $("#tooltip");
}
$(".tipLink").hover (function () {
var st = $(this).data ("tip"),
rect = this.getBoundingClientRect(),
hasImage = st.match(/^<img/) ? true : false,
bottomPadding = hasImage ? "5px" : "10px";
if (!$tip) {
makeTip ();
}
// It'd be good to preload the image!
$tip.html (st);
// Center tooltip and arrow below link.
$tip.css ({"display":"block",
"top": window.pageYOffset + rect.bottom + 10 + "px",
"left": window.pageXOffset + rect.left + rect.width/2,
"padding-bottom": bottomPadding});
},
function () {
$tip.css ("display", "none");
});
});
#tooltip {
display: none;
background-color: #444;
font-family:"Times New Roman", Times, serif;
font-size: 1.2rem;
line-height: 1.3rem;
color: #fff;
text-align: center;
padding: 10px;
border-radius: 6px;
/* Position the tooltip text */
position: absolute;
z-index: 1;
max-width: 200px;
transform: translateX(-50%); /* translate left by half the tip width */
}
#tooltip::after { /* Add an arrow */
content: " ";
position: absolute;
bottom: 100%; /* At the top of the tooltip */
left: 50%; /* Centered horizontally */
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: transparent transparent #444 transparent;
}
/* The styles below are for the demo, and aren't needed in actual use. */
.contentDiv {
margin-left: 100px;
padding: 5px;
width: 150px;
border: 1px solid black;
}
.contentDiv p {
margin: 0;
}
.contentDiv.twoColumn {
width: 300px;
column-count:2;
-moz-column-count: 2;
-webkit-column-count: 2;
column-rule: 1px solid black;
-moz-column-rule: 1px solid black;
-webkit-column-rule: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class = "contentDiv">
<p>
Item 1: <span class="tipLink" data-tip="Tooltip text for Hover #1.">Hover 1</span>
</p>
<p>
Item 2: <span class="tipLink" data-tip="Tooltip text for Hover #2.">Hover 2</span>
</p>
</div>
<div style="clear:both;"></div>
<br>
<div class = "contentDiv twoColumn">
<p>
Item 3: <span class="tipLink" data-tip="Tooltip text for Hover #3.">Hover 3</span>
</p>
<p>
Item 4: <span class="tipLink" data-tip="<img src='https://upload.wikimedia.org/wikipedia/commons/thumb/archive/b/b3/20091118075632%21UN_flag.png/120px-UN_flag.png'>">Hover 4</span>
</p>
</div>
This solution (using jQuery) shows the tooltip text when you mouse over a tipLink element, such as this span:
<span class="tipLink" data-tip="Tooltip text">Link</span>
In this example, "Link" is the text on the page, and the contents of the data-tip are displayed as the tooltip when the user hovers over the word "Link".
Alternatively you can use the data-tip to specify an img element that will appear as the tip.
This code centers the tooltip below the tipLink element, and the tooltips appear properly in multi-column layouts on at least FireFox, Safari, and Chrome.
I hope others who want to make tooltips available in multi-column page elements may find this useful.

Mysterious whitespace in firefox

There's a mysterious whitespace along the right of my site in firefox (on both PC and Mac, latest versions) and I can't for the life of me figure out what's causing it.
This is what it looks like -
I've been searching the CSS for ages now trying to figure out if it's some margin or padding issue but I can't find anything.
Also, if I remove the div ID 'slider3' the issue seems to disappear, yet I can't figure out how this div is causing the whitespace, since it has no CSS applied to it - it's simply a container.
Here's my site http://www.simplerweb.co.uk
Here's some relevant code so the answer is useful for people later on.
<div class="fullw">
<div class="sliderleft"></div>
<div class="sliderright"></div>
<div id="slider3">
<div class="quote">
<div class="centmid">
<h1 class="fronth">Hello</h1>
<h2 class="frontp">Welcome to Simpler Web</h2>
<h2 class="frontp2">We're an Edinburgh based Web<br> Design Agency</h2>
</div><!-- end div centmid -->
</div> <!-- end div quotes1 -->
<div class="quote2">
<div class="centmid">
<h2 class="frontb">We make wonderful, cross platform <br> accessible Websites </h2>
</div> <!-- end div centmid -->
</div> <!-- end div quotes2 -->
<div class="quote3">
<div class="centmid">
<h2 class="frontc">We can translate your ideas into reality </h2>
</div> <!-- end div centmid -->
</div><!-- end div quotes3 -->
</div> <!-- #slider3 -->
</div>
CSS
/* The following styles are essential to the slider's functionality */
.plusslider {
overflow: hidden;
position: relative;
padding-top: 140px; /* The height / width of the slider should never be set via the CSS. The padding increases the slider box-model while keeping it dynamic */
}
.plusslider-container { position: relative; }
/* Slides must have a set width - even though they may be dynamic. If no width is set on <img> slides, the default image size will be assumed */
div.child { width: 480px; }
.plusslider .child { float: left; }
/* PlusFader Specific (not needed with plustype:slider */
.plustype-fader .child { display: none; position: absolute; left: 0; top: 0; }
.plustype-fader .current { z-index: 5; }
/* End PlusFader Specific */
/* No-javascript fallback -- change "#slider" and "#slider2" identifiers as needed for your html */
#slider > * { display: none; }
#slider > *:first-child, #slider2 > *:first-child { display: block; }
/* End no-javascript fallback */
/* End essential styles*/
/* The following styles are not essential for slider functionality. They are specific to the example content.
It is important to note that the fading effect does not work correctly with non-image content unless that
content area has a solid background (either a background image or a background-color, but not transparent).
Slides to not have to be the same width or height, but if you'd like a consistent width and/or height, make sure to set that within the CSS! */
#slider .slide1 { padding-left: 40px; padding-right: 40px; margin-left: 0; margin-right: 0; }
#slider .slide1 { height: 210px; padding-top: 20px; padding-bottom: 20px; margin-top: 0; margin-bottom: 0; }
.slide1 { height: 500px; padding: 20px 40px; }
.slide1 h2 { color: #fff; font-size: 20px; margin: 0 0 20px 0; text-align: left; }
.slide1 p { border-left: 3px solid #fff; color: #fff; padding: 0 0 0 10px; }
.quote, .quote2, .quote3 { height:400px; padding: 20px 0; width: 980px; width: 100%; position: relative; }
.quote { background-image: url(../images/weare.png); background-position: center; background-repeat: no-repeat; }
.quote2 { background-image: url(../images/headlogosandroid.png); background-position: center; background-repeat: no-repeat; }
.quote3 { background-image: url(../images/ideafront.png); background-position: center; background-repeat: no-repeat; }
.plusslider a img { border: none; } /* Prevent blue borders in IE (not only does it look ugly, but it messes up spacing which breaks the "slider" type */
.plusslider-pagination { position: absolute; left: 0; bottom: 0; }
.plusslider-pagination li { float: left; list-style: none; margin-left: 5px; }
#slider3 {margin: 0; padding: 0;}
You have (in FF) exactly 17px extra width that is exactly the width of the browser scrollbar.
Your starting (initial) loading black screen (that animates) leaves a glitch of 17px:
cause it's animation maintains the DOM width that equals the screen width without the right scrollbar (100% screen width).
After the page is fully loaded and the scrollbar is added to the page, it actually adds the extra 17px (to the 100%) width that were maintained by the Loading animation.
Hope I put you in the right direction.
By the way, try to add:
html {
overflow-y: scroll;
}
and - if still needed - adjust the loading element width as I mentioned before.
Add this:
body{
overflow-x: hidden;
}
Problem solved. (temporarily)
So where is the problem?
It is at your <div> with the classes plusslider slider3 plustype-slider. You are constantly setting an incorrect width to it. You have to subtract the scrollbar width.
You can also try to do this: Padding: 0px(or whatever) 17px; and margin: 0px(or whatever) -17px; now your whitespace at the sides are gone.

Categories

Resources