CSS Flex Box Gallery Issue - css

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>

Related

Vertically center grid items in a column

I have a grid that's two columns side by side. However, there's an odd number of elements, so I would like to offset the right column so it's centered vertically against the left column.
What would be the best way to do that using grid?
Here's an example how i want the layout to look:
Here's an example: https://codepen.io/patricktm/pen/JjMzQWj
body {
max-width: 1000px;
margin: auto;
}
.grid-item {
background-color: #ccc;
border: 1px solid;
height: 200px;
}
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1em;
}
<body>
<div class='grid'>
<div class='grid-item'>1</div>
<div class='grid-item'>2</div>
<div class='grid-item'>3</div>
<div class='grid-item'>4</div>
<div class='grid-item'>5</div>
<div class='grid-item'>6</div>
<div class='grid-item'>7</div>
</div>
</body>
This layout isn't really feasible with Grid because there are fix row tracks that prevent the free flow of items across the column.
You're basically asking the top item in the second column to somehow space itself down in the first row track and cross into the second track, pushing down the other items along the way.
Grid doesn't work this way. The matter is discussed in detail in this post:
Aligning grid items across the entire row/column (like flex items can)
One simple way to make this layout work uses flexbox, which has no column or row tracks crossing through the flex lines. (You'll have to tweak it though, as my simple example will only work on taller screens. On shorter screens additional columns will be generated.)
.grid {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center; /* key */
height: 100vh;
gap: 1em;
}
.grid-item {
background-color: #ccc;
border: 1px solid;
height: 21%; /* prevents a 5th item in the column */
}
body {
max-width: 1000px;
margin: auto;
}
<div class='grid'>
<div class='grid-item'>1</div>
<div class='grid-item'>2</div>
<div class='grid-item'>3</div>
<div class='grid-item'>4</div>
<div class='grid-item'>5</div>
<div class='grid-item'>6</div>
<div class='grid-item'>7</div>
</div>

Is there a way to say that two adjacent CSS grid columns take a certain amount of space in sum?

I have a CSS grid layout with four columns and I need the first two and the second two to take 50% of the container width each. But I don't know the width of the odd columns.
So basically something like grid-template-columns: auto calc(50% - auto) auto calc(50% - auto); I know this doesn't work but I was wondering if this is possible at all. Has anyone ever been in a similar situation and have any suggestions?
edit: so the green columns should fit to the content and the blue ones take the remaining space. The red line is at 50% of the container width.
.container {
display: grid;
grid-template-columns: auto 1fr auto 1fr;
width: 300px;
}
.container > div {
border: 1px solid black;
}
.fit {
background-color: lime;
}
.container > div:not(.fit) {
background-color: lightblue;
}
#helper1 {
grid-column: 1/3;
background-color: orange;
}
#helper2 {
grid-column: 3/5;
background-color: orange;
}
<div class="container">
<div class="fit">ABC</div>
<div>0</div>
<div class="fit">A</div>
<div>1<br>2<br>3</div>
<div class="fit">A</div>
<div>4<br>5</div>
<div class="fit">ABCDEFG</div>
<div>6</div>
<div class="fit">B</div>
<div>7</div>
<div class="fit">D</div>
<div>8</div>
<div id="helper1">50%</div>
<div id="helper2">50%</div>
</div>
So, what values to use for grid-template-columns, so that the blue colums don't have equal width but sum up with their left adjacent to 50% of the container's width.
It's definitely possible, but what you have your hands on is a case of nesting grids. I'd recommend looking into using flexbox as an alternative for situations like these, but here's a stackblitz that may give some grid-related inspiration https://stackblitz.com/edit/angular-vsaato?embed=1&file=src/app/app.component.ts
The reason revolves around the 'auto' sizing of columns is used to fill available space, similar to how flexbox works, but it can't be segmented within a single grid. Thus, we make like a bird and nest!
Hope it's what you're looking for, happy coding!

