Mouseover and mouseout for multiple element - javascript

Using Javascript, I have multiple element and when I hover that element, it changes the content and element.
I tried using mouseover and mouseout, it's working for single element, but doesn't work when I have multiple element.
I add loops for the parent, but still not working, also now when I hover the first element, it's just looping over.
What am I doing wrong?
const wrapper = document.querySelectorAll(".wrapper");
wrapper.forEach(function () {
let mouseWhite = document.querySelector(".commercial-white");
let mouseBlue = document.querySelector(".commercial-blue");
mouseWhite.addEventListener("mouseover", function (e) {
mouseBlue.classList.add("open");
e.stopPropagation();
})
mouseBlue.addEventListener("mouseout", function (e) {
mouseBlue.classList.remove("open");
e.stopPropagation();
})
})
.wrapper {
display: flex;
position: relative;
}
.commercial-white {
background-color: #f1f1f4;
width: 240px;
height: 260px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-bottom: 15px solid #005da0;
margin: 10px;
}
.commercial-blue {
position: absolute;
background-color: #005da0;
color: #FFFFFF;
width: 240px;
height: 273px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10px;
border: 2px solid #FFFFFF;
visibility: hidden;
}
.open.commercial-blue {
visibility: visible;
}
.commercial-flip {
padding: 20px;
}
<div class="wrapper">
<div class="commercial-white">
<div class="commercial-flip">
<img style="width:100px" src="http://g-ec2.images-amazon.com/images/G/31/img14/anywhere/amazon-logo-500500._V327001990_.jpg">
<h1>Your title</h1>
</div>
</div>
<div class="commercial-blue">
<div class="commercial-flip">
<img style="width:100px" src="https://images-na.ssl-images-amazon.com/images/G/01/gc/designs/livepreview/amazon_dkblue_noto_email_v2016_us-main._CB468775337_.png">
<h1>Lorem Ipsum</h1>
<p>lorem ipsum dolor si amet lorem ipsum dolor si amet lorem ipsum dolor si amet</p>
</div>
</div>
</div>
<div class="wrapper">
<div class="commercial-white">
<div class="commercial-flip">
<img style="width:100px" src="http://g-ec2.images-amazon.com/images/G/31/img14/anywhere/amazon-logo-500500._V327001990_.jpg">
<h1>Your title</h1>
</div>
</div>
<div class="commercial-blue">
<div class="commercial-flip">
<img style="width:100px" src="https://images-na.ssl-images-amazon.com/images/G/01/gc/designs/livepreview/amazon_dkblue_noto_email_v2016_us-main._CB468775337_.png">
<h1>Lorem Ipsum</h1>
<p>lorem ipsum dolor si amet lorem ipsum dolor si amet lorem ipsum dolor si amet</p>
</div>
</div>
</div>

