CSS: fit an image into an unknown size parent - css

Here is below a simplified version of what I have.
The goal is to fit the image into its parent. In other words, the image size must not exceed the parent size. max-width and max-height don't work because the parent (#media-insert) don't have a known size. What is currently happening, is that the parent increases its size to fit the image.
This is really easy solve by setting the image as the background of the parent instead of inserting it into the parent. However, I don't want to do that, because I want to be able to replace the image by a video.
Also, I don't want to modify the HTML. Keep in mind that this is a simplified version, in the real world there is more going on in the layout.
Thanks
* {
box-sizing: border-box;
}
main {
display: flex;
flex-direction: column;
justify-content: space-between;
}
#media-description {
/* the description must take the minimum possible space (flex-grow: 0) to fit everything (flex-shrink: 0) */
flex-shrink: 0;
flex-grow: 0;
}
#media-wrapper {
/* the wrapper should shrink/grow to fit the remaining space */
flex-shrink: 1;
flex-grow: 1;
}
#media-wrapper #media-insert {
width: 100%;
height: 100%;
/* center the image */
display: flex;
align-items: center;
justify-content: center;
}
#media-wrapper #media-insert img {
display: block;
/* image must fit inside the parent (doesn't work) */
max-width: 100%;
max-height: 100%;
}
/***** debug *****/
main {
border: 5px solid red;
/* simulate phone screen */
width: 350px;
height: 500px;
}
#media-wrapper {
border: 5px solid green;
}
#media-insert {
border: 5px solid lightgreen;
}
#media-description {
border: 5px solid blue;
}
<main>
<div id="media-wrapper">
<div id="media-insert">
<img src="https://picsum.photos/200/300" alt="lorem ipsum">
</div>
</div>
<div id="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>
Edit:
Here is how I want it to look like (but without setting the image as the background of the parent):
* {
box-sizing: border-box;
}
#examples {
display: flex;
}
#examples > div {
margin: 1em
}
main {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.media-description {
/* the description must take the minimum possible space (flex-grow: 0) to fit everything (flex-shrink: 0) */
flex-shrink: 0;
flex-grow: 0;
}
.media-wrapper {
/* the wrapper should shrink/grow to fit the remaining space */
flex-shrink: 1;
flex-grow: 1;
}
.media-wrapper .media-insert {
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: center;
}
#img-example-1 {
background-image: url("https://picsum.photos/200/300");
}
#img-example-2 {
background-image: url("https://picsum.photos/100/100");
}
/***** debug *****/
main {
border: 5px solid red;
/* simulate phone screen */
width: 350px;
height: 500px;
}
.media-wrapper {
border: 5px solid green;
}
.media-insert {
border: 5px solid lightgreen;
}
.media-description {
border: 5px solid blue;
}
<div id="examples">
<div>
<p>
Image too big<br>
-> scale down
</p>
<main>
<div class="media-wrapper">
<div class="media-insert" id="img-example-1"></div>
</div>
<div class="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>
</div>
<div>
<p>
Image smaller than parent<br>
-> image keeps its size
</p>
<main>
<div class="media-wrapper">
<div class="media-insert" id="img-example-2"></div>
</div>
<div class="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>
</div>
</div>

You could position the image with absolute position, set it to 100% width and height and use the object-fit property to style it. It's like the background-size: cover:
* {
box-sizing: border-box;
}
main {
display: flex;
flex-direction: column;
justify-content: space-between;
}
#media-description {
/* the description must take the minimum possible space (flex-grow: 0) to fit everything (flex-shrink: 0) */
flex-shrink: 0;
flex-grow: 0;
}
#media-wrapper {
/* the wrapper should shrink/grow to fit the remaining space */
flex-shrink: 1;
flex-grow: 1;
}
#media-wrapper #media-insert {
width: 100%;
height: 100%;
/* center the image */
display: flex;
align-items: center;
justify-content: center;
background:red;
position:relative;
}
#media-wrapper #media-insert img {
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
object-fit:cover;
}
/***** debug *****/
main {
border: 5px solid red;
/* simulate phone screen */
width: 350px;
height: 500px;
}
#media-wrapper {
border: 5px solid green;
}
#media-insert {
border: 5px solid lightgreen;
}
#media-description {
border: 5px solid blue;
}
<main>
<div id="media-wrapper">
<div id="media-insert">
<img src="https://picsum.photos/200/300" alt="lorem ipsum">
</div>
</div>
<div id="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>