Can I make a flexbox and therefore its children inherit the screen's height and in doing so, make the last child stick to bottom?

There's a certain peculiarity about flexbox that I both understand and don't understand:
If I am to declare the following:
#container {
display: flex;
border: 1px solid gray;
flex-direction: column;
}
.one {
height: 100px;
width: 100px;
background-color: red;
display: block;
}
.two {
height: 100px;
width: 100px;
background-color: green;
display: block;
}
<div id="container">
<div class="item one"></div>
<div class="item two"></div>
</div>
The container will basically inherit the height of whatever children it has.
Now here's the thing: almost every single layout out there has the main container, the "everything goes here" type of div.
But what happens now is that if the children themselves are not tall enough to push the last child to "stick to the bottom", you'll have a layout looking like this:
But the problem here is that if you make the height of all the children be a percentage of the total height, then things become literally ugly really fast.
Why does flex choose to do this and how can we work around it?
I would keep the footer in it's separate div from the container at the very end.
<div class="content-main">
<div class="main-content">
</div>
</div>
<div class="footer-content">
</div>
If the wordpress template you are using is coded where the footer is inside the same container as main content. I would link to the site/and or test site, so we can better figure out the root cause because the image you posted does not show the browser window, so I cannot see exactly how big of a space on the bottom you have.

CSS Grid - How to make items responsive

I was trying to make the 2 items (box1 and box2) responsive on small screen, but I couldn't seem to figure it out. Please help. Thanks!
<html lang="en">
<head>
<style>
body{
background: lightblue;
}
.container{
padding:10px;
display: grid;
background: lightyellow;
width:100%;
grid-gap:5px;
justify-content:center;
grid-auto-flow: column;
grid-auto-columns: 300px 100px;
}
.box1{
background: lightgray;
min-height:150px;
}
.box2{
background: lightgreen;
min-height:150px;
}
</style>
</head>
<body>
<div class="container">
<div class="box box1">BOX 1</div>
<div class="box box2">BOX 2</div>
</div>
</body>
</html>
You've told the columns to be a fixed width...so they're naturally not responsive.
Use percentage or fractional values instead.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
body {
background: lightblue;
}
.container {
padding: 10px;
display: grid;
background: lightyellow;
width: 100%;
grid-gap: 5px;
justify-content: center;
grid-auto-flow: column;
grid-auto-columns: 3fr 1fr;
}
.box1 {
background: lightgray;
min-height: 150px;
}
.box2 {
background: lightgreen;
min-height: 150px;
}
<div class="container">
<div class="box box1">BOX 1</div>
<div class="box box2">BOX 2</div>
</div>
grid-auto-columns: 300px 100px;
in that line above you use ABSOLUTE sizes. If you want them to be responsive use % instead of px.
something like
grid-auto-columns: 30% 10%;
Any time you use fixed pixel widths, your elements will remain at that size and not be responsive.
The quick and easy solution to this is to switch to percentage widths, which tells the element to be a proportion of its container's size. Assuming the container is itself responsive, then this will make your elements change size according to the width of the screens. You need to do this all the way through your CSS, as any fixed sizes further up the element tree could stop everything inside from responding.
However, a naive percentage figure is often not a perfect solution, because things may not look right with the same proportions at lower screen sizes. For example, a three-column layout may shrink down, but it will look very squashed on a small mobile phone screen.
There are a bunch of solutions to this, and the exact answer will depend on your page design and your preferences.
First up, consider using min-width and max-width with pixel sizes to limit the sizes of your elements. These CSS values will override the percentage if the percentage figure causes them to go above or below the max or min width that you specify. This can be helpful for preventing things from getting exessively squashed or stretched out while still responding appropriately within the desired range.
Next, you need to know about Media Queries. This is a CSS feature that allows you to specify CSS that is only applied when the browser size is within a specified range. (Media queries can do a lot more than this, but I'll leave it to you to investigate them further)
An example might help here:
#media(max-width:600px) {
.container {
grid-auto-flow: unset;
grid-auto-columns: unset;
}
}
The example above uses a media query to switch off your columns if the browser width is 600 pixels or less. For narrow browsers, a column-based layout may not be appropriate, so switching away from it at low resolutions is often a good idea.

