Parent component not resizing to fit children - javascript

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>

Related

Flexbox inheritence issue

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);
}

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 !

How to prevent cutting off absolute positioned elements and still keep a box-shadow embrace the parent div?

First of all an example:
https://jsfiddle.net/85uqehz5/
The code is just an example, an easier version of my real code. I figured out that I cant't have both: Setting the wrap-div to overflow: visible the menu that shows up isn't cut off but the box shadow doesn't embrace the box; With overflow:auto; the box-shadow is working but the menu cut off. How could I solve this? A fixed height would not be an option.
Example Code:
$('#menu').click(function() {
$('#menu-list').toggleClass('hidden');
});
#wrap {
width: 80%;
height: auto;
overflow: visible;
box-shadow: 0 0 .2rem rgba(0, 0, 0, .4);
}
#content {
width: 200px;
height: 20px;
margin: 0 auto;
}
#content2 {
float: left;
}
.hidden {
display: none;
}
#menu {
position: relative;
height: 20px;
width: 100px;
background-color: #ccc;
float: left;
}
#menu-list {
position: absolute;
top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="wrap">
<div id="content">
Some Content
</div>
<div id="content2">
Some Content
</div>
<div id="menu">
Open Menu
<div id="menu-list" class="hidden">
<div> bla </div>
<div> bla </div>
<div> bla </div>
</div>
</div>
</div>
It's very simple, in your specific case:
1- Remove overflow: auto; from #wrap
2- Add this to your CSS:
#wrap:after {
display: table;
content: "";
clear: both;
}
This makes the height of #wrap's calculation include the floated element.
If you have multiple uses declare a class like clearfix and use it whenever needed.
Demo: https://jsfiddle.net/85uqehz5/1/
Floats must be cleared: https://jsfiddle.net/85uqehz5/3/
<div id="wrap" class="clearfix">
The reason the menu is cut off is because you haven't clear your float: left and that is done with such piece of code to the container
.clearfix:after {
content: "\0020";
display: block;
height: 0;
clear: both;
visibility: hidden;
}

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%} }
}

With jQuery how can you make all of the parent divs and body expand in height to accommodate content?

Objective
To have the page the page on my website to expand in height according to the dynamic data pushed into the container.
Background
The page has a set of images and text that is populated via a JSON feed. The text is overflowing into the footer because it is not expanding its containing div which would subsequently expand its containing div which would subsequently expand the body. So I need for a specific child div to push its multiple parent divs.
I have searched similar problems on Stackoverflow and attempted various CSS solutions such as giving all of the parent divs a CSS rule of clear:both or even in the HTML inserting a <div style="clear:both"></div> but none of those solutions worked.
So now I am experimenting with jQuery to see if I could find a solution to this problem.
I know I need to create a variable of some sort like
var newHeight = $("#carousel").height();
And that it needs to have push out the height with something like
$(".case").height(newHeight);
This is my current HTML
<body>
<div class="container">
<div class="block push">
<div id="mainContent" class="row">
<div class="large-12 columns">
<h1>Before & After Case Gallery</h1>
<div id="casesContainer">
<div id="carousel"></div>
</div>
<script id="casestpl" type="text/template">
{{#cases}}
<div class="case">
<div class="gallery_images_container">
<div class="item_container">
<div class="gallery_heading">BEFORE</div>
<img src="/assets/img/content/images-bruxzir-zirconia-dental-crown/cases/{{image}}_b_300.jpg" alt="Photo of {{alt}}" />
</div>
<div class="item_container">
<div class="gallery_heading">AFTER</div>
<img src="/assets/img/content/images-bruxzir-zirconia-dental-crown/cases/{{image}}_a_300.jpg" alt="Photo of {{alt}}" />
</div>
</div>
<div class="description_container">
<p>
<span><strong>Case Number {{{number}}} {{version}}:</strong></span>
{{{description}}}
</p>
</div>
</div>
{{/cases}}
</script>
The {{{description}}} in the <p> is overflowing into its parent divs <div class="description_container"> then <div class="case"> then <div id="carousel"> then <div class="casesContainer"> then <div class="large-12"> (which is a container in Foundation) then <div class="mainContent"> and so on.
Here is my CSS
html, body { height: 100%; }
.container { display: table; height: 100%; width: 100%; margin: 0 auto; }
.block { display: table-row; height: 1px; }
.push { height: auto; }
#mainContent {}
#casesContainer {
min-width:310px;
}
.image-navigation {
background: rgb(6,6,6);
color: #fff;
width:100%;
max-width: 640px;
height: 24px;
}
.image-navigation a {
color: #fff;
padding: 6px;
}
.image-navigation-previous, .image-navigation-next{
float:left;
width: 50%;
}
.image-navigation-previous {
text-align: right;
}
.image-navigation-next {
text-align: left;
}
#carousel {
height:auto;
min-height:600px;
overflow-y: auto;
}
.case {
max-width: 640px;
height:auto;
}
.gallery_images_container {
clear: both !important;
}
.item_container{
max-width: 320px;
float: left;
}
.gallery_heading {
background: black;
color: white;
width: 100%;
text-align: center;
}
.description_container {
background: none repeat scroll 0% 0% white;
min-width: 308px;
max-width: 640px;
padding: 6px 6px 12px 6px;
clear: both !important;
}
I realize that #carousel { height:auto; min-height:600px; overflow-y: auto; } is an ugly hack. It was just an experiment.
I hope that I am just completely missing something and this is an easy jQuery fix. Or maybe my HTML and CSS could use a different structure?
Not a complete fix but maybe helpful.
I've used this function but Internet Explore increases the heights on resize.
$(document).on('ready', function() {
// $(window).on('resize', function() {
var height1 = $("#r1c1").height();
if (height1 < $("#r1c2").height()) { height1 = $("#r1c2").height() }
if (height1 < $("#r1c3").height()) { height1 = $("#r1c3").height() }
$("#r1c1").height(height1);
$("#r1c2").height(height1);
$("#r1c3").height(height1);
// }).trigger('resize'); // Trigger resize handlers not working correctly with IE8.
});//ready

Categories

Resources