Got it! I modified passatgt's answer (thanks for showing me how object-fit works).
The modification I made:
All the image is visible: object-fit: contain instead of object-fit: cover
The image keeps its size if it already fits in the parent (max-width and max-height instead of width and height).
Added an example to show that it works with image bigger than parent and smaller than parent.
* {
box-sizing: border-box;
}
#examples {
display: flex;
}
#examples > div {
margin: 1em
}
main {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.media-description {
/* the description must take the minimum possible space (flex-grow: 0) to fit everything (flex-shrink: 0) */
flex-shrink: 0;
flex-grow: 0;
}
.media-wrapper {
/* the wrapper should shrink/grow to fit the remaining space */
flex-shrink: 1;
flex-grow: 1;
}
.media-wrapper .media-insert {
position: relative;
width: 100%;
height: 100%;
}
.media-wrapper .media-insert img {
position:absolute;
left: 50%;
top: 50%;
max-width: 100%;
max-height: 100%;
object-fit: contain;
transform: translate(-50%, -50%);
}
/***** debug *****/
main {
border: 5px solid red;
/* simulate phone screen */
width: 350px;
height: 500px;
}
.media-wrapper {
border: 5px solid green;
}
.media-insert {
border: 5px solid lightgreen;
}
.media-description {
border: 5px solid blue;
}
<div id="examples">
<div>
<p>
Image too big<br>
-> scale down
</p>
<main>
<div class="media-wrapper">
<div class="media-insert">
<img src="https://picsum.photos/200/300" alt="lorem ipsum">
</div>
</div>
<div class="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>
</div>
<div>
<p>
Image smaller than parent<br>
-> image keeps its size
</p>
<main>
<div class="media-wrapper">
<div class="media-insert">
<img src="https://picsum.photos/100/100" alt="lorem ipsum">
</div>
</div>
<div class="media-description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</main>
</div>
</div>

change the max-width and max-height to min
#media-wrapper #media-insert img {
display: block;
min-width: 100%;
min-width: 100%;
}
Edit: or are you trying just to increase the width to fit the parent?

Related

Flexbox: how to make element scrollable without taking up remaining space

I have 2 divs, yellow and red. The yellow div has a variable content.
I want to achieve the following:
When the yellow div grows, the red div should be pushed down, but never below the page edge. The red div should always be fully visible.
If the yellow div becomes too large, it should be scrollable, so the red div is still visible.
The yellow div should not take up more space than its content. When the yellow div does not take up much space, the red div should not be pushed down. It should be displayed right below the yellow div.
How can I achieve this with flexbox?
I succeeded in making the yellow box scrollable, and keeping the red box always visible. However, my solution displays the yellow box always at the bottom of the page, which is not what I want.
.page {
height: 120px;
width: 300px;
display: flex;
flex-direction: column;
border: 4px solid gray;
padding: 10px;
}
.yellow {
flex: 1 1 0;
overflow: auto;
min-height: 0;
border: 4px solid #F7B64C;
padding: 10px;
margin-bottom: 10px;
}
.red {
border: 4px solid #F05467;
padding: 10px;
}
Example 1: yellow div has a lot of content and correctly becomes scrollable:
<div class="page">
<div class="yellow">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div class="red"></div>
</div>
<br/>
<br/> Example 2: yellow div has little content, incorrectly pushes red div to the bottom:
<div class="page">
<div class="yellow">
Lorem ipsum dolor sit amet.
</div>
<div class="red"></div>
</div>
How can I make the yellow box take up only the space it actually needs, and not take up the remaining space?
It seems that the default behavior of flex box might achieve the desired result without additional settings.
In the following example, try click the buttons to adjust the amount of content in yellow and red.
An additional spacer div after red can be added to further enforce the layout, but it seems to be unnecessary in this use case.
.spacer {flex: 1}
<div class="spacer"></div>
Example:
const btns = document.querySelectorAll("button");
const yellow = document.querySelector(".yellow");
const red = document.querySelector(".red");
btns.forEach((btn, i) =>
btn.addEventListener("click", () => {
yellow.innerText = i === 0 ? "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." : i === 1 ? "Lorem ipsum dolor sit amet." : yellow.innerText;
red.innerText = i === 2 ? "Duis aute irure dolor in reprehenderit in velit eu fugiat nulla pariatur." : i === 3 ? "" : red.innerText;
})
)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
}
.control {
display: flex;
flex-direction: column;
align-items: flex-start;
width: 300px;
margin: 10px 10px;
gap: 10px;
}
button {
padding: 6px;
}
section {
height: 180px;
width: 300px;
display: flex;
flex-direction: column;
border: 4px solid gray;
padding: 10px;
margin: 3px 10px;
}
.yellow {
overflow: auto;
min-height: 0;
border: 4px solid #f7b64c;
padding: 10px;
margin-bottom: 10px;
}
.red {
border: 4px solid #f05467;
padding: 10px;
}
/* .spacer {
flex: 1;
} */
<div class="control">
<button>Example 1: Lots of content in yellow</button>
<button>Example 2: Little content in yellow</button>
<button>Example 3: Some content in red</button>
<button>Example 4: No content in red</button>
</div>
<br />
<section>
<div class="yellow">Try click buttons to see examples</div>
<div class="red"></div>
<!-- <div class="spacer"></div> -->
</section>

