I have a simple CSS grid, with one cell - an <img>. The grid has a fixed width of 100px and uses grid-auto-columns: 100%; to scale the image down to fit inside:
.grid {
display: grid;
width: 100px;
grid-auto-columns: 100%;
background-color: #844;
}
.grid > * {
grid-column: 1;
grid-row: 1;
}
<div class='grid'>
<img src='https://i.imgur.com/HAwaW3D.png' />
</div>
But for some reason, the grid's height remains as if the image was rendered at its original size, leaving this empty space after the cell:
And I cannot for the life of me find a way to avoid it.
Any ideas on how to make the grid's height match its contents in this scenario?
note: I'm testing in Firefox 56.2.5
Related
I have a grid with 2 columns x 2 rows. All of them are set in minmax() size. Can I ask why the element with class show doesn't take the full size of the grid even though I set all other elements (hide class) in the grid to width 0 and height 0. Doesn't minmax() work properly?
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--seemoresz: 100px;
}
#outer {
display: grid;
grid-template-columns: minmax(calc(700px - var(--seemoresz)), 700px) minmax(0px, var(--seemoresz));
grid-template-rows: minmax(0px, var(--seemoresz)) minmax(calc(700px - var(--seemoresz)), 700px);
width: 700px;
height: 700px;
overflow: hidden;
background-color: aqua;
}
.hide {
width: 0;
height: 0;
}
<div id="outer">
<div class="hide">
hide this
</div>
<div class="hide">
hide this
</div>
<div class="show">
show this
</div>
<div class="hide">
hide this
</div>
</div>
The minmax() function is working fine. So is the calc() function.
The problem is a misunderstanding about the minimum height and widths that are set.
Even though you set the grid items to zero width and height:
.hide {
width: 0;
height: 0;
}
...the grid columns have their own width and height:
#outer {
display: grid;
grid-template-columns: minmax(calc(700px - var(--seemoresz)), 700px) minmax(0px, var(--seemoresz));
grid-template-rows: minmax(0px, var(--seemoresz)) minmax(calc(700px - var(--seemoresz)), 700px);
}
The columns and rows aren't shrinking to zero, which prevents .show from expanding across the entire container.
Consider using auto instead of minmax() in grid-template-*. That will enable the column / row to track the size of the grid item.
Also consider the solutions in these posts:
How to make a column span full width when a second column is not there? (CSS Grid)
Is it possible to hide columns with empty content via the grid-template-columns definition?
minmax() defaulting to max
I would like to have container, that satisfies following conditions:
it has 2 rows and unlimited amount of columns
all items inside it are one-word text elements, that have their width
all items inside it are equal width, defined by the widest element (longest word)
I was thinking about using a flexbox. Since all of the items have known height (because they are one line of text), I can define wrappable container like this:
display: flex;
flex-flow: column wrap;
height: 100px;
All items inside the same column are equal in width. But I want all of the items have the same width. Should I use grid? If yes, how?
You can try CSS grid like below:
.grid {
display: inline-grid;
grid-template-rows: 1fr 1fr; /*two equal rows*/
grid-auto-columns: 1fr; /*all columns will be equal*/
grid-auto-flow: column;
}
span {
outline: 1px solid;
padding: 5px
}
<div class="grid">
<span>some_text</span>
<span>text_long</span>
<span>text</span>
<span>a</span>
<span>text</span>
<span>some_text</span>
<span>some_looong_text</span>
<span>some_text</span>
</div>
If you want all the items to have the same width, you need to define their width within their class.
.container{
display: flex
height: 100px
}
.container__item{
width: 20px
height: 100%:
}
Change the width to your pleasure.
Currently I try to create an "image gallery" with flex box.
This is what I currently have: https://jsfiddle.net/neu28Lnc/2/
The width of the images are always 50% - meaning I will always have 2 images next to each other.
Height of the page is not fixed - you should be able to scroll / add more images.
The problem I have, is that I want to remove the gaps between those images.
Like this: https://jsfiddle.net/neu28Lnc/1/ (hard coded with margins).
Usually I would use flex-direction: column; but since I have a no height, it will never wrap to a 2nd column.
Maybe some of you can help me with my issue / have a better solution.
Thanks in advance.
Syllz
You can do something with css Grid, but after all, css grid is more for grids, of course.
A grid is made of lines which supports each other. Each rectangular form drawn by those lines inevitably share a common horizontal and vertical line.
Flexbox is another option, but you have to set a height to your container so that columns wrap with the flex-direction: column.
If you have a lot of elements, and they exceed the space given by the height we have established, the container will break, with the remaining elements showing up on one side.
The best option here is Multi-column. Example
Cons:
- We can't have an item span more than 1 column.
- The items aren`t listed horizontally.
For me is the best "css only" solution.
W3C - CSS Multiple Columns
You can use masonary using grid layout. Hope this is helpful to you.
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 20px;
}
.image {
height: 50px;
background: #ddd;
}
.image2 {
height: 150px;
background: #abc;
}
.image3 {
height: 180px;
background: #def;
}
.image4 {
height: 30px;
background: #fad;
}
.image5 {
height: 150px;
background: #ddd;
}
<div class="container">
<div class="image img">img1</div>
<div class="image2 img">img2</div>
<div class="image3 img">img3</div>
<div class="image4 img">img4</div>
<div class="image5 img">img5</div>
<div class="image img">img1</div>
<div class="image2 img">img2</div>
<div class="image3 img">img3</div>
<div class="image4 img">img4</div>
<div class="image5 img">img5</div>
</div>
I have 3 divs inside a container. There are no nested divs.
I am using flex and order property.
On mobile, it is ok with order property.
But on larger screens it fails.
I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.
HTML FILE
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
CSS FILE
/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;
}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;
}
/***************************/
#media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}
In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?
Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.
In flexbox, items in a row wrap container must wrap to new rows. This means that div3 cannot wrap beneath div2. It must wrap beneath div1.
Here's how items wrap in a flex container with row wrap:
If div3 were to wrap under div2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.
Put another way, you can't make a flex item wrap under another item in the same row.
As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating unsightly gaps.
For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.
One way to align the items would be to wrap div2 and div3 in their own container. This new container would be a sibling to div1. It can then become a nested flex container with flex-direction: column. Now the gaps are gone and layout looks right.
Except, in this particular case, you need the order property to work (meaning all items must have the same parent), so a nested flex container is out of the question.
What may work is column wrap instead of row wrap:
/*************** MOBILE *************/
.container {
display: flex;
flex-direction: column;
height: 200px; /* necessary so items know where to wrap */
}
div.orange {
background-color: orange;
}
div.blue {
order: -1;
background-color: aqua;
}
div.green {
background-color: lightgreen;
}
.container > div {
width: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
/***************************/
#media screen and (min-width: 800px) {
.container {
flex-wrap: wrap;
}
div.orange {
flex-basis: 100%;
width: 50%;
}
div.blue {
flex-basis: 50%;
width: 50%;
order: 0;
}
div.green {
flex-basis: 50%;
width: 50%;
}
}
<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>
jsFiddle
Here are two other options:
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
Related post: Is it possible for flex items to align tightly to the items above them?
I am building a page which has 8 items distributed over two rows using a flexbox container. Each item is 25% wide and 50% high. Because it is a horizontal scrolling page, I use px instead of % (values are generated by javascript based on the screen size). For this example I'm using a screen size of 1440px.
Now when I click on one of the items, it has to go to the very start, become twice as wide and twice as high.
It currently looks like this (ignore the blurry images please):
Initial state
Making the items wider is no problem (using flex-basis: 720px), but when I make the first item higher (height 100%), the items that were previously on the second row are no longer visible. Instead they are pushed down because of the first image: State when I make the first item bigger
What I actually want is that the smaller items are evenly distributed next to the bigger item. Is this possible?
This is my HTML markup (it contains web2py syntax, but there are 8 items in total):
<div class="scrollable">
<div class="flexcontainer">
{{for s in stages:}}
<div class="flexitem">
<img src="{{=URL('default', 'download', args=s.image)}}" class="stage-img">
</div>
{{pass}}
</div>
</div>
And this is my CSS:
.flexcontainer {
position: relative;
display: flex;
flex-flow: row wrap;
height: 100%;
width: 3000px; /* Hardcoded width for testing purposes */
}
.flexcontainer .flexitem {
flex: 1;
flex-basis: 360px;
height: 50%;
}
.flexcontainer .flexitem img {
width: 100%;
height: 100%;
}
/* Style for the active/clicked item */
.flexcontainer .flexitem.active {
flex-basis: 720px;
height: 100%;
}