Fixed width columns with fluid gutters

I know this can be done with columns, but I have to support IE.
I'm trying to get to a layout whose columns are all fixed width, with the gutters being fluid.
I couldn't get this to work with floats, so I settled on using justified inline-block items:
HTML
<div class="wrapper">
<div></div>
<div></div>
<div></div>
<!-- more divs... -->
</div>
CSS
.wrapper {
text-align: justify;
}
.wrapper div {
width: 100px;
display: inline-block;
}
This works wonderfully, but the last row of divs are all aligned to the left: http://jsfiddle.net/EsHh3/
The only solution I found is to add additional unnecessary divs: http://jsfiddle.net/EsHh3/1/
I feel uncomfortable about this, so I'd like to know if there are any other options.
Please don't tell me not to re-invent the wheel. I have not found any fluid grid system that supports fluid gutters.
For what you want to do, I'm afraid a CSS only solution is not available at the moment, much less if you want it to work in IE8.
Since you want to have (a) items that are in the HTML source as a list (b) a variable number of columns depending on available space (c) column spacing depending on width of container I think the solution you'll need would have to employ at least a bit of javascript.
Consider on of the frameworks proposed in the other answers. One I've worked with and could do what you want is Masonry (or the for-pay bigger brother Isotope). (There's also a non-jQuery version of Masonry). You'll have to come up with a function that when the page is resized, recalculates the desired gutter and reconfigures the framework. Something along the lines of calculating x = how many items would fit per line based on the container width and item width and then dividing the remaining space by x-1.
If you want to stick with the idea of adding extra DIV's to the markup, an alternative would be to listen to resize events, and add DIVs as needed based on the width and how many items would fit per line.
ORIGINAL ANSWER, which failed to fit all the criteria.
Since you're relying on text-align: justified the reason the last line doesn't expand to the full width is because there's no line break at the end of it. So to accomplish that we add an extra element with an wrapper:after {} rule, that is also an inline block with a width of 100% so it guaranties a line break.
See fiddle
The CSS ends up something like:
.wrapper {
text-align: justify;
width: 380px;
margin: 0 auto;
}
.wrapper div {
width: 100px;
display: inline-block;
}
.wrapper:after {content: ''; width: 100%; display: inline-block; background: pink; height: 2px; overflow: hidden}
Note that the pink background is there so that you can see where the element is. You might need to play with the border/margin/padding of that extra element or the wrapper so that content that comes after wrapper doesn't gain extra margin. In chrome unfortunately there's a slight missalignment of the last row items, possibly because of the extra space between the last DIV and the fake element.
Hey I don't know why you want a fluid gutter, but I have a simple grid sample which you might want to have a look and if you want to see the css then click the SCSS on the codepen site. Also, if you are learning then this sample is very good start point for how to make your own grid. Also, to avoid yourself reinventing the wheel you might want to try different grid frameworks out there. Just google css grid frameworks.
you can try this:
.wrapper {
text-align: justify;
width: 380px;
margin: 0 auto;
moz-column-count: 3;
-moz-column-gap: 20px;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
column-count: 3;
column-gap: 20px;
}
Updated URL
This is how I would go about it: http://codepen.io/jeremychurch/pen/wmtJz
.container {
display: table;
width: 100%; }
.cell {
display: table-cell; }
.content {
width: 15em;
margin: 0 auto; }
<div class="container">
<div class="cell">
<div class="content">
</div>
</div>
<div class="cell">
<div class="content">
</div>
</div>
<div class="cell">
<div class="content">
</div>
</div>
</div>

Resources