Flex transition in Safari

The following is part of my small contribution to a post on auto height transitions:
html {
display: grid;
}
body {
display: flex;
flex-direction: column;
}
.content {
background: aqua;
flex-basis: 0;
overflow: hidden;
transition: all 1s ease;
}
span:hover + .content {
flex: 1;
}
<span>Hover over me!</span>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<p>Rest of the page content...</p>
It works in all major browsers except Safari. Any CSS tweak to run it smoothly in Safari as well?
In your code flex:1 expands to flex: 1 1 0%, thanks for the correction.Your the demo does animate flex-grow but it works because there is free space for the content to grow. Make the flexbox flex-flow: column and remove fixed height height: 200px;.
.flex-container {
width: 300px;
/* uncomment height to start animating*/
/*height: 200px;*/
font-size: 32px;
outline: 1px solid black;
display: flex;
flex-flow: column;
}
.flex-container div {
flex-grow: 0;
}
.item1 {
background: #e84d51;
}
.item2 {
background: #7ed636;
}
.item3 {
background: #2f97ff;
}
.animated {
animation: test 4s infinite;
}
#keyframes test {
0% {
flex-grow: 0;
}
100% {
flex-grow: 1;
}
}
<div class="flex-container">
<div class="item1">1</div>
<div class="item2 animated">2</div>
<div class="item3">3</div>
</div>
Now it doesn't animate because flex-grow is for distributing free space. If there is no free space, then changing flex-grow doesn't affect anything.
Your code sample in the opening post works because of the weird combination of display grid, percentage flex-basis and flex-grow values < 0:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
#grd {
/* if you remove following line ,
then the .content won't clip due to overflow */
display: grid;
}
#flx {
display: flex;
flex-flow: column;
}
.content {
background: aqua;
flex-basis: 0%;
flex-grow: 0.25;
overflow: hidden;
}
</style>
</head>
<body>
<div id=grd>
<div id=flx>
<span>Top</span>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<p>Bottom</p>
</div>
</div>
</body>
</html>
Here flex-grow:0.25 shouldn't reduce the content size. ref. Somehow this happens on Chrome and not on Safari. If you remove display:grid, then overflow:hidden stops clipping the content. I don't think chrome is correct here cos flex-grow shouldn't reduce the .content size.
There is some difference I found how Chrome and safari switch attribute units while animating. Run following code on both chrome and safari:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.setInterval(function () {
init();
}, 400);
function init() {
var content = document.querySelector('.content');
var stat = window.getComputedStyle(content).getPropertyValue('flex-basis');
var grow = window.getComputedStyle(content).getPropertyValue('flex-grow');
var height = window.getComputedStyle(content).getPropertyValue('height');
document.getElementById('stat').innerText = 'flex-basis:' + stat +
'\n' + 'flex-grow:' + grow + '\n' + 'height: ' + height;
}
</script>
<style>
#grd {
display: grid;
}
#flx {
display: flex;
flex-flow: column;
}
.content {
background: aqua;
flex-basis: 0;
overflow: hidden;
transition: all 6s ease;
}
span:hover+.content {
flex: 1;
}
p {
white-space: pre;
}
</style>
</head>
<body>
<div id=grd>
<div id=flx>
<span>Hover over me!</span>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex
ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.</div>
<p>Rest of the page content...</p>
<p id="stat">stat</p>
</div>
</div>
</body>
</html>
Observer flex-basis see how it switches from 0px to 0% instantly on chrome on animation start. But on Safari it switches at the end of animation. I don't know how it relates to the issue.
Solution: I still stick to animating flax-basis instead of flex-grow here. If fit-content is experimental and not desired then you can still use min-content and max-content. Unlike fit-content all browsers support them.
html {
display: grid;
}
body {
display: flex;
flex-direction: column;
}
.content {
background: aqua;
flex-basis: 0;
overflow: hidden;
transition: all 1s ease;
/* limit the height */
/* use either of these as per situation */
max-height: fit-content;
max-height: min-content;
max-height: max-content;
}
span:hover+.content {
flex: 1;
}
/* Safari 11+ */
#media not all and (min-resolution: 0.001dpcm) {
#supports (-webkit-appearance: none) and (stroke-color: transparent) {
span:hover + .content {
flex-basis:100vh;
}
}
}
/* Safari 10.1 */
#media not all and (min-resolution: 0.001dpcm) {
#supports (-webkit-appearance: none) and (not (stroke-color: transparent)) {
span:hover + .content {
flex-basis:100vh;
}
}
}
/* Safari 6.1-10.0 (but not 10.1) */
#media screen and (min-color-index: 0) and(-webkit-min-device-pixel-ratio:0) {
#media {
span:hover+.content {
flex-basis: 100vh;
}
}
}
<span>Hover over me!</span>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<p>Rest of the page content...</p>
We have to set max-height to intrinsic size to limit the height, otherwise it'll grow till end of the view port.
Note: I've tested the code on Safari 14.1 and Chrome 95 on iPadOS 15.1
To create Safari specific CSS I've referred https://www.browserstack.com/guide/create-browser-specific-css
As you know, flex transition doesn't work since Safari 13.1 (Mac). But if you use the below code maybe it works.
html {
display: grid;
}
body {
display: flex;
flex-direction: column;
}
.content {
background: aqua;
height: 0;
overflow: hidden;
transition: all 1000ms ease;
}
span:hover + .content {
height: 100%;
}
<span>Hover over me!</span>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<p>Rest of the page content...</p>
In the above snippet code, I change transition: all 1s easy; to transition: all 1000ms easy;.
I came to this conclusion based on This and this
Transition in safari has some problems that discussed here:
css transitions not working in safari
It can't work for auto values and all can't be use. also -webkit- at the start should use.
Here is my trick to solve this problem (Known problem: max-height is limited to 1000px):
.content {
background: aqua;
flex-basis: 0;
max-height: 0;
overflow: hidden;
transition: all 1s ease;
-webkit-transition: max-height 1s ease;
}
span:hover + .content {
flex: 1;
max-height: 1000px;
}

