I need to create a horizontal layout where one block takes all available space and the other ones shrink to fit their content.
For example:
<div class="grid"> <div class="expand">Long text label</div> <div class="shrink">Button</div> </div>
A more complex example with two rows (an actual grid):
<div class="grid"> <div class="row"> <div class="shrink">...</div> <div class="expand">...</div> <div class="shrink">...</div> <div class="shrink">...</div> </div> <div class="row"> <div class="shrink">...</div> <div class="expand">...</div> <div class="shrink">...</div> <div class="shrink">...</div> </div> </div>
My requirements:
I am targeting Android and iOS smartphones.
I have tried to adapt the code from this answer but I could not make it work for multiple rows. Also, the source code must be out of order, which is confusing (though not blocking for my use case). Here's a jsfiddle: http://jsfiddle.net/k3W8L/
Just use width: 100% and height: 100% in the CSS class of the item you want to fill the grid. Join a max-width property and a max-height property if you don't want a grid item inside a grid container to grow more than some size.
1. Auto-fill: The auto-fill property fills the rows with as many columns as it can fit. The newly added column may be empty but it will still occupy a space in the given row. It is an important property in the CSS grid that make a responsive layout without writing a media query for each grid.
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 .
auto-fit behavior: “make whatever columns you have fit into the available space. Expand them as much as you need to fit the row size. Empty columns must not occupy any space. Put that space to better use by expanding the filled (as in: filled with content/grid items) columns to fit the available row space.”
You need to use grid-template-column
and set the size of column you want to shrink-to-fit as auto
, and specify the size of at least one other column using the fr
unit.
Example: To recreate the sidebar-content layout, where the sidebar is collapsible,
------------------------------- | Sidebar | Content | -------------------------------
you can create the grid as:
.grid { display: grid; ... grid-template-columns: auto minmax(0, 1fr); // see note below grid-template-areas: "sidebar content"; } .sidebar { grid-area: sidebar; } .content { grid-area: content; }
See the codepen here for a demo & code: https://codepen.io/khs/pen/vegPBL You can click on the navbar to see auto-sizing in action.
Note: One thing I've learnt since writing this answer is that in most cases, and especially in a fixed-height/fixed-width layout, you should use minmax(0, 1fr)
instead of 1fr
. The reason is that 1fr
is actually a shorthand for minmax(auto, 1fr)
. This breaks when used for fixed layouts with longer content. See this question for more details: Why does minmax(0, 1fr) work for long elements while 1fr doesn't? Hence I've updated my answer to reflect the fact. The minmax
might be a little verbose, but it's almost always what you want for this kind of layout.
Context: I bumped into this question recently while learning to use grid in my app. With some help from ilyaigpetrov's answer, I was able to get a shrink-to-fit column sizing to work. Their answer doesn't give much explanation though, so I thought I'd add this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With