I'm currently trying to get an element (div) stretching itself over the free space of a parent element while respecting the size of other elements on its level. I found some solutions and tried most of them but I couldn't get it to work. I suspect this is because of the cms I'm working with which - when telling it to make a set of columns the same height - changes the parent display-style to table-cell. So... here is an image of what I'm trying to archive.
As said, the CMS changes the blue container to display: table-cell to stretch it over the whole area and make all columns in a row the same height. Inside of this blue container are the elements I can control. These are up to four div (white/green) inside of a parent div (yellow). The white div are dynamic and not always present and the green one needs to stretch over the whole vertical space no matter which of the white elements are present.
And idea how to accomplish that? I tried a lot of answers about this topic but they didnt work.. I think that's maybe due to the fact that the blue container is a table-cell?
edit: Here is what I got so far.
<div id="box_wrap">
<div class="box_title">
Title
</div>
<div class="box_image">
Image
</div>
<div class="box_content">
Content
</div>
<div class="box_more">
Read More
</div>
</div>
All of this is in a container provided by the CMS itself which has the attibute display: table-cell.
#box_wrap {
display: flex;
flex-direction: column;
}
.box_content {
display: flex;
flex: 2;
}
I think the problem might be that the container provided my the CMS has no defined height. If I give my #box_wrap a fixed height manually then the div in it will work as they should. I also tried height: auto and height: 100% for the #box_wrap and it doesn't work. Again, probably because the parent has no defined height, no? That is the last thing that I need to solve. The #box_wrap needs to stretch over the vertical, currently it only extends as far as it needs to cover the content.
I also noticed that the first image I provided wasn't 100% accurate so I updated it.
I would use this to allow the .box_content to grow (i.e. become higher) and the others not:
.box_title,
.box_image,
.box_image {
flex-grow: 0;
}
.box_content {
flex-grow: 1;
}
In addition, you should apply height: 100% to #box_wrap, but for that you also need height: 100% on body and html to have a reference for the height of #box_wrap. So, to sum up:
html, body {
height: 100%;
margin: 0;
}
#box_wrap {
height: 100%;
}
You also might want to add...
body {
padding: 10px;
box-sizing: border-box;
}
...to get that distance between the edge of the screen and your container as it's shown in your image.
Related
I am trying to display mathematical equations that can be nested infinitely. But I am stuck on the correct styling of the exponents.
My current approach is as follows:
// HTML
<div class="power">
3
<div class="exponent">
<span>2</span>
</div>
</div>
// CSS
.power {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.exponent {
display: block;
min-height: 40px;
}
.exponent span {
vertical-align: super;
height: 100%;
}
But this requires a height on the parent container (exponent) to be set in one way or another, to properly render the exponent above the base with vertical-align: super;.
I've also tried to achieve the same thing with flexbox, but basically ended up with the same issue of having to set the height manually.
I could obviously resort to setting the height via javascript, but is there a css-only-solution that automatically expands the height to accomodate the height of the child (exponent) and the height needed to lift it above the parent (base)?
Correctly displayed:
Wrongly displayed when exponent is nested with another euqation:
To get this displayed as high as you want, the line height of the parent needs to be increased. Specifying a min-height for the .exponent achieved that already. But for that, you had to find some sort of “magic number”, and that doesn’t easily adapt dynamically to what height the actual text content of the element already provides.
Switching out the min-height for a padding-bottom can help make this a bit more dynamic, because that just adds spacing below the actual content, so the effective height of the element will be the height provided by the text content itself, plus the fixed padding value.
I need to create form that stays stickied when scrolling through a new full width element.
On this site, you can see it in action: https://www.pillpack.com/how-it-works but after inspecting the elements, I still cant see how they achieve this effect.
Here is what my layout currently looks like:
The red rectangle is stickied and when scrolling, it will stick to the top of the viewport. The problem I am facing here is that I need the red rectangle to stay stickied even when reaching the green portion.
The way I am currently achieving this effect is essentially 2 columns within a parent container. The parent container is flexing its children elements and the red rectangle has position sticky. But now I have a full width element that my red rectangle still needs to stay sticky on.
Would love some insight on this.
EDIT:
some basic psuedo-esque code for you...
HTML
section.wrapper
div.container
div.left
form
section.wrapper.green-bg
div.container
div.left
CSS
.wrapper {
position: relative;
width: 100%;
}
.container {
max-width: 1100px;
width: 90%;
margin: 0 auto;
display: flex;
flex-flow: row nowrap;
align-items: flex-start;
}
.form {
position: sticky;
top: 0;
}
Hopefully you guys can understand the problem here. sections are full width elements. Inside sections, theres a div.container which has a max-width and is centered. Within the container is where the content goes.
The first section needs to have no background but the second section needs a green background. Since the background is full-width, it needs to be done on the section element. This causes problems because for the red rectangle to be stickied, all elements needs to be inside a parent container.
It's because your form is nested inside a separate wrapper from your green area. The sticky form and the green area need to be encompassed by the same parent element.
Basic example: https://codesandbox.io/s/elastic-hoover-mdy4t
Can someone let me know if this is an undocumented bug with flexbox, or that I'm just doing it wrong? I've got 3 images lined up in a row inside a div container. This is as simple as it gets folks.
Without any hyperlinks, all 3 images shrink down perfectly as they should.
<div style="width: 100%; margin: 0 auto; display: flex; justify-content: center;">
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
</div>
Now, only 2 out of the 3 images when viewed on all devices shrink down correctly depending on manually maximizing dragging the browser, of via viewport.
The only image that will not change shape or size is the image with the hyperlink. So, I took the hyperlink off the first image. And decided to test it by placing it on the 2nd, now the 1st image and the 3rd image shrinks fine.
But, the 2nd image stays the exact same size? Tried then adding hyperlinks to all the images and none of them change to match the screen width?
Am I wrong to say flex items if they are images won't flex if they have a hyperlink lol? Surely this cannot be the case right?
The problem has nothing to do with hyperlinks. You could wrap the image in any element (try a span or a div) and it will have the same effect as the a container.
The problem is the hierarchical structure of a flex container.
When you set an element to display: flex (or inline-flex) you establish a flex container.
Only the children of a flex container are flex items. Descendants of a flex container beyond the children are not flex items and don't accept flex properties.
Here are the three flex items:
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
The img in the first element is not a flex item. It is wrapped by the a element and is therefore a child of a flex item.
The two img items can shrink because of two default settings on a flex container:
flex-wrap: nowrap ~ flex items are forced to remain on a single line
flex-shrink: 1 ~ flex items are permitted to shrink to prevent them from overflowing the container
If you switch to flex-wrap: wrap and/or flex-shrink: 0 the img items will no longer shrink.
The a item does not shrink because of another default setting: min-width: auto, which means that flex items cannot be smaller than the size of their content. In this case, the a item cannot shrink below the width of the image.
You can override this setting by adding min-width: 0 to your code.
#container {
display: flex;
}
span {
min-width: 0;
display: flex;
}
img {
min-width: 0;
}
<div id="container">
<span><img src="http://i.imgur.com/60PVLis.png"></span>
<img src="http://i.imgur.com/60PVLis.png">
<img src="http://i.imgur.com/60PVLis.png">
</div>
More information:
Why don't flex items shrink past content size?
Proper use of flex properties when nesting flex containers
I don't know why, but this solves the problem. I would like to know why as I cannot find out any information about this issue in any HTML/CSS documents.
If you add the following.
<style>
img {
max-width: 100%;
height: auto;
}
</style>
Then all 3 images will shink perfectly. Even if they have hyperlinks. Funny enough if you set just the width: 100%; then the image with the hyperlink stays the exact same size as the image is, and all the others without hyperlinks blow up to the 100% size of the container.
I didn't know flexbox had such rules that needed you to set image max-widths to make items responsive/shrink down if they have a hyperlink attached.
So, tried it in chrome: Only the image now with the anchor shrinks down, the other 2 stay the same size. FireFox all 3 shrink down, but chrome only shrinks the image with the hyperlink wrapped around it.
Tried wrapping hyperlinks around each of the other 2 images and in chrome, they all shrink down fine.
Can someone explain what is going on? How can i set a max-width: and height: auto on a hyperlink?
It's tough to say without seeing your CSS, but you probably are not selecting the images within <a> tags. If you alter your CSS to select images that are inside of <a> tags, it should work fine.
I've added my complete working solution. Thanks to many people here giving their various methods. So, this is for anyone else who may be struggling.
First lets set the style's up.
<style>
img {
max-width: 100%;
width: 100%;
min-width: 0;
min-height: 0;
}
</style>
adding min-width: 0; | min-height: 0; seems to be overkill, but with chrome, it works much better apparently than setting them as auto;
Since it's using flexbox we don't add the usual width: 33.33%; even if there are 3 images. In flexbox, this will just space them out way to far apart within a 100% wide div.
Here's the really important part I found out the hard way.
You must use either width: 100% on the images, or max-width: 100%; otherwise, (On Chrome without adding either 100% width or max-width: 100%; it just won't flex/shrink down when you minimize the browser to test its responsiveness.)
So, next to keep each of the 3 images in perfect aspect ratio remember to include each image inside its own div container. Otherwise, they will shrink but will just skew up to each other as they do.
As you can see the first image is even wrapped in a hyperlink, but because it's inside its own div it will shrink and grow completely flush and inline with the other images. This saves using extra markup and saves adding a span tag then making that a flex container to contain the hyperlink. I've tried both ways this is by far the easier method.
I've used inline styles for the flexbox container. (bad habit.)
<div style="border: 2px solid red; margin: 0 auto; display: flex; justify-content: center;">
<div>
<img src="flash-tooltip.png">
</div>
<div>
<img src="html-tooltip.png">
</div>
<div>
<img src="portables-tooltip.png">
</div>
</div>
Remember to close off that last /div it's a real gotcha!
And that's how I've done it. Tested it in many browsers works perfectly. Even on mobile phones and tablets.
If you don't like flexbox? You can do the same thing using regular floats.
I've included this same method as above, only this time in a float: version.
I'm using flexbox to responsively lay out a bunch of images.
.cards
.card.card1
.card.card2
.card.card3
.card.card4
etc....
footer
css:
.cards{
display: flex;
width: 100%;
flex-wrap: wrap;
height: 81.2rem;
}
.card{
display: flex;
flex-wrap: wrap;
height: 100%;
max-height: 28rem;
position: relative;
}
The problem I'm having is...
I have a footer that needs to be below the .cards div, but since .cards has a height, the footer is hovering over the div where I tell the height to be. (The cards themselves extend past the height.)
I have tried setting a taller height, however, then the space between the rows of cards expand (which I don't want). I've also tried not setting a height, but then the cards don't lay out at all, they just disappear or float way down the page.
Is there a way I can clear the .cards div?
Or just in general, get the footer to appear below the cards?
This shows the footer where it currently is, which is incorrect.
This shows the footer where I need it to be:
Instead of height: 100%, which limits the container to a fixed height, use min-height: 100% or remove height altogether.
If your height property is installed properly, you may need to apply the min-height to parent or ancestor elements.
More details: Working with the CSS height property and percentage values
Additional notes from OP:
Add the height to the direct children of the flex-box, this allows the container to determine its height.
On another note, if you put the height on the sub-children (not direct descendants), the container flex-box will not know how to set its own size and will have no height.
This seems like a really amateur question, in my opinion, but nonetheless it's still a frustrating anomaly.
This is actually the 2nd part of a 2 part problem. The first part is a rather common one, involving getting an element to stretch to 100% height of its parent object. In my demo, I have the following HTML:
<body>
<div id="sbcontainer">
DIV 1
<div id="sbcontent">
DIV 2
<table id="sbmaintable" cellspacing="0">
<tr>
<td>
TABLE
</td>
</tr>
</table> <!-- END MAINTABLE -->
</div> <!-- END CONTENT -->
</div> <!-- END CONTAINER -->
</body>
I want each element here to fill all vertical space within its parent element. I tried used the following style on each of the elements (Please note that BODY and HTML are also set to 100% height in my demo):
min-height: 100%;
height: auto !important;
height: 100%;
The result was as follows:
As you can see, the outermost DIV followed the 100% height property but the rest did not. As implied in the image note, but not actually shown in this image, I tried setting the 2nd DIV (red border) to a static height of 400px to see if the TABLE within would stretch to 100% height, and it still did not.
I then found that if I removed height:auto; from each of the elements, they would follow the 100% height property, but with an unwanted side effect:
As you can see in the image, each element is now truly 100% the height of its parent element, forcing the bottom to extend beyond the boundaries of its parent. (Even in my first example, the outermost DIV with the green border extended farther than desired because there is another sibling DIV above it on the page). NOTE: After looking more carefully, I can see that the blue TABLE element is not actually the same height as its red DIV parent, but it still extends beyond its boundary. I'm not sure if this means anything, but I do notice it.
One would think that this would be an easy thing to solve, but despite my efforts, I've had no success.
If I keep only height:auto; and remove the 100% properties, this does not stretch them at all.
I have searched for solutions on this via Google and StackOverflow, and although many sites covered 100% height issues, I still haven't found an actual solution.
I am currently testing this in Firefox.
You can use absolute positioning.
#b {
width: 40em;
height: 20em;
position:relative;
background: red;
}
#c {
position: absolute;
top: 1em;
bottom: 1em;
left: 1em;
right: 1em;
background: blue;
}
<div id="b">
<div id="c">
</div>
</div>
I believe the proper solution to something like this is using a flexbox. Flexbox has great support the lately with all modern browsers.
Use following for the parent
.stretch-items {
display: flex;
flex-direction: column;
}
And for the item that should grow
.stretch-items .stretch {
flex-grow: 1;
}
Here is a codepen demonstrating it https://codepen.io/giorgosk/pen/NWWaqPO