You need to 'querySelect' on each wrapper, not the document because in your code document.querySelector(".commercial-white") will only give you the first occurence of .commercial-white .. and it will do that twice, but it will still be the same occurence... the first one in the document (twice).
Your querySelectorAll gave you a NodeList of elements wrapper.
forEach will go through each element of your NodeList (kind of) like an array. wrapper[0] wrapper[1]...
The argument aWrapper is just the name for "The current element being processed in the NodeList".
This way, aWrapper.querySelector will only "select" within the current element wrapper in the loop.
wrapper.forEach(function (aWrapper) {
let mouseWhite = aWrapper.querySelector(".commercial-white");
let mouseBlue = aWrapper.querySelector(".commercial-blue");
const wrapper = document.querySelectorAll(".wrapper");
wrapper.forEach(function(aWrapper) {
let mouseWhite = aWrapper.querySelector(".commercial-white");
let mouseBlue = aWrapper.querySelector(".commercial-blue");
mouseWhite.addEventListener("mouseenter", function(e) {
console.log("e.target.classList mouseWhite :", e.target.classList);
mouseBlue.classList.toggle("open");
})
mouseBlue.addEventListener("mouseout", function(e) {
console.log("e.target.classList mouseBlue :", e.target.classList);
mouseBlue.classList.toggle("open");
})
})
.wrapper {
display: flex;
position: relative;
}
.commercial-white {
background-color: #f1f1f4;
width: 240px;
height: 260px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-bottom: 15px solid #005da0;
margin: 10px;
}
.commercial-blue {
position: absolute;
background-color: #005da0;
color: #FFFFFF;
width: 240px;
height: 273px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10px;
border: 2px solid #FFFFFF;
visibility: hidden;
}
.open.commercial-blue {
visibility: visible;
}
.commercial-flip {
padding: 20px;
pointer-events: none;
}
<div class="wrapper">
<div class="commercial-white">
<div class="commercial-flip">
<img style="width:100px" src="http://g-ec2.images-amazon.com/images/G/31/img14/anywhere/amazon-logo-500500._V327001990_.jpg">
<h1>Your title</h1>
</div>
</div>
<div class="commercial-blue">
<div class="commercial-flip">
<img style="width:100px" src="https://images-na.ssl-images-amazon.com/images/G/01/gc/designs/livepreview/amazon_dkblue_noto_email_v2016_us-main._CB468775337_.png">
<h1>Lorem Ipsum</h1>
<p>lorem ipsum dolor si amet lorem ipsum dolor si amet lorem ipsum dolor si amet</p>
</div>
</div>
</div>
<div class="wrapper">
<div class="commercial-white">
<div class="commercial-flip">
<img style="width:100px" src="http://g-ec2.images-amazon.com/images/G/31/img14/anywhere/amazon-logo-500500._V327001990_.jpg">
<h1>Your title</h1>
</div>
</div>
<div class="commercial-blue">
<div class="commercial-flip">
<img style="width:100px" src="https://images-na.ssl-images-amazon.com/images/G/01/gc/designs/livepreview/amazon_dkblue_noto_email_v2016_us-main._CB468775337_.png">
<h1>Lorem Ipsum</h1>
<p>lorem ipsum dolor si amet lorem ipsum dolor si amet lorem ipsum dolor si amet</p>
</div>
</div>
</div>
Edit :
For the buggy display I just added "pointer-events: none;" to .commercial-flip and it was enough :
.commercial-flip {
padding: 20px;
pointer-events: none; }
I am fairly new to JS (so I may be wrong), but if I understand correctly, it work because if .commercial-flip can receive pointer events then when it's hovered, it's parent is not.
Before this modification, as long as you didn't enter the border of .commercial-flip it worked just fine.
So apparently hovering a child isn't the same as hovering it's parent if the child can catch the event, but if it can't it's all good.
Edit : Preventing Child from firing parent's click event
Note : I used classList.toggle instead of classList.add and classList.remove, and mousenter instead of mouseover but it's just a personal preference here ; it gives the exact same result.

You have to query the childs:
wrapper.forEach(function (el) {
let mouseWhite = el.querySelector(".commercial-white");
let mouseBlue = el.querySelector(".commercial-blue");
....

You're looping over each one but using the same selector which causes some issues. Just change your loop to the following so there's a reference to each element:
wrapper.forEach(function (el) {
let mouseWhite = el.querySelector(".commercial-white");
let mouseBlue = el.querySelector(".commercial-blue");
mouseWhite.addEventListener("mouseover", function (e) {
mouseBlue.classList.add("open");
e.stopPropagation();
})
mouseBlue.addEventListener("mouseout", function (e) {
mouseBlue.classList.remove("open");
e.stopPropagation();
})
})

Related

How do I use jQuery toggle class to add class or remove element?

I'm not sure why my code is not responding, everything looks correct to me. I'm new to using jQuery and trying to use toggleClass to have card info displayed when the card on my page is clicked. Initially, I'd like it to be hidden but able to be toggled on and off.
$(document).ready(function() {
$('.card').click(function() {
$(this).toggleClass('inner-card.active');
});
});
.card {
display: flex;
flex-direction: column;
justify-content: end;
width: 350px;
height: 180px;
background: lightgreen;
border: 2px solid black;
margin-left: 8px;
margin-bottom: 8px;
cursor: pointer;
}
.inner-card .active {
display: none;
}
.inner-card {
display: flex;
flex-direction: column;
justify-content: end;
background: rgba(255, 165, 0, 0.5)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
<div class="inner-card">
<h5>Title</h5>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sunt, libero?</p>
Link goes here
<div class="img-div">
<img src="../static/img/search.png" class="card-img" alt="">
</div>
</div>
</div>
It should go from this
To this
I believe there are several problems. First of all, I believe you want to write the display:none CSS logic this way:
.inner-card.active{
display: none;
}
This means that the inner card will be hidden if it also has the active class.
Secondly, I believe you need to rewrite the script this way:
$(document).ready( function(){
$('.card').click( function() {
$(this).find(".inner-card").toggleClass('active');
});
});
When you use the toggleClass you need to use just the name of the class, not the selector (-> no dot). Also, from the CSS, it looks like you need to find the inner card element first.
Fiddle link
You probably want something like this:
$(document).ready(function() {
$('.card').click(function() {
$(this).find(".inner-card").toggleClass('hidden');
});
});
.card {
display: flex;
flex-direction: column;
justify-content: end;
width: 350px;
height: 180px;
background: lightgreen;
border: 2px solid black;
margin-left: 8px;
margin-bottom: 8px;
cursor: pointer;
}
.hidden {
display: none !important;
}
.inner-card {
display: flex;
flex-direction: column;
justify-content: end;
background: rgba(255, 165, 0, 0.5)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
<div class="inner-card hidden">
<h5>Title</h5>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sunt, libero?</p>
Link goes here
<div class="img-div">
<img src="../static/img/search.png" class="card-img" alt="magnify lens">
</div>
</div>
</div>

i get "Uncaught TypeError: Cannot read property 'toggle' of undefined" everytime i click on the image

i tried to make an element appear after a user clicks on an image. i used classlist.toggle for that but when i click on the image the error message "Uncaught TypeError: Cannot read property 'toggle' of undefined" appears in the console. And of course it is not working 🙁
const plusbtn = document.querySelector(".btn-img");
const drop = document.getElementsByClassName("boxes")
plusbtn.addEventListener('click', () => {
drop.classList.toggle("box-drop");
})
.boxes {
border: 1px solid rgba(39, 81, 197, 0.39);
margin-top: 50px;
padding: 15px;
display: none;
flex-direction: row;
justify-content: space-around;
}
.btn-img {
align-self: center;
filter: grayscale(50%);
cursor: pointer;
}
.box-drop {
display: flex;
}
<section>
<h1>RESOURCES</h1>
<div class="resource-boxes">
<div class="box1">
<div class="top">
<img src="../images/plus.png" alt="" class="btn-img">
</div>
<div class="boxes">
<a href="">
<div class="minibox">
<span class="minibox-txt">Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet consectetur, adipisicing elit. Numquam, enim! </span>
</div>
</a>
</div>
</div>
</div>
</section>
getElementsByClassName returns a HTMLCollection. You need to loop every element in that collection in order to access it.
But, since you already use .querySelector() you could as well
use .querySelectorAll() which returns a NodeList which offers by default a .forEach() Method
Instead of hiding elements where they are styles-defined, use instead a reusable utility class like .u-none{ display: none; }
const EL_btnPlus = document.querySelector(".btn-img");
const ELS_drop = document.querySelectorAll(".boxes");
EL_btnPlus.addEventListener('click', () => {
ELS_drop.forEach(EL => EL.classList.toggle("u-none"));
});
.boxes {
display: flex;
}
/* Utility classes */
.u-none {
display: none;
}
<img class="btn-img" src="https://lh3.googleusercontent.com/a/AATXAJzyljorAsMuzZ3OQ6B7g_2EU0bkA4lk3iH076AR=k-s64" alt="">
<div class="boxes u-none">Box one</div>
<div class="boxes u-none">Box two</div>
drop is a list of elements (see the return value of getElementsByClassName). You have to loop through it and toggle the class on each individual element:
const plusbtn = document.querySelector(".btn-img");
const drop = [...document.getElementsByClassName("boxes")];
plusbtn.addEventListener('click', () => {
drop.forEach(e => e.classList.toggle("box-drop"));
})
.boxes {
border: 1px solid rgba(39, 81, 197, 0.39);
margin-top: 50px;
padding: 15px;
display: none;
flex-direction: row;
justify-content: space-around;
}
.btn-img {
align-self: center;
filter: grayscale(50%);
cursor: pointer;
}
.box-drop {
display: flex;
}
<section>
<h1>RESOURCES</h1>
<div class="resource-boxes">
<div class="box1">
<div class="top">
<img src="https://www.gravatar.com/avatar/0fdacb141bca7fa57c392b5f03872176?s=48&d=identicon&r=PG&f=1" alt="" class="btn-img">
</div>
<div class="boxes">
<a href="">
<div class="minibox">
<span class="minibox-txt">Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet consectetur, adipisicing elit. Numquam, enim! </span>
</div>
</a>
</div>
</div>
</div>
</section>

highlighting an active tab with vanilla JS

I am creating a tabbed navigation bar wherein when the tab is active it should change its color the color that i set it to change with. Navigating thru the pages with the tabs works fine however the color highlight on the active tab just don't seem to work.
here is my code so far:
HTML:
<section class="tab" id="active_Current_Tabs">
<header>Active/Current Tabs</header>
<nav class="navbar">
<ul>
<li class="btn currentTab" onclick="activeTab(event, 'lorem7')">TAB1</li>
<li class="btn currentTab" onclick="activeTab(event, 'lorem8')">TAB2</li>
<li class="btn currentTab" onclick="activeTab(event, 'lorem9')">TAB3</li>
</ul>
</nav>
<main class="main-doc">
<article class="selectedPage" id='lorem7'>
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
<article class="selectedPage" id="lorem8">
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
<article class="selectedPage" id="lorem9">
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
</main>
</section>
CSS:
article {
text-align: center;
width: 100%;
height: 300px;
max-height: 300px;
margin: 0;
}
/*navbar css*/
nav {
width: 100%;
height: 75px;
padding: 0;
margin: 0;
}
nav ul {
height: 100%;
padding: 0;
display: flex;
list-style: none;
justify-content: space-around;
}
.btn {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
width: 100%;
height: 100%;
background-color: #8b9d98;
cursor: pointer;
font-weight: 500;
}
.btn:hover {
background-color: #d7e0e0;
font-weight: 700;
transition: .5s;
}
/*main css*/
main {
margin-top: 0;
}
/*Active/Current Tab */
#lorem7 {
display: flex;
flex-direction: column;
background-color: #49c2a4;
align-items: center;
justify-content: center;
}
#lorem8 {
display: none;
flex-direction: column;
background-color:#35386f;
align-items: center;
justify-content: center;
}
#lorem9 {
display: none;
flex-direction: column;
background-color:#e28968;
align-items: center;
justify-content: center;
}
Javascript:
// active/current tab function
function activeTab(evnt, currPage) {
var currenttab;
var pages = document.getElementsByClassName('selectedPage');
for (i = 0; i < pages.length; i++) {
pages[i].style.display = "none";
}
//for dehighlighting inactive tabs
currenttab = document.getElementsByClassName('currentTab');
for(j = 0; j < currenttab.length; j++) {
currenttab[j].className = currenttab[j].className.replace("green", " ");
}
document.getElementById(currPage).style.display = "flex";
evnt.currentTarget.className += "green"; //this appends the color to active tab
}
help please! T_T
I'm not sure what you were trying to do with the "green" class because there were no rules for it in your CSS. I answered the question assuming you wanted the active tab to be the same color as the active page. Sorry if that's not what you intended, but I think it makes sense.
To avoid problems with specific class names, you can use .classList methods like "add" and "remove". This way you don't have to worry about the order of class names in the markup. Examples:
tabs[i].classList.remove('active')
e.currentTarget.classList.add('active')
You can also attach your event listener (click handler) dynamically to keep your HTML uncluttered. Example:
for(j = 0; j < tabs.length; j++) {
// attach event listener to all tabs
tabs[j].addEventListener('click', clickTab)
}
You can also make your CSS less repetitive by assigning similar styles to a common class:
.page {display:none;}
.page.active {
display:flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
I modified your IDs in order to be able to reference tabs and pages independently without explicitly passing parameters to the click handler functions. Example:
<li id="t2" class="tab">TAB2</li>
...
<article class="page" id="p2">...</article>
Here is my JS Bin:
http://jsbin.com/defidih/edit?html,css,js,console,output
evnt.currentTarget.className += "green";
This line will add to the already existing className.
So your class class="btn currentTab"
becomes class="btn currentTabgreen"
instead of class="btn currentTab green" if you didn't add green to it before.
So it would better to use currenttab[j].className.replace("green", ""); to reset the previous green classes and evnt.currentTarget.className += " green"; to set the new green class.
Edit: this does imply that the classname will keep growing with one space every time. SO the optimal would be to use classList.add() and classList.remove() instead of manually editting the class string.
function activeTab(evnt, currPage) {
var currenttab;
var pages = document.getElementsByClassName('selectedPage');
for (i = 0; i < pages.length; i++) {
pages[i].style.display = "none";
}
//for dehighlighting inactive tabs
currenttab = document.getElementsByClassName('currentTab');
for(j = 0; j < currenttab.length; j++) {
currenttab[j].className = currenttab[j].className.replace("green", "");
}
document.getElementById(currPage).style.display = "flex";
evnt.currentTarget.className += " green"; //this appends the color to active tab
}
article {
text-align: center;
width: 100%;
height: 300px;
max-height: 300px;
margin: 0;
}
/*navbar css*/
nav {
width: 100%;
height: 75px;
padding: 0;
margin: 0;
}
nav ul {
height: 100%;
padding: 0;
display: flex;
list-style: none;
justify-content: space-around;
}
.btn {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
width: 100%;
height: 100%;
background-color: #8b9d98;
cursor: pointer;
font-weight: 500;
}
.btn:hover {
background-color: #d7e0e0;
font-weight: 700;
transition: .5s;
}
/*main css*/
main {
margin-top: 0;
}
/*Active/Current Tab */
#lorem7 {
display: flex;
flex-direction: column;
background-color: #49c2a4;
align-items: center;
justify-content: center;
}
#lorem8 {
display: none;
flex-direction: column;
background-color:#35386f;
align-items: center;
justify-content: center;
}
#lorem9 {
display: none;
flex-direction: column;
background-color:#e28968;
align-items: center;
justify-content: center;
}
.green {
background-color: green;
}
<section class="tab" id="active_Current_Tabs">
<header>Active/Current Tabs</header>
<nav class="navbar">
<ul>
<li class="btn currentTab" onclick="activeTab(event, 'lorem7')">TAB1</li>
<li class="btn currentTab" onclick="activeTab(event, 'lorem8')">TAB2</li>
<li class="btn currentTab" onclick="activeTab(event, 'lorem9')">TAB3</li>
</ul>
</nav>
<main class="main-doc">
<article class="selectedPage" id='lorem7'>
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
<article class="selectedPage" id="lorem8">
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
<article class="selectedPage" id="lorem9">
<h2>Lorem</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus, est?</p>
</article>
</main>
</section>
To create a tabbed navigation bar wherein when the tab is active it should change its color to a custom color that you have set. You could use this few lines of vanilla JavaScript.
JS:
var activeTab;
var acctOptions = document
.querySelector(".account-options")
.querySelectorAll("li");
acctOptions.forEach(option => {
option.addEventListener("click", function() {
if (activeTab) activeTab.classList.remove("active");
activeTab = option;
activeTab.classList.add("active");
});
});
CSS:
.active {
background: blue;
}
HTML:
<ul class="account-options">
<li class='login'><a>Login</a></li>
<li class='register'>Register</li>
<li class='account' ><a>My Account</a></li>
<li class='reward-points'><a>Reward Points</a></li>
<li class='password-reset'><a>Reset Password</a></li>
<li class='logout'><a>Logout</a></li>
</ul>

Make div expand to take all the available space [duplicate]

This question already has answers here:
Make a div fill the height of the remaining screen space
(41 answers)
Closed 5 years ago.
I want a desktop-like full-page width layout.
Some menu at the top (uknown height, depending on the content),
and div underneath that takes ALL the available space in viewport.
div {
padding: 0px
}
html,
body {
height: 100%;
padding: 0px;
margin: 0px;
}
.outer {
background: olive;
height: 100%;
}
.menu {
background: orange;
}
.should_fill_available_space {
background: brown;
}
<div class="outer">
<div class="menu">
Lorem Ipsum Lorem Ipsum Lorem Ipsum
</div>
<div id="this" class="should_fill_available_space">
Brown color should go all the way down
</div>
</div>
I've got a codepen for this case:
https://codepen.io/marek-zganiacz/pen/NvEaxr
I want should_fill_available_space go all way down, as in the case where menu would have height:10% and should_fill_available_space have 'height:90%`.
The easiest way to achieve this is using flexbox.
You assign display: flex to the parent container. in your case this is outer .outer.
a flexbox works in a single direction. So you can look at them like a column (vertical) or row(horizontal). The default setting is that it spreads the children elements out over a row. But we want to create a column. Therefore we have to change the flex-direction on .outer to flex-direction: column.
Now we need to specify how we want the flexbox to divide the amount of space available in the .outer. Normal behaviour is that the flexbox gives its children their normal width/height. But by assigning flex:1 to .should_fill_available_space, this element will get all the extra available space. What the flexbox basically says is that we want the computer to use all 1/1 = 100% (used flex value divided by the total flex value of all children) available room to apply to .should_fill_available_space, while keeping minimal space for the .menu width. Technically flex: is a shorthand for some other properties, but that doesn't really matter for this question.
Here is your JS-Fiddle: https://jsfiddle.net/cryh53L7/
html
<div class="outer">
<div class="menu">
Lorem Ipsum
Lorem Ipsum
Lorem Ipsum
</div>
<div id="this" class="should_fill_available_space">
Brown color should go all the way down
</div>
</div>
css
div{
padding: 0px
}
html, body{
height: 100%;
padding: 0px;
margin: 0px;
}
.outer {
display: flex;
flex-direction: column;
background: olive;
height: 100%;
}
.menu{
background: orange;
}
.should_fill_available_space{
flex: 1;
background: brown;
}
Try this!
I used a table display, I hope it is okay for you :)
HTML:
<div class="outer">
<div class="menu">
Lorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
Lorem Ipsum
Lorem IpsumLorem Ipsum
</div>
<div id="this" class="should_fill_available_space">
Brown color should go all the way down
</div>
CSS:
div{
padding: 0px
}
html, body{
height: 100%;
padding: 0px;
margin: 0px;
}
.outer {
background: olive;
height: 100%;
display:table;
width:100%;
}
.menu{
background: orange;
display:table-row;
}
.should_fill_available_space{
background: brown;
display:table-row;
}
div+ div{
height:100%;
}
You can achieve this with flexbox in CSS3 (https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
Update your CSS like this to see it working:
.outer {
background: olive;
height: 100%;
display: flex;
flex-direction: column;
}
.should_fill_available_space{
background: brown;
flex-grow: 2;
}
This is where the world of web document standards meets viewport based desktop application emulation. You need containers to be positioned absolute. Within these containers you will be able to setup relative position elements or use elements that will use the html flow.
There are numerous APIs out there which will do just that under the covers and they will invariably rely on javascript calculations to place elements according to their dimensions after being attached to the DOM.
Here is a simple example based on your code:
div{
padding: 0px
}
html, body{
height: 100%;
padding: 0px;
margin: 0px;
}
.outer {
background: olive;
height: 100%;
width:100%
position:absolute;
}
.menu{
background: orange;
}
.should_fill_available_space{
background: brown;
position:absolute;
bottom:0px;
width:100vw;
}
<div class="outer">
<div id="menu" class="menu">
Lorem Ipsum
Lorem Ipsum
Lorem Ipsum
</div>
<div id="this" class="should_fill_available_space">
Brown color should go all the way down
</div>
</div>
As I mentioned, you can use javascript to retrieve the dimension of the menu and than apply that to your layout.
window.addEventListener("load", function load(event){
var menu = document.getElementById("menu");
var main = document.getElementById("this");
var menuHeight = menu.offsetHeight;
main.style.top = menuHeight + "px";
},false);
And here is the codepen.

Position child elements of a flexbox with position relative and the top property (right property works but top doesn't)

<div class="b-wrapper d-flex d-flex-center">
<div class="inner-wrapper">
<h2 class="b-animate h b-from-top b-delay03">Project 3</h2>
<p class="b-animate p b-from-right b-delay03">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
When trying to add the styles of position: relative; right: -100%; to the h2 element the text moves right 100%. However, if I change the styles to position: relative; top: -100%; the text refuses to move up 100%. I'm assuming this has someting to do with flexbox and positioning. What should I do to fix this?
.d-flex-center {
justify-content: center;
align-items: center;
}
.d-flex {
display: flex!important;
}
.b-wrapper .inner-wrapper {
margin: 0 15px -17px 15px;
}
Top positioning is not working here, because you are using a percentage value, while the container has no height. It would be the same for a positive value too.
To see your top/bottom positioning take effect, either
Give the containing element a height, so the percentage value will be calculated based on that
or
Use a pixel value for top/bottom positioning
Using % value
Parent container must have specified height, so that percentage will be calculated correctly.
.d-flex-center {
justify-content: center;
align-items: center;
}
.d-flex {
display: flex!important;
}
.b-wrapper .inner-wrapper {
margin: 0 15px -17px 15px;
}
.inner-wrapper {
height: 150px; /* container height */
}
h2 {
position: relative;
right: -40%;
top: -20%; /* -20% is now equivalent to -30px (20% of 150px height) */
}
<div class="b-wrapper d-flex d-flex-center">
<div class="inner-wrapper">
<h2 class="b-animate h b-from-top b-delay03">Project 3</h2>
<p class="b-animate p b-from-right b-delay03">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
Using px value
Pixel value will always be consistent, as it is not calculated based on another value. (No need to specify height on parent container.)
.d-flex-center {
justify-content: center;
align-items: center;
}
.d-flex {
display: flex!important;
}
.b-wrapper .inner-wrapper {
margin: 0 15px -17px 15px;
}
h2 {
position: relative;
right: -40%;
top: -30px; /* -30px === -30px */
}
<div class="b-wrapper d-flex d-flex-center">
<div class="inner-wrapper">
<h2 class="b-animate h b-from-top b-delay03">Project 3</h2>
<p class="b-animate p b-from-right b-delay03">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>

Categories

Resources