Prevent content from expanding grid items
By default, a grid item cannot be smaller than the size of its content.
Grid items have an initial size of min-width: auto
and min-height: auto
.
You can override this behavior by setting grid items to min-width: 0
, min-height: 0
or overflow
with any value other than visible
.
From the spec:
6.6. Automatic Minimum Size of Grid
ItemsTo provide a more reasonable default minimum size for grid items, this
specification defines that theauto
value ofmin-width
/min-height
also applies an automatic minimum size in the specified axis to grid items whoseoverflow
isvisible
. (The effect is analogous to the automatic minimum size imposed on flex items.)
Here's a more detailed explanation covering flex items, but it applies to grid items, as well:
- Why don't flex items shrink past content size?
This post also covers potential problems with nested containers and known rendering differences among major browsers.
To fix your layout, make these adjustments to your code:
.month-grid {
display: grid;
grid-template: repeat(6, 1fr) / repeat(7, 1fr);
background: #fff;
grid-gap: 2px;
min-height: 0; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
.day-item {
padding: 10px;
background: #DFE7E7;
overflow: hidden; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
jsFiddle demo
1fr
vs minmax(0, 1fr)
The solution above operates at the grid item level. For a container level solution, see this post:
- Who does minmax(0, 1fr) work for long elements while 1fr doesn't?
Prevent grid items from expanding when content is added
You're setting the column and row sizes to auto
. This means they will be sized based on their content. Instead, use fr
units, which use the free space in the container.
#content { display: grid; grid-template-rows: 20px auto 20px; grid-template-columns: 20px auto 20px; height: 100vh; background-color: #880022;}
#grid { grid-row-start: 2; grid-column-start: 2; display: grid; grid-template-rows: 1fr 1fr; /* adjustment */ grid-template-columns: 1fr 1fr; /* adjustment */ grid-gap: 2px;}
.tile { display: flex; align-items: center; justify-content: center; background-color: rgba(255, 255, 255, 0.2);}
.tile:hover { background-color: rgba(255, 255, 255, 0.3);}
.tile span { font-size: 2em;}
body { margin: 0;}
<div id="content"> <div id="grid"> <div class="tile"><span>test</span></div> <div class="tile"></div> <div class="tile"></div> <div class="tile"></div> </div></div>
How can I prevent an item in a CSS grid layout from growing to accommodate its content?
The solution was to add position: relative;
to the container that I didn't want to grow (#output_container
) and position: absolute; width: 100%;
to its child (#output
), whose content was causing the growth of the parent container.
function showSize(selector) {
const a = document.querySelector(selector);
const p = a.querySelector('p');
p.textContent = `${getComputedStyle(a).width} x ${getComputedStyle(a).height}`;
}
function showSizes() {
showSize('#left');
showSize('#right1');
showSize('#right2');
window.setTimeout(showSizes, 100);
}
function writeOutput(lines) {
const output = document.querySelector('#output');
let text = '';
for (let i = 0; i < lines; i++) {
for (let j = 65; j < 91; j++) {
text += String.fromCharCode(j);
}
text += "\n";
}
output.textContent = text;
output.scrollTop = output.scrollHeight;
}
document.querySelector('#small').addEventListener('click', () => writeOutput(5));
document.querySelector('#large').addEventListener('click', () => writeOutput(50));
writeOutput(5);
showSizes();
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#output_container {
/* Setting the height to 100% makes it the right size, unless its child div forces it to grow.
I want to prevent this type of growth, because the child content is scrollable.
*/
height: 100%;
/* Setting the height to a fixed size works, but I don't know in advance what the size should be in order for the Output panel to be be size that it would have been if this content were not there. */
/* height: 170px; */
background: lightseagreen;
position: relative;
}
#output {
position: absolute;
width: 100%;
background-color: hsl(0, 0%, 83%);
min-height: 50px;
max-height: 100%;
padding: 0.5em;
overflow: auto;
}
.pre {
white-space: pre;
font-family: monospace;
}
.pre:after {
/* Allows user to see a trailing line break. */
content: '';
}
#grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas:
"left right1"
"left right2";
}
#left {
grid-area: left;
background: lightskyblue;
display: flex;
flex-direction: column;
// min-height: 800px;
}
#grid > div {
padding: 10px;
overflow: hidden;
}
#right1 {
grid-area: right1;
background: seagreen;
min-height: 300px;
display: grid;
grid-template-rows: auto auto 1fr;
}
#right2 {
grid-area: right2;
background: lightsalmon;
min-height: 300px;
}
h1 {
margin: 0.5rem 0;
}
button {
margin: 0.25rem;
}
<div id="grid">
<div id="left">
<p></p>
<button id="small">Small amount of output</button>
<button id="large">Large amount of output</button>
</div>
<div id="right1">
<p></p>
<h1>Output</h1>
<div id="output_container">
<div id="output" class="pre"></div>
</div>
</div>
<div id="right2">
<p></p>
</div>
</div>
Prevent CSS grid from causing overflow
A few things to consider:
missing height reference
Using a percentage value to set the height of the img
is problematic because there is no defined height on the container. Generally speaking, percentage heights should have a height reference on the parent for reliable rendering. Your declarations may or may not be ignored / misinterpreted.
See: Working with the CSS height
property and percentage values
height: 100%
Setting the #results
element to height: 100%
is problematic, if you want to prevent a vertical overflow, because it doesn't factor in the height of the sibling (the h1
).
height: 100% + height of h1 title > height of container (resulting in an overflow)
use a flexible height instead
Instead of using a percentage height, set a more flexible height, such as flex-grow
. This tells the container to simply consume remaining space.
override the minimum height default
Grid and flex items are set by default to stop shrinking at the size of their content. Override that setting with min-height: 0
.
See: Why don't flex items shrink past content size?
cross browser compatibility
Chrome can do the layout with less code (than posted below). It makes more assumptions about an author's intentions. Firefox, Edge and Safari assume less, so require more rules.
#container { display: grid; grid-template-columns: 1fr 5fr; height: 100vh;}
#left { background: lightblue;}
#right { display: flex; flex-direction: column; height: 100vh;}
#results { flex-grow: 1; min-height: 0; display: grid; grid-template-rows: repeat(5, 1fr);}
.result { min-height: 0;}
img { max-width: 100%; max-height: 100%;}
body { margin: 0;}
<div id="container"> <div id="left"> <p>Some stuff on the left....</p> </div> <div id="right"> <h1>Title</h1> <div id="results"> <div class="result"> <img src="https://upload.wikimedia.org/wikipedia/commons/6/62/Paracas_National_Reserve%2C_Ica%2C_Peru-3April2011.jpg" /> </div> <div class="result">Result 2</div> <div class="result">Result 3</div> </div> </div></div>
How to prevent item height expansion from expanding other item in the same row - CSS grid/flex?
So after some more searching I figured that the actually layout style that I needed aligns with the Masonry/Mosaic pattern. Since I now know the name I could do more specific Googling and found a blog post written by Tobias Ahlin with a solution.
https://tobiasahlin.com/blog/masonry-with-css/
The gist is that you need to have the flow direction be columns while being wrapped and then place orderings on the elements using :nth-child
.
/* Render items as columns */
.container {
display: flex;
flex-flow: column wrap;
}
/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n) { order: 3; }
/* Force new columns */
.container::before,
.container::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}
If I'm honest, I'm not really sure why this works. It will also behave unexpectedly depending on the heights of the container and the items.
Hope this helps anyone else who's having issues with this deceptively simple design layout!
How to prevent CSS grid from taking up full width?
Because you're using block level grid which is always takes up the full width available. Use inline-grid
instead.
.layout-grid {
margin: 0 auto;
background-color: lime;
display: inline-grid;
grid-template-columns: 200px 100px;
grid-template-rows: auto;
grid-gap: 1rem;
grid-template-areas:
"company company"
"form billing";
}
<div class="layout-grid">
<div style="grid-area: company">company</div>
<div style="grid-area: form">form</div>
<div style="grid-area: billing">billing</div>
</div>
prevent content from increasing size of CSS grid column
Shubh Sheth's answer is correct but probably another way of writing that is:
grid-template-columns: repeat(3, 1fr);
Comes in handy when you have numerous columns to layout.
Having said this, your error is that you are not specifying the columns but only the areas.
grid-template-areas:
'header header header'
'col1 col2 col3'
;
Grid areas are used in conjunction with grid-template-columns, not as a replacement.
So your layout code should look something like this:
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-areas:
'header header header'
'col1 col2 col3';
In this case, you could very well remove the template-areas code because you are not changing any positions.
Related Topics
Overriding the Encapsulated CSS of External Component
Html 5 Strange Img Always Adds 3Px Margin At Bottom
Prevent Content from Expanding Grid Items
Custom CSS Scrollbar For Firefox
When to Use Margin VS Padding in Css
Better Way to Set Distance Between Flexbox Items
How to Make an HTML Link Look Like a Button
Prevent Body Scrolling But Allow Overlay Scrolling
How to Vertically Center Content With Variable Height Within a Div
Browsers' Default CSS Stylesheets
How Would You Make Two <Div>S Overlap
How to Include CSS Files Using Node, Express, and Ejs
How Are the Points in CSS Specificity Calculated
What's So Bad About In-Line Css
Is There a CSS Hack to Affect Safari Only Not Chrome
Css '≫' Selector; What Is It