css: aspect ratio with grid-template - css

I am using the grid box in css. Each item in the grid must be 1/3 of the width of the container. I want the aspect ratio of each item to be 2/1 which means the width should always be twice as big as the height. If the size of the container resizes I want the items to resize as well while keeping the aspect ratio. How do I do this?
css:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 5px;
}
.grid-item {
background-color: orange;
border: solid;
}
html:
<div class="grid-container">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>

You need your grid items to span their place in the grid. As long as the browsersupport for aspect-ratio is not complete, you could use the padding-trick:
.grid-item {
position: relative;
display: flow-root;
&:before {
content: '';
float: left;
padding-top: 50%;
}
}

Related

Centering grid clips nested grid

I'm trying to create layout with two columns as nested grid with left grid having dynamic number of columns/width and right column with static width. Left grid can have many columns (from 0 to n) and right grid has static width. I want to center parent of these grids horizontally but adding justify-content: center causes overflow to clip some content of left grid
where I want it to work as here:
https://jsfiddle.net/4o8bkdtm/17/
Where is centered to the full width of the grid parent.
Reproduction
.grid {
background-color: #e2e2e2;
height: 400px;
display: grid;
overflow: auto;
grid-template-columns: max-content 400px;
justify-content: center;
}
.grid-1,
.grid-2 {
border: 1px solid #000000;
display: grid;
grid-template-columns: 1fr;
}
.grid-1 {
direction: rtl;
grid-auto-columns: max-content;
}
.grid-1>div {
width: 150px;
}
<div class="grid">
<div class="grid-1">
<div style="grid-column: 1; grid-row: 1;">first</div>
<div style="grid-column: 2; grid-row: 1;">second</div>
<div style="grid-column: 3; grid-row: 1;">third</div>
</div>
<div class="grid-2">
static width
</div>
</div>
Reproduction fiddle: https://jsfiddle.net/zLmxorgv/5/

Keep wrapped flex items on left while others centred

I'm trying to display a list of flex items with fixed width in the center of flexbox with wrap by using margin: auto. When wrap happens, the wrapped item also centers in its own container:
Is there a way to keep the wrapped item on the left while everything else is centred?
.parent {
display: flex;
flex-wrap: wrap;
height: 100px;
}
.children {
flex: 1;
border: 1px solid black;
max-width: 300px;
min-width: 300px;
margin: auto;
height: 100px;
margin-top: 1rem;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
You're saying you want the items centered, but when there is only one item that wraps, you want it left-aligned.
The problem is that there is really no left-alignment in the flex container. Everything is centered, based on available space in the row. So the single item in the last row has no concept of what's going on above, and nothing to align with.
Here's what happens if you left-align the last item (on wider screens):
.parent {
display: flex;
flex-wrap: wrap;
}
.children {
border: 1px solid black;
max-width: 300px;
min-width: 300px;
margin: auto;
height: 100px;
margin-top: 1rem;
}
.children:last-child {
margin-left: 0;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
What you need is a nested grid structure.
A top-level grid to establish the centering.
A nested grid for the wrapping.
In the demo below, you'll find a three-column grid. The left and right columns are empty (spacer) items, created with CSS pseudo-elements, and set to equal widths. This centers the middle item.
The middle item is also a grid container. Using the repeat() and auto-fill functions, the items can wrap, with individual items aligning left.
body {
display: grid;
grid-template-columns: auto 1fr auto;
}
body::before,
body::after {
content: ''; /* in grid (and flex) layouts, pseudo-elements on the container
are treated as items */
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
grid-auto-rows: 100px;
grid-gap: 10px;
justify-content: center; /* centers the columns (not the items, like in flex) */
}
.children {
border: 1px solid black;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
jsFiddle demo

CSS how to only show 1 row and hide the others?

I have a nav at the top of my page.
In it I have 5 market stocks for 5 different companies. I want to display the 5 at full width but as the window gets smaller, I basically want behavior which will cut off the ones that overflow, and resize the remaining ones to fill up the nav container (so let's say at some point it would only show 3 of the stocks and hide the others). Here is the code right now:
.stocks-container {
display: grid;
grid-template-columns: repeat(auto-fit, 150px);
grid-template-rows:1fr;
grid-auto-rows: 0;
overflow-y: hidden;
justify-content: space-between;
width: 75%;
font-size: 11px;
overflow-y: hidden;
}
What this does currently is almost what I need. The problem is that now the stock items that overflow, and should basically create a new row, get mushed on top of the first row. Again, I don't want them to create a new row, or be scrollable. I just don't want them to be showing at all. Any ideas?
You can use CSS max-height and #media queries to achieve this effect:
Give the .stocks-container a max-height which corresponds with the height of a single grid row and declare overflow: hidden
This ensures that there will now only ever be a single row visible (ie. no vertical wrapping of rows).
Now add a short series of break-point media queries to reset grid-template-columns as percentages of the viewport width.
This enables those grid boxes which are still visible to fill the entire horizontal width reserved for the .stocks-container.
Working Example:
.stocks-container {
display: grid;
grid-template-columns: repeat(5, calc(20% - 6px));
grid-template-rows: 92px;
grid-column-gap: 6px;
grid-row-gap: 6px;
max-height: 92px;
font-size: 11px;
overflow: hidden;
}
.stocks-container div {
height: 80px;
text-align: center;
border: 1px solid rgb(127, 127, 127);
}
#media only screen and (max-width: 900px) {
.stocks-container {
grid-template-columns: repeat(4, calc(25% - 6px));
}
}
#media only screen and (max-width: 750px) {
.stocks-container {
grid-template-columns: repeat(3, calc(33.33% - 6px));
}
}
#media only screen and (max-width: 600px) {
.stocks-container {
grid-template-columns: repeat(3, calc(50% - 6px));
}
}
<div class="stocks-container">
<div>
<h2>Company 1</h2>
<p>Company Stock</p>
</div>
<div>
<h2>Company 2</h2>
<p>Company Stock</p>
</div>
<div>
<h2>Company 3</h2>
<p>Company Stock</p>
</div>
<div>
<h2>Company 4</h2>
<p>Company Stock</p>
</div>
<div>
<h2>Company 5</h2>
<p>Company Stock</p>
</div>
</div>

How to collapse the width of CSS-grid to center it in the grid-container

Is it possible to collapse the width of a CSS grid with auto-filled columns to the minimal width required to have equal width columns that are centered with respect to the grid container?
IE if I have grid defined like this:
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
and the grid-container is 800px wide, is there a way to ensure the grid itself is only 600px wide instead of 800px?
Since I'm not sure how to explain it properly I've made a fiddle: https://jsfiddle.net/mhozx4ns/10/
I'm looking for a way that makes the top container behave like the bottom one if it is wider than what is required to place all children in one row.
body {
width: 800px;
background: black;
}
.grid div {
height: 50px;
background: #ededed;
}
.css {
display: grid;
justify-content: center;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-column-gap: 64px;
grid-row-gap: 64px;
background: red;
}
.manual {
width: 664px;
margin: 32px auto 0;
background: blue;
}
.manual:after {
content: '';
display: table;
width: 100%;
}
.manual.grid div {
width: 300px;
float: left;
margin-bottom: 64px;
}
.manual.grid div:nth-of-type(even) {
margin-left: 64px;
}
.manual.grid div:last-child {
margin-bottom: 0;
}
}
<div class="css grid">
<div>
</div>
<div>
</div>
<div>
</div>
</div>
<div class="manual grid">
<div>
</div>
<div>
</div>
<div>
</div>
</div>
When you say minmax(300px, 1fr) in your rule, you're saying this:
Each column must be a minimum width of 300px and a maximum width of 1fr.
The fr unit consumes free space in the grid container. So if your container is 800px wide, the fr will factor in all that space.
Also, since fr consumes all free space, justify-content, which functions by distributing free space, is rendered useless.
Why not just remove the 1fr?
body {
width: 800px;
background: black;
}
.css {
display: grid;
justify-content: center;
grid-template-columns: repeat(auto-fill, 300px);
grid-auto-rows: 50px;
grid-column-gap: 64px;
grid-row-gap: 64px;
background: red;
}
.grid div {
background: #ededed;
}
<div class="css grid">
<div></div>
<div></div>
<div></div>
</div>

