Flexbox inheritence issue - javascript

I am building a simple website. I have flex boxes full of "modules" which contain text content. When one of these modules is hovered over (using javascript code that is not included in this post because it works fine) I would like a "shade" to appear which darkens the entire module and displays a button. I am having a lot of trouble getting the shades to be the correct size: 100% of the width and height of each module. For some reason, height and width are not inherited from module to shade.
HTML:
<div class="support">
<div class="module">
<div class="shade">
<button type="button" class="source_btn">View Source</button>
</div>
<div class="content">
<h1>Homocide rates have skyrocketed in the United States.</h1>
<p>Jeffery Miron, an economist estimates that the homicide rate in America is as much as seventy-five percent higher $
</div>
</div>
<div class="module">
<div class="shade">
<button type="button" class="source_btn">View Source</button>
</div>
<div class="content">
<h1>Drug markets are forced to solve their disputes through violence.</h1>
<p>Because the War on Drugs has forced drug markets into the shadows, there is now way they can settle disputes throu$
</div>
</div>
<div class="module">
<div class="shade">
<button type="button" class="source_btn">View Source</button>
</div>
<div class="content">
<h1>The violence is not only occurring in the United States.</h1>
<p>For some perspective, there have been almost one hundred thousand deaths in Mexico in the past decade caused not b$
</div>
</div>
</div>
CSS:
section .support {
display: flex;
flex-direction: row;
background: var(--bg);
height: 60vh;
}
.module {
flex: 1;
text-align: center;
height: inherit;
}
.module .content h1 {
margin-top: 5rem;
margin-bottom: 5rem;
font-size: 2.5rem;
}
.module .content p {
font-size: 1.5rem;
padding: 0 3rem 0 3rem;
}
.module .shade {
position: absolute;
background: rgba(0,0,0,.6);
}
.shade .source_btn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20%;
height: 20%;
font-size: 2vw;
background: var(--background);
color: var(--accent);
border: 2px solid var(--accent);
border-radius: .5rem;
}
Note that if I change the .shade styling to:
.module .shade {
position: absolute;
background: rgba(0,0,0,.6);
width: 33.33333%;
height: 60vh;
}
I get the exact desired effect IF there are 3 modules. I believe this means that the width and height are inherited from elsewhere, and I do not know why. I need to be able to say width: 100% and height: 100% in the .shade styling to make the shade take up the entire module because there will be a different number of modules per support class.
I am very confused as to why the width and height are not being inherited as I would expect. Since .shade is a child of .module, why aren't the width and height inherited from the .module div?
If I can provide any additional information, please let me know. I will be active.

When you set absolute as a value for position, the parent of the element should have relative as a value for position. Otherwise, the child element can't measure the position and the size of its parent element.
Following css should work for you:
.module {
flex: 1;
text-align: center;
height: inherit;
position: relative;
}
.module .shade {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0,0,0,.6);
}

Related

Parent component not resizing to fit children

