I'm trying to create a horizontally scrollable div with flexbox. So far, I have most of it. However, the only problem I am facing is that I'm trying to add space to my items, but for some reason, nothing seems to be working. I've tried adding margin, padding, justifying content, etc. Here's a jsfiddle of what I'm trying to achieve.
.grid {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
margin-bottom: 20px;
justify-content: space-between;
}
/*Each item is one column*/
.item {
width: 50%;
}
.article-scroll-mobile {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
flex-wrap: nowrap;
text-align: center;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
/*For iOS smooth scroll effect*/
}
<div class="grid article-scroll-mobile">
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
</div>
There a few things you have to consider.
First of all; with justify-content you define how remaining space is handled. By using space-between your items will be aligned so that the space between them is equal, by setting it to center the remaining space will be around all items, with all items stuck together.
In your case though, there is no remaining space, because your items actually stretch the div. So that doesn't help you.
Next; you've set the width of an item to 50%. Which is fine, your item's will be 50% of the viewport. That's because your grid will implicitly be 100% of the viewport. But because your image overflows the box, you can set margins if you want, and they will put the items further apart, but you need big-ass margins to actually see them. Bigger then the overflowing of your image.
So, to fix this, you make the images responsive by making them as width as the item;
.item img { display: block; height: auto; width: 100%; }
But that poses another problem; flexbox tries to size it's flex items to fit it all into the flex container. So you'll see that it automatically resizes your items so they will all fit in. To fix this, you have to explicitly force the width of your items;
.item { flex: 0 0 50%; }
Which is a shorthand for;
.item { flex-grow: 0; flex-shrink: 0; flex-basis: 50%; }
So basically you say; make my item 50% of it's container, and don't use your awesome algorithm to try to make it bigger or smaller.
Now you've got what you want, and you can use margin-right: 20px for example to create a 20px space between your items.
Full snippet;
.grid { display: flex; width: 100%; }
.item { flex: 0 0 50%; margin-right: 20px; }
.item img { display: block; height: auto; width: 100%; }
.article-scroll-mobile {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
flex-wrap: nowrap;
text-align: center;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
/*For iOS smooth scroll effect*/
}
<div class="grid article-scroll-mobile">
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
<div class="item">
<img src="https://www.w3schools.com/howto/img_fjords.jpg">
</div>
</div>
There is column-gap to adjust row gaps between elements.
.form-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: stretch;
column-gap: 0.875rem;
}
Related
I have 4 items inside a flex container. I want to make the 4 of them the same width and height, but always having them in 2 different rows (so a 2 X 2 grid).
Since the children are in different flex containers, they do not obey flex-grow: 1; Even the children of the same row do not obey the rule. And if I put them in the same container, they put themselves in the same row, and I need the 2 X 2 grid.
You can find a codepen here with the same code: https://codepen.io/mongolhippie/pen/yLYQbVd?editors=1100
.tile {
display: flex;
flex-direction: column;
border: 2px solid #A97C50;
border-radius: 20px;
padding: 20px;
margin: 25px;
/* THESE 3 OPTIONS TO CONTROLL HAVING THE SAME SPACE FOR EVERY TILE */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
flex: 1;
}
.tile p {
font-size: min(calc( 1.125vw + 1.2rem ), 3.9rem);
}
.flex-center{
display: flex !important;
justify-content: center !important;
align-items: center;
}
.manual-link {
text-decoration: none !important;
color: var(--brown-dark);
}
.manual-link:hover {
text-decoration: none !important;
color: var(--brown-dark);
}
.icon-and-title{
display: flex;
align-items: center;
}
.icon-and-title p{
font-size: min(calc( 1.125vw + .9rem ), 3.9rem);
}
.icon-and-title img{
max-width: 100%;
height: auto;
transition: all .3s;
max-height: 80px;
margin-right: 20px;
margin-bottom: 10px;
}
<div class="flex-center">
<a class="manual-link" href="/manuals/manual-it.pdf">
<div class="tile">
<div class="icon-and-title">
<img src="https://i.pinimg.com/originals/06/bc/e8/06bce81285badba0c3becd273ca67f95.png" alt="">
<p>ADMIN</p>
</div>
<div class="links-manuals">
<p>For the administrator of the app</p>
</div>
</div>
</a>
<a class="manual-link" href="/manuals/manual-developers.pdf">
<div class="tile">
<div class="icon-and-title">
<img src="https://i.pinimg.com/originals/06/bc/e8/06bce81285badba0c3becd273ca67f95.png" alt="">
<p>DEVELOPERS</p>
</div>
<div class="links-manuals">
<p>To upgrade the Code</p>
</div>
</div>
</a>
</div>
<div class="flex-center">
<a class="manual-link" href="/manuals/manual-design.pdf">
<div class="tile">
<div class="icon-and-title">
<img src="https://i.pinimg.com/originals/06/bc/e8/06bce81285badba0c3becd273ca67f95.png" alt="">
<p>DESIGNERS</p>
</div>
<div class="links-manuals">
<p>Style guide</p>
</div>
</div>
</a>
<a class="manual-link" href="/manuals/ngo.pdf">
<div class="tile">
<div class="icon-and-title">
<img src="https://i.pinimg.com/originals/06/bc/e8/06bce81285badba0c3becd273ca67f95.png" alt="">
<p>NGOs</p>
</div>
<div class="links-manuals">
<p>The project</p>
</div>
</div>
</a>
</div>
Which is the secret to having them in a 2 X 2 disposition with the same width and height??
Thanks a lot!
Simply move from Flexbox to CSS GRID.
So change the CSS like this:
.flex-center{
display: grid;
grid-template-columns: 1fr 1fr;
}
Since you are handling your layout in 2 different rows we'll play with the grid-template-columns.
The fr unit tells the grid to have to "cells" with the same width.
Better renaming the class from .flex-center to something else since you'll use CSS GRID.
Here the updated working Codepen
Flebox are very good to make a 1D flexible container (vertically or horizontally) and can also handle multi-lines when they is no more space for all elements (instead of overflow the container)
BUT They is another display type used mainly for 2D flexible grid. And it's called grid, you should look at this guid in order to use it right.
As you want by default a 2D (2x2) grid, it'll be way easier to use it, This is a very basic grid you can set in order to have both columns and rows to take half of available space (50%)
.container {
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
}
I want to make the background color fill the area so it's always the same height for the longest amount of text, and center the text vertically, regardless of how many lines it is. I don't want to set a fixed height on the parent if possible as that may change.
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: -8px;
margin-right: -8px;
}
.flexbox .sm-col-3 {
width: calc(1/3 * 100% - 16px);
}
.entry {
position: relative;
}
.entry-image {
display: block;
margin: 0 auto;
}
.entry-title {
margin: 0
}
.entry-title-link {
position: absolute;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 8px 9px 9px;
background: rgba(0, 87, 149, 1);
color: #fff;
width: 100%;
}
<div class="articles-container flexbox">
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
Some Long Wrapping Two Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
One Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
</div>
You should think of this problem in terms of 2 different layouts.
the first one is to put your entry divs next to each other, 3 per line, same height each. That's the flex row you are using on .flexbox
the second one is within each entry div, to put the image on top and the link on the bottom. That's what I'm proposing here with another flex layout, nested inside the first one.
So the way to do this is to apply flex and column on .sm-col-3 to create the nested flex layout. And then it's just up to you how you need to allocate the space. The most common way to do it in this type of case would be to allocate a fixed size (or at least fixed ratio) to the image on top, and then put a flex: 1 on the text at the bottom so that it will occupy everything that's left, thus occupying the same amount of space on each entry.
Now if you also need to vertically center the next in that bottom section .entry-content, that is a 3rd problem to be solved.
the box at the bottom should have its content vertically centered
Except that now that we've divided the problem into its sub-problems, that 3rd one is easy to solve (tons of tutorials online on how to vertically center something within its parent). But since we're doing flexboxes here, let's use that a third time. That's going to be display: flex and align-items on .entry-content.
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: -8px;
margin-right: -8px;
}
.flexbox .sm-col-3 {
width: calc(1/3 * 100% - 16px);
display: flex;
flex-direction: column;
}
.entry {
position: relative;
}
.entry-image {
display: block;
margin: 0 auto;
}
.entry-content {
flex: 1;
background: rgba(0, 87, 149, 1);
padding: 8px 9px 9px;
display: flex;
align-items: center;
}
.entry-title {
margin: 0;
}
.entry-title-link {
text-align: center;
color: #fff;
width: 100%;
}
<div class="articles-container flexbox">
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
Some Long Wrapping Two Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
One Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
</div>
I'm just trying the FlexLayout for different screen sizes.
The 3 boxes/divs below should be side to side on a large display, if it shrinks they should be above each other. But my top div is outside of my window and I don't want that.. How can I fix that?
<div class="container" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="space-around center">
<div class="asd" [style.background-color]="'black'"></div>
<div class="asd" [style.background-color]="'green'"></div>
<div class="asd" [style.background-color]="'blue'"></div>
</div>
.asd {
min-height: 500px;
min-width: 400px;
}
.container {
height: 100%;
}
Flex elements won't stack unless you use flex-wrap: wrap along with a min-width or flex-basis declaration.
Basically, if the number of flex elements in the row would need to be smaller than their min-width they'll wrap to the next line.
.flexContainer {
display:flex;
max-width: 80%;
margin: 20px;
justify-content: space-between;
flex-wrap: wrap;
}
.flexItem {
background: #dddddd;
padding: 20px;
min-width: 200px;
margin: 0 10px 10px 0;
}
<div class="flexContainer">
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
</div>
I have the following layout (simplified version). .account is the flex-container and .card-two holds the actual table. When there is a lot of content, everything works fine, but when .card-two doesn't have enough content (when showing error messages), it does not fill the height of its parent .content. the cards have a background color set, so the entire effect looks quite ugly.
How do I make the card behave and stretch to fill its container? I tried setting height on .account, setting flex-basis:1 0 0, but it doesn't work. setting height:100% to .card-two just makes it massively overflow its parent. Note: I do not have a lot of control on the HTML.
HTML code:
<div class="container">
<div class="account">
<div class="sidebar">This is a sidebar aka the first column</div>
<div class="content">
<div class="card-one">this is card number one. full width of the parent</div>
<div class="card-two">this card should have a lot of content. but sometimes it doesn't.</div>
</div>
</div>
</div>
CSS (without the changes I have tried):
.container{
// just a generic container.
width:1140px; margin:auto;
}
.account{
display: flex;
}
.sidebar{
width: 25%;
}
.content{
width: 75%;
}
here's a codepen (with some comments as to what I have tried): https://codepen.io/samia92/full/MVJqwQ
any help is much appreciated.
You need to add flex to .content then only card-two can have flexbox properties.
.container {
width: 600px;
margin: auto;
box-sizing: border-box;
}
.account {
display: flex;
height: 400px;
}
.card {
background: #ddd;
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.5);
padding: 15px;
}
.sidebar {
width: 25%;
margin-right: 10px;
}
.content {
width: 75%;
display: flex; /*Addded*/
flex-direction: column; /*Addded*/
}
.card-one {
margin-bottom: 20px;
}
.card-two {
flex: 1; /*Addded*/
}
<div class="container">
<div class="account">
<div class="sidebar card">
This is a sidebar aka the first column
</div>
<div class="content">
<div class="card-one card">
<p>this is card number one. full width of the parent</p></div>
<div class="card-two card"><p>this card should have a lot of content. but sometimes it doesn't.</p>
<p>I want it to expand to it's parent, which has appropriate height</p>
<p>There You go.</p>
</div>
</div>
</div>
</div>
I tried to follow the advice in this answer, and as shown in this CodePen, but the image that needs to flex is still keeping its original dimensions unless the screen is so narrow it is alone on the row.
There is another set of divs in the real page in a similar situation - it would help the page work across a much larger range of widths if the side divs would shrink.
The div it is wrapped in has flex: auto; on it and img {width: 90%; height: auto;} for any image in it, the parent of that div has style="flex: 0 1 250px;" on it.
Here is a CodePen of it.
I guess there is a simple mistake, if not I suppose I'll make the image the background of the div it is currently in, and set background-size: 100% auto; on it.
section {
padding: 15px;
display: flex;
flex-wrap: wrap;
margin-top: 3vw;
margin-left: 6vw;
}
.outerDiv {
background-color: rgba(50, 50, 0, 0.5);
}
.innerDiv {
background-color: rgba(10, 10, 10, 0.6);
display: flex;
flex-flow: column nowrap;
align-items: flex-end;
margin: 15px;
}
.innerDiv p {
padding: 6px 18px 0 15px;
}
.imgResize {
flex: auto;
align-self: center;
padding: 15px;
}
.imgResize img {
width: 90%;
height: auto;
}
<section>
<div class="outerDiv">
<div class="innerDiv" style="flex: 0 1 250px;">
<h2>The Rocket Equation</h2>
<p>Mass ratio:</p>
<div class="imgResize">
<a href="rotovator.html">
<img src="http://www.moonwards.com/img/animatedRotovatorLink.png">
</a>
</div>
</div>
</div>
<div class="outerDiv">
<div class="innerDiv">
<h2>Suborbital Hop</h2>
<img src="http://www.moonwards.com/img/mapmini.jpg" width="512" height="256">
<canvas id="subOrbitalCanvas" width="512" height="256"></canvas>
</div>
</div>
</section>
An initial setting on flex items is min-width: auto. This means that a flex item, by default, cannot shrink below the size of its content.
In this case, the section element is the primary flex container.
The flex items are .outerDiv.
Because these flex items contain images, they cannot shrink below the image's size. To overcome this, override the default with min-width: 0.
revised codepen
Okay, so now the item can shrink past the content, but the image is still inflexible.
You can fix that with:
img { width: 100%; height: auto; }
revised codepen
Here's more information: Why doesn't flex item shrink past content size?