Prevent overflow:hidden from cutting text in the middle when using flexbox column

I want to create a fixed height card with a title, body, and footer. The title and footer can be one or more lines, and the body text should expand to fill the remaining space.
.card {
display: flex;
flex-direction: column;
height: 192px;
width: 300px;
border: 1px solid;
padding: 12px;
}
.title {
font-size: 18px;
font-weight: bold;
margin-bottom: 8px;
}
.body {
flex: 1 1 auto;
overflow: hidden;
overflow-wrap: break-word;
word-wrap: break-word;
margin-bottom: 8px;
}
<div class="card">
<div class="title">
This is a title
</div>
<div class="body">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div>
footer text
</div>
</div>
How can I prevent the body text from being cut off? overflow-wrap/word-wrap seem to have no effect.
You have to make the height a mutliple of the height of one line. Here is an example using CSS grid.
Resize the main container to see the magic:
.card {
display: flex;
flex-direction: column;
height: 192px;
width: 300px;
border: 1px solid;
padding: 12px;
overflow: hidden;
resize: both;
}
.title {
font-size: 18px;
font-weight: bold;
margin-bottom: 8px;
}
.body {
flex: 1 1 auto;
margin-bottom: 8px;
line-height: 1.2em; /* height of one line */
display: grid;
grid-template-rows: repeat(auto-fit, 1.2em); /* same as line-height here */
grid-auto-rows: 0;
}
.body>div {
grid-row: 1/-1;
overflow: hidden;
}
<div class="card">
<div class="title">
This is a title
</div>
<div class="body">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
<div>
footer text
</div>
</div>