Single-row grid with height 1fr not filling height in Chrome

I have a CSS Grid inside a Flexbox column, and the grid has flex-grow: 1.
In Chrome, the grid expands to fill available space, but its content does not, even with align-content: stretch on the grid. In Firefox and Edge, the content expands to fill the grid's height, as desired.
Here's a pen that reproduces the problem, and images of how it looks in different browsers. Is this a bug with Chrome, and if so, can anyone suggest a straightforward workaround?
Chrome
Firefox
Edge
#wrapper {
display: flex;
flex-direction: column;
height: 15rem;
background-color: #aaa;
}
#grid {
flex-grow: 1;
display: grid;
background-color: #ccf;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
align-content: stretch; /* "end" correctly puts the row to the bottom */
}
#left {
background-color: #fcc;
}
#right {
background-color: #cfc;
}
<div id="wrapper">
<div id="top">not in grid</div>
<div id="grid">
<div id="left">left</div>
<div id="right">right</div>
</div>
</div>
Is this a bug with Chrome, and if so, can anyone suggest a straightforward workaround?
It looks like a bug in Chrome. But I can't say for sure.
Here's what's happening:
You have the flex item grid container set to consume all available height with flex-grow: 1
Because you've only defined the flex-grow property, the other two flexibility properties – flex-shrink and flex-basis – remain at their default values.
The default value of flex-shrink is 1, and is not pertinent to this problem.
The default value of flex-basis is auto, and is the source of the problem.
If you add flex-basis: 0 to your code, the item takes full height in Chrome, as well.
revised codepen
#wrapper {
display: flex;
flex-direction: column;
height: 15rem;
background-color: #aaa;
}
#grid {
/* flex-grow: 1; */
flex: 1; /* fg:1, fs:1, fb:0 */
display: grid;
background-color: #ccf;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}
#left { background-color: #fcc; }
#right { background-color: #cfc; }
<div id="wrapper">
<div id="top">not in grid</div>
<div id="grid">
<div id="left">left</div>
<div id="right">right</div>
</div>
</div>

Resources