I have a <div className="canvas"> element that contains four <div className="stripe stripe-color"> elements that I will be styling dynamically adding random color classes.
I want to use this canvas element as a 'dynamic background'.
As you can see, I have a <div className="children">{props.children}</div> element among the <div className="stripe"/> elements:
const Canvas = (props) => {
return (
<div className="stripe-container">
<div className="children">{props.children}</div>
<div className="stripe stripe-yellow" />
<div className="stripe stripe-green" />
<div className="stripe stripe-red" />
<div className="stripe stripe-purple" />
</div>
);
};
And SCSS:
.stripe-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
padding: 0;
margin: 3vw;
height: 100vh;
}
.children {
position: absolute;
width: calc(100% - 6vw);
}
.stripe-yellow {
background: #fdc111;
}
.stripe-green {
background: #00ad5e;
}
.stripe-red {
background: #d33136;
}
.stripe-purple {
background: #8f3192;
}
The problem here is that <div className="canvas"> won't grow to fit the children's height so if the content in <div className="children">{props.children}</div> becomes too large or if the user uses a smaller viewport, the children will overflow into the height and allow you to scroll, but canvas won't expand to fit it's children.
As additional information, props.children is a React component that contains a list of "card elements" for a restaurant's menu. The cards and its container use flex to wrap around if they don't have enough space horizontally. This is causing the canvas to become too small on smaller viewports. height:100% and their variants won't work either.
Any ideas into how I can get the desired behavior? I'm also open to refactoring as long as my requirement of achieving dynamic color stripes remains.
Here's a minima reproducible example without React:
.stripe-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
padding: 0;
margin: 3vw;
height: 100vh;
}
.children {
position: absolute;
width: calc(100% - 6vw);
}
.stripe {
height: 100%
}
.stripe-yellow {
background: #fdc111;
}
.stripe-green {
background: #00ad5e;
}
.stripe-red {
background: #d33136;
}
.stripe-purple {
background: #8f3192;
}
.child-container {
display: flex;
flex-wrap: wrap;
}
.child {
border: 1px solid white;
margin: 1rem;
width: 25vw;
height: 25vw;
background: lightgray;
opacity: 80%;
}
<div class="stripe-container">
<div class="children">
<div class="child-container">
<div class="child">one</div>
<div class="child">two</div>
<div class="child">three</div>
<div class="child">four</div>
<div class="child">five</div>
<div class="child">six</div>
<div class="child">seven</div>
<div class="child">eight</div>
<div class="child">nine</div>
</div>
</div>
<div class="stripe stripe-yellow"></div>
<div class="stripe stripe-red"></div>
<div class="stripe stripe-green"></div>
<div class="stripe stripe-purple"></div>
</div>
I'm not sure I understand 100% what you're trying to achieve. But I'll try my best to help you.
Removing the absolute from the children and putting it on the stripes instead might do the trick. Additionally, you'll want to position the stripes on 25% of the width to the left respectively.
I don't think you need CSS grid for this anymore, so I removed it and added some small tweaks as well. Let me know if you have any questions or if I got the question wrong.
.stripe-container {
padding: 0;
margin: 3vw;
position: relative;
}
.children {
position: relative;
z-index: 2;
width: 100%;
}
.stripe {
width: 25%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
}
.stripe-yellow {
left: 0;
background: #fdc111;
}
.stripe-green {
left: 25%;
background: #00ad5e;
}
.stripe-red {
left: 50%;
background: #d33136;
}
.stripe-purple {
left: 75%;
background: #8f3192;
}
.child-container {
display: flex;
flex-wrap: wrap;
}
.child {
border: 1px solid white;
margin: 1rem;
width: 25vw;
height: 25vw;
background: lightgray;
opacity: 80%;
box-sizing: border-box;
}
<div class="stripe-container">
<div class="children">
<div class="child-container">
<div class="child">one</div>
<div class="child">two</div>
<div class="child">three</div>
<div class="child">four</div>
<div class="child">five</div>
<div class="child">six</div>
<div class="child">seven</div>
<div class="child">eight</div>
<div class="child">nine</div>
</div>
</div>
<div class="stripe stripe-yellow"></div>
<div class="stripe stripe-red"></div>
<div class="stripe stripe-green"></div>
<div class="stripe stripe-purple"></div>
</div>
This way, the stripes work as a background for the stripe-container no matter the size, and since the children element is no longer absolute, the container is finally able to have the same size as the children.
Why not use a linear gradient for the striped background? You could accomplish what you're trying to do with simpler CSS and without the extraneous markup.
Optional: If you declared custom properties for the stripe colors you could change them simply by setting different values instead of having to rewrite the gradient each time (although the gradient itself isn't complicated or particularly verbose anyway.)
:root {
/*
Using custom properties here to demonstrate
that you could control the stripe colors without
hard-coding them in the stylesheet. an element
could declare its own colors via another class
or even an inline style, e.g.
<div style="--stripe-1: blue">
This isn't required. Just a suggestion.
*/
--stripe-1: #fdc111; /* yellow */
--stripe-2: #00ad5e; /* green */
--stripe-3: #d33136; /* red */
--stripe-4: #8f3192; /* purple */
}
.container {
padding: 0;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
background: linear-gradient(
to right,
var(--stripe-1) 0 25%,
var(--stripe-2) 25% 50%,
var(--stripe-3) 50% 75%,
var(--stripe-4) 75%
);
}
.container > * {
border: 1px solid white;
margin: 1rem;
width: 25vw;
height: 25vw;
background: lightgray;
opacity: 80%;
}
<div class="container">
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>
<div>five</div>
<div>six</div>
<div>seven</div>
<div>eight</div>
<div>nine</div>
</div>

Why is my image taking up more height in the background space than the image itself?

I have inserted an image into a website and now want to write a paragraph in a new div below it. I noticed that there was extra white space and colored each background of the elements pink & red to understand which was causing a problem. The pink is attributed to div of id="parent", and the red is only attributed to the id="hero_image" contained in the parent div. If it's in the parent, why is the red extending beyond the pink? I'm still trying to grasp position in CSS and what the computer "sees".
Here is an image of what I am seeing.
Here is my html & CSS (the nav styling is missing from CSS bc I checked and removed it to make sure it wasn't the issue)
*{
margin: 0;
padding: 0;
border: 0;
}
body {
font-family: 'Noto Sans HK', sans-serif;
}
#parent {
position: relative;
width: 100%;
background-color: violet;
height: 70vw;
}
.hero-text {
position: absolute;
text-align: center;
right: 10vw;
top: 28vw;
z-index: 9;
font-size: 3.5vw;
float: right;
color: white;
}
#logo_png {
max-width: 25vw;
position: absolute;
z-index: 100;
}
#hero_img {
max-width: 85vw;
float: right;
top: 0;
z-index: 100;
background-color: tomato;
}
<div id="parent">
<h1>
<a href='THIS WILL BE LINK TO HOME PAGE'>
<img id="logo_png" src="C:\Users\rebec\Desktop\LBS WEBSITE\Images\lbs_blue_circle_logo_1500x1500.png" alt="Little Big Scientists"/>
</a>
</h1>
<h1>
<img id="hero_img" src="Images/circle_hands_lbsphoto.png" alt="Little Big Scientists"/>
</h1>
<div class="hero-text">
<p>We’re on a mission to teach,
<br>guide, and empower the next
<br> generation of scientists
</p>
</div>
<!-- Div for Nav Bar-->
<div id="container">
<nav>
<ul>
<li>Mission</li>
<li>About</li>
<li>Events</li>
<li>Donate</li>
<li>Contact</li>
</ul>
</nav>
</div>
</div>
<div id="test">
<h2 class="p1">Inspiring Education</h2>
</div>
Your style properties have wrong values !
vh is for height and vw is for width !
anyways , your #hero_img has height : 85vw which is greater than #parent 's height of 70vw.
this should fix the overflow !
#hero_img {
max-width: 25vh;
float: right;
top: 0;
z-index: 100;
background-color: tomato;
}
#parent {
position: relative;
width: 100%;
background-color: violet;
height: 35vh;
}
vh and vw are relative units used to style the element according to the size of the view port !
this article covers more about them and other units too !