CSS - Best way to add full width column background colour to columns inside container

I've got a design I need to complete with 2 columns, the content inside the columns needs to line up with the container that's used across the site.
The issue I've got is on the design the second column has a background colour that stretches to the edge of the viewport.
If you look at the JSfiddle/code below I have a working solution if you uncomment the .col::after code at the bottom, however I was hoping there might be a cleaner more simple way of achieving this?
Cheers
https://jsfiddle.net/qksmpfrv/
html,
body {
padding: 0;
margin: 0;
}
* {
box-sizing: border-box;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 80px;
}
.grid {
display: flex;
flex-wrap: wrap;
}
.col {
padding: 80px;
position: relative;
width: 50%;
}
.col:last-child {
background: grey;
}
/* .col:last-child::after {
background: grey;
content: '';
position: absolute;
height: 100%;
left: 100%;
top: 0;
width: 500px;
} */
<div class="container">
<h1>Title</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<div class="grid">
<div class="col">
1
</div>
<div class="col">
2
</div>
</div>
</div>
How about moving the grid outside the max-width container and then adding a max-width inside the columns:
Advantages of this approach over an after
will always be the width of the screen no matter how wide the monitor is - the after approach will only cover screens up to 2400px wide (I know not many screens are this big, but sometimes you might want to display your site at a marketing event and those screens may be)
you are not creating an extra 500px box off screen for smaller resolutions (so less rendering time for things like mobile and tablet)
You don't have to use a hack on every column you want to stretch to the edge
It's just nicer and easier to maintain
html,
body {
padding: 0;
margin: 0;
}
* {
box-sizing: border-box;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 80px;
}
.grid {
display: flex;
flex-wrap: wrap;
}
.col {
position: relative;
width: 50%;
}
.inner {
max-width: 700px;
padding: 80px; /* move padding to inner */
}
.col:first-child .inner {
margin-left: auto; /* push this to the right if no wide enough to fill col */
}
.col:last-child {
background: grey;
}
<div class="container">
<h1>Title</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<!-- move grid outside container -->
<div class="grid">
<div class="col">
<div class="inner">
<!-- add inner containers with max-width of 700px (half of your container) -->
1
</div>
</div>
<div class="col">
<div class="inner">
2
</div>
</div>
</div>

Set all margins/padding to 0, I'm still having problems with CSS layout

CSS beginner here, I'm at my wits end with a relatively simple css layout and was hoping someone would just look over it for me..
What i've got:
CSS embedded temporarily, excuse the indenting (i've just come from programming and indenting was helping me make sense of it):
<!DOCTYPE HTML>
<html lang="en">
<style>
* {margin: 0; padding:0;}
body
{
font: normal 100% Helvetica, Arial, sans-serif;
background-color: LightSkyBlue;
margin: auto auto;
max-width: 90%;
}
#central_container
{
background-color: Yellow;
width: 100%;
margin: auto auto;
float: left;
}
#leftside_container
{
background-color: Ivory;
float: left;
width: 66%;
clear: left;
}
#header_container
{
background-color: DeepSkyBlue;
width: 100%;
height: 15em;
}
#header_title
{
background-color: Lime;
width: 100%;
height: 80%;
}
#header_title h1{ padding: 0; margin: 0; }
#navbar_container
{
background-color: Coral;
width: 100%;
height: 20%;
}
.navbar_links{ background-color: HotPink; }
#currentpage_content
{
background-color: grey;
width: 100%;
height: 20%;
}
#rightside_container
{
background-color: Khaki;
float: right;
width: 33%; <!--/* 320 /960 */-->
}
#register_container
{
background-color: LightPink;
width: 100%;
}
#contacts_content
{
background-color: SeaGreen;
width: 100%;
}
</style>
<head>
<title>Verge Green IT</title>
<link rel="stylesheet" href"CSS/base.css" type="text/css" />
</head>
<body>
<div id="central_container">
<!--Left-side Current-page Content-->
<div id="leftside_container">
<!--Header-->
<div id="header_container">
<div id="header_title">
<h1>#header_title</h1>
</div>
<!--Navbar-->
<div id="navbar_container">
<div class="navbar_links">
</div>
</div>
</div>
<!--Current Page Contents-->
<div id="currentpage_content">
<p> #currentpage_content</p>
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p><p>
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
</div>
</div>
<!--Right-side Every-page Content-->
<div id="rightside_container">
<div id="register_container"><p> #register_container </p></div>
<div id="contacts_content"><p> #contacts_content</p></div>
</div>
</div>
</body>
</html>
What i'm aiming for:
(Vague text alternative: Where the register_container fills the rightside_container up to the height of the bottom of the navbar_container. And the contact_content fills up the rest of the rightside_container as the current_page content does on the leftside_container. )
I think i'm having some trouble because of the floating i'm trying to do.. and i have no idea why there's empty yellow space on the left of register_container/contacts_content. Nor why i can specify height for things like the header_title but not the register_container.
Really appreciate any help!
I think you have some minor problems with values you have given in the Width and height field.
This works fine for me.
<!DOCTYPE HTML>
<html lang="en">
<style>
* {margin: 0; padding:0;}
body
{
font: normal 100% Helvetica, Arial, sans-serif;
background-color: LightSkyBlue;
margin: 0 auto;
max-width: 90%;
height: auto;
}
#central_container
{
background-color: Yellow;
width: 100%;
margin: 0 auto;
height: 100%;
float: left;
}
#leftside_container
{
background-color: Ivory;
float: left;
width: 66%;
clear: left;
}
#header_container
{
background-color: DeepSkyBlue;
width: 100%;
height: 15em;
}
#header_title
{
background-color: Lime;
width: 100%;
height: 80%;
}
#header_title h1{ padding: 0; margin: 0; }
#navbar_container
{
background-color: Coral;
width: 100%;
height: 20%;
}
.navbar_links{ background-color: HotPink; }
#currentpage_content
{
background-color: grey;
width: 100%;
height: 20%;
}
#rightside_container
{
background-color: Khaki;
float: right;
width: 34%; <!--/* 320 /960 */-->
}
#register_container
{
background-color: LightPink;
width: 100%;
height:240px;
}
#contacts_content
{
background-color: SeaGreen;
width: 100%;
height:250px;
}
</style>
<head>
<title>Verge Green IT</title>
<link rel="stylesheet" href"CSS/base.css" type="text/css" />
</head>
<body>
<div id="central_container">
<!--Left-side Current-page Content-->
<div id="leftside_container">
<!--Header-->
<div id="header_container">
<div id="header_title">
<h1>#header_title</h1>
</div>
<!--Navbar-->
<div id="navbar_container">
<div class="navbar_links">
</div>
</div>
</div>
<!--Current Page Contents-->
<div id="currentpage_content">
<p> #currentpage_content</p>
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p><p>
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
</div>
</div>
<!--Right-side Every-page Content-->
<div id="rightside_container">
<div id="register_container"><p> #register_container </p></div>
<div id="contacts_content"><p> #contacts_content</p></div>
</div>
</div>
</body>
</html>

Resources