Javascript Popup and Class instead of ID

I've been using a simple script to pop up a hidden div, and an absolute hyperlink in behind as a "failsafe" way for the user to close the popup. Now that I want to have multiple "pop ups" on the same page, I need to adjust so that I'm not targeting by ID. getElementsbyClassName does not seem to be working.
My current HTML code:
Button One
Button Two
<div id="buttonOne" class="white_content"><a class="closeWindow" href="javascript:void(0)" onclick="document.getElementById('buttonOne').style.display='none';document.getElementById('fade').style.display='none'">CLOSE</a>
<p>BUTTON ONE CONTENT</p>
</div>
<div id="buttonTwo" class="white_content"><a class="closeWindow" href="javascript:void(0)" onclick="document.getElementById('buttonOne').style.display='none';document.getElementById('fade').style.display='none'">CLOSE</a>
<p>BUTTON TWO CONTENT</p>
</div>
<div id="fade" class="black_overlay"></div>
And some CSS:
.black_overlay{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index:1001;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
.black_overlay a {
display:block;
width:100%;
height:100%;
cursor:unset;
}
.white_content {
display: none;
position: fixed;
top: 12%;
left: 12%;
width: 75%;
height: 75%;
padding: 16px;
background-color: white;
z-index:1002;
overflow: auto;
}
So the pop-up triggers/buttons work fine, because I can connect each button to its respective content window with a unique ID. But the div at the bottom (#fade) is what goes behind the window and fills the background with a semi-transparent overlay. I liked having a giant link there that closed the window whenever you clicked outside the content window. Since it needs to target the current open div container by ID, I'm at a loss.
I tried replacing the link in there with document.getElementsbyClassName and giving all of the windows the same class, but I get an undefined error.
Any help would be greatly appreciated!
One minimal change solution is to track the active button using a global variable, like this (the global is activeButton, code changes are in the onclick attributes for the a tags and the #fade tag, and there's a bit of JavaScript declaring the variable):
var activeButton;
.black_overlay{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index:1001;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
.black_overlay a {
display:block;
width:100%;
height:100%;
cursor:unset;
}
.white_content {
display: none;
position: fixed;
top: 12%;
left: 12%;
width: 75%;
height: 75%;
padding: 16px;
background-color: white;
z-index:1002;
overflow: auto;
}
Button One
Button Two
<div id="buttonOne" class="white_content"><a class="closeWindow" href="javascript:void(0)" onclick="document.getElementById('buttonOne').style.display='none';document.getElementById('fade').style.display='none'">CLOSE</a>
<p>BUTTON ONE CONTENT</p>
</div>
<div id="buttonTwo" class="white_content"><a class="closeWindow" href="javascript:void(0)" onclick="document.getElementById('buttonOne').style.display='none';document.getElementById('fade').style.display='none'">CLOSE</a>
<p>BUTTON TWO CONTENT</p>
</div>
<div id="fade" class="black_overlay"></div>
I would strongly suggest moving all of that JavaScript out of onclick=... attributes and into functions, though, not least because it would allow a lot less code duplication.

JavaScript Enabled Scroll Fixed Nav Bar Trouble

I have a JavaScript enabled scrolling nav bar. It starts below a hero graphic then sticks to the top when it gets to the top. It works perfectly, however, when it reaches the top it causes the div below it to snap to the top instead of smoothly getting there. It's hard to explain so here's the code.
I know what's happening: Once the nav bar reaches the top, it stacks above the div causing the div to "jump." I just can't figure out how to make it smoother.
Here's the code and thanks for your thoughts!
<body>
<div class="home-hero-image">
<h1>Assemble</h1>
</div>
<div class="header">
<div class="header_container">
<div class="header_onecol">
<ol>
<li class="links">Blog</li>
<li class="links">Members</li>
<li class="links">Technology</li>
<li class="links">Contact Us</li>
</ol>
</div>
</div>
</div>
<div class="intro">
<p class="maintext">
We are dedicated to delivering the latest information on current threats, to provide industry best practices, and to enhance every public sector IT professional's understanding of cybersecurity by opening direct conversations between the government and IT community.
</p>
</div>
</body>
body {
font-family: Helvetica, Arial, Sans-serif;
font-style: normal;
font-weight: 200;
color: #888888;
margin: 0;
padding: 0;
font-size: 100%;
display: block;
text-align: center;
}
p {
line-height: 1.5;
}
img {
max-width: 100%;
height: auto;
}
.home-hero-image {
height: 250px;
background: url('../images/hero_image.jpg') no-repeat;
z-index: -1;
}
h1 {
color: white;
float: right;
padding-right: 5%;
font-size: 5em;
}
.header {
height: 77px;
position: relative;
clear: both;
background-color: white;
border-bottom: 1px solid gray;
border-top: 1px solid gray;
}
.fixed {
position:fixed;
top:0px;
right:0px;
left:0px;
padding-bottom: 7px;
z-index:999;
}
.header_container {
width: 75%;
margin: 0 auto;
padding: 0 12px;
}
.header_onecol {
width: 97%;
height: 40px;
margin: 1%;
display: block;
overflow: hidden;
background-image: url('../images/Logo.png');
background-repeat: no-repeat;
padding-top: 24px;
}
<script language="javascript" type="text/javascript">
var win = $(window),
fxel = $(".header"),
eloffset = fxel.offset().top;
win.scroll(function() {
if (eloffset < win.scrollTop()) {
fxel.addClass("fixed");
} else {
fxel.removeClass("fixed");
}
});
</script>
When a div is fixed, it will no longer take up "space", meaning the next div will do exactly as you described -- stack up near the top.
Consider wrapping all of your content after the header using a div:
<div class="header">
...
</div>
<div class="main-body">
<div class="intro">
<p class="maintext">
We are dedicated to delivering the latest information on current threats, to provide industry best practices, and to enhance every public sector IT professional's understanding of cybersecurity by opening direct conversations between the government and IT community.
</p>
</div>
</div>
When we fix the header, we can add top-padding equal to the height of the header to the main-body div to prevent it from jumping.
var win = $(window),
fxel = $(".header"),
eloffset = fxel.offset().top;
win.scroll(function() {
if (eloffset < win.scrollTop()) {
$(".main-body").css("padding-top", fxel.height());
fxel.addClass("fixed");
} else {
$(".main-body").css("padding-top", 0);
fxel.removeClass("fixed");
}
});
JSFiddle here
Hope this helps!

Getting the height of a element hidden by a container with height 0

I'm encountering an issue with scrollHeight and offsetHeight that I suspect is a product of abusing the css rendering engine.
I'm attempting to get an accurate scrollHeight or offsetHeight for an element in the following context.
CSS
.transitionHeight {
overflow: hidden;
transition: height 1s;
}
.closed {
height: 0 !important;
overflow: hidden;
padding: 0 !important;
border: none !important;
margin: 0 !important;
margin-top: 0 !important;
margin-right: 0 !important;
margin-bottom: 0 !important;
margin-left: 0 !important;
width: .1rem;
}
HTML (snippet)
<div class="fullHeight closed" id="addressTarget" style="height: 1119px;">
<div class="widget bar contact" id="addressDetails">
<div class="column left">
Header:
</div>
<p class="column right">Information</p>
<div class="column left">
Header 2:
</div>
<a href="" class="column right">
More Details
</a>
<div class="column left">
Like us on Facebook at:
</div>
<a href="" target="_blank" class="column right">
Even More Details
</a>
</div>
</div>
Calls to document.querySelector("#addressDetails").clientHeight and document.querySelector("#addressDetails").offsetHeight are both returning a seemingly random integer when the closed style is applied to the #addressTarget, when #addressTarget does not have the closed style attached either call returns an accurate value. Ideally the code should be able to calculate the correct height while the style is applied to avoid an FOUC, is there a way to get this value?
The goal here is to set document.querySelector("#addressTarget").style.height to the value returned by the height check to create a reliable slide down. If the javascript call cannot return the required height is there a css rule that can be applied to .heightTransition that will a) represent a transition target and b) be calculated correctly?
(While the exact definitions of .column .left and .right are not required to solve this problem I'm including them here in case they are useful, however the best place I can pull them from is the original .scss so I'm providing them in sass rather than css:
$rook: 500px;
$bishop: 750px;
.column {
display: inline-block;
box-sizing: border-box;
margin: 0;
padding: 1rem;
box-sizing: border-box;
&.left {
width: 100%;
vertical-align: top;
text-align: center;
#include applyWiderThan($rook) {
width: 33%;
text-align: right; }
#include applyWiderThan($bishop) {
width: 20%} }
&.right {
width: 100%;
overflow: scroll;
border: 1px solid mix($gold, white, 20%);
border-radius: 10px/10px;
#include applyWiderThan($rook) {
width: 65%;
border: none;
border-radius: none; }
#include applyWiderThan($bishop) {
font-size: 1.5rem;
width: 78%} }
}

Categories

Resources