Use flexbox to wrap elements within flex elements to the next line - css

I have a flexbox which contains "product boxes", which themselves contain thumbnails of the product. Is there a way I can wrap the thumbnails to the next line if the product box runs out of space on that line? I might have 10+ thumbnails per product so it might even need to run to the next two lines if needed, but they should still be "inline" with the reset of the products and not line-break at their beginning and end.
I don't have to use flexboxes, but I assume they might be useful for something like this. However I cannot figure this one out. Thanks!
.products {
display: flex;
background: yellow;
}
.product {
flex: 1;
margin: 1em;
background: magenta;
}
.thumbnail {
display: inline-block;
margin: 1em;
width: 100px;
height: 40px;
background: blue;
}
<div class="products">
<div class="product">
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
</div>
<div class="product">
<div class="thumbnail"></div>
<div class="thumbnail"></div>
<div class="thumbnail"></div>
</div>
</div>
What happens:
What I would like to happen:

With a few smaller adjustments you can achieve that, where to not group the thumbnails and use a wrapper to compensate for the top margin.
.products {
background: yellow;
}
.wrapper {
display: inline-flex; /* avoid collapsed margin on parent element */
flex-wrap: wrap;
margin-top: -15px; /* so margin only affect second row */
}
.products a {
padding: 1em;
margin-top: 15px;
background: magenta;
}
.products a:nth-child(3n) { /* target every 3rd element with a right margin */
margin-right: 15px;
}
.thumbnail {
width: 100px;
height: 40px;
background: blue;
color: white;
}
<div class="products">
<div class="wrapper">
<div class="thumbnail">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
</div>
</div>
As you mentioned in a comment, where the amount of thumbnails is arbitrary, it might not be practical to use nth-child to create the gap between the elements to be viewed as a group.
Based on that fact, and assumed you generate these thumbnails dynamically, you can either use a space element, or like below, add the margin inline.
.products {
background: yellow;
}
.wrapper {
display: inline-flex; /* avoid collapsed margin on parent element */
flex-wrap: wrap;
margin-top: -15px; /* so margin only affect second row */
}
.products a {
padding: 1em;
margin-top: 15px;
background: magenta;
}
.thumbnail {
width: 100px;
height: 40px;
background: blue;
color: white;
}
<div class="products">
<div class="wrapper">
<div class="thumbnail">1</div>
<div class="thumbnail">2</div>
<a style="margin-right: 15px" href="#"><div class="thumbnail">3</div></a>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<a style="margin-right: 15px" href="#"><div class="thumbnail">6</div></a>
</div>
</div>

Removed the two .product
then wrapped each thumbnail in an inline-block
the inline-blocks have a -2.5px left and right margins so they appear to belong to the same container when inline.
the outer block is display:table
every 3rd thumbnail has a .5em right margin (as suggested by LGSon)
Demo
*,
*::after,
*::before {
margin: 0;
padding: 0;
border: 0;
}
main {
display: table;
table-layout:fixed;
padding: .5em;
background: yellow;
}
b {
display: inline-block;
padding: 8px;
margin: 10px -2.5px;
background: magenta
}
.thumbnail {
width: 100px;
height: 40px;
background: blue;
}
main>div>b:nth-of-type(3n) {
margin-right: .5em
}
<main>
<div class="products">
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
<b><div class="thumbnail"></div></b>
</div>
</main>

Related

CSS: Placing two different sized elements so that the middle is exactly between them [duplicate]

I'm trying to align a top menu which consists of 3 blocks of content.
What I'm trying to achieve is this:
block 1: left aligned
block 2: centered horizontally
block 3: right aligned
If all 3 blocks were the same size, I could use flexbox (as in the snippet), but they're not, so it doesn't produce the output I require.
Instead, flexbox puts equal space between the 3 blocks - resulting in the middle block being aligned off-center.
I was wondering if this could be achieved with flexbox, or if not, another solution. This needs to work robustly in production so a 'Grid' solution is not applicable as there is insufficient support.
.container {
margin: 20px 0;
}
.row {
background-color: lime;
display: flex;
justify-content: space-between;
}
.item {
background-color: blue;
color: #fff;
padding: 16px;
}
<div class="container">
<div class="row">
<div class="item">left, slightly longer</div>
<div class="item">center, this item is much longer</div>
<div class="item">right</div>
</div>
</div>
You can consider flex-grow:1;flex-basis:0% for the left and right elements then use text-align to align content inside. I have added an extra wrapper to keep the background only around the text.
The trick is to calculate the free space by removing only the middle content and split it equally to the left and right element.
.container {
margin: 20px 0;
padding-top:10px;
background:linear-gradient(#000,#000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:last-child {
text-align: right;
}
.item span{
background-color: blue;
display:inline-block;
padding: 16px;
border: 2px solid red;
box-sizing:border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
You can also do the same by keeping the element close. Simply adjust text-align:
.container {
margin: 20px 0;
padding-top: 10px;
background: linear-gradient(#000, #000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:first-child {
text-align: right;
}
.item span {
background-color: blue;
display: inline-block;
padding: 16px;
border: 2px solid red;
box-sizing: border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
I asked what seems to be a very similar question and stack overflow directed me here. The response from #Paolamoralesval inspired me to realise the required effect can be achieved in CSS grid. Now that grid support is pretty much universal I hope that this meets everyone's needs. This solution is I believe fully responsive to window size as well as height and width of the header items as you should see if you resize the window where you view the snippet.
.header {
grid-row: 1;
grid-column: 1;
display: grid;
grid-template-rows: min-content;
grid-template-columns: 1fr 1fr 1fr;
}
.header-left {
justify-self: start;
align-self: center;
text-align: left;
background-color: red;
}
.header-center {
justify-self: center;
align-self: center;
text-align: center;
background-color: green;
}
.header-right {
justify-self: end;
align-self: center;
text-align: right;
background-color: blue;
}
.shrink-kitty {
width: 200px;
}
<html>
<body>
<div class="page">
<div class="header">
<div class="header-left">
<img class="shrink-kitty" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Kittyply_edit1.jpg/1280px-Kittyply_edit1.jpg"/><br/>
By David Corby<br/>
Edited by: Arad<br/>Image:Kittyplya03042006.JPG<a><br/><a href="https://creativecommons.org/licenses/by/2.5" title="Creative Commons Attribution 2.5">CC BY 2.5, Link
</div>
<div class="header-center">In the middle</div>
<div class="header-right">
Much much much much more on the right hand side</br>
Indeed two lines
</div>
</div>
<div class="body">Body of the page</div>
<div class="footer">At the bottom</div>
</div>
</body>
</html>
can you give flex-grow:1 for the item class and check
.item {
background-color: blue;
color: #fff;
padding: 16px;
flex-grow:1;
}
Hope this is what you are looking for
Alternative using display table (an ancient supported grid).
Quote from https://www.w3schools.com/cssref/pr_tab_table-layout.asp
If no widths are present on the first row, the column widths are divided equally across the table, regardless of content inside the cells
.container {
display: table;
table-layout: fixed
} // would divide cells equally along table's 100% width.
.row {
display: table-row
}
.item {
display: table-cell
}

CSS Flexbox getting center item truly centered [duplicate]

I'm trying to align a top menu which consists of 3 blocks of content.
What I'm trying to achieve is this:
block 1: left aligned
block 2: centered horizontally
block 3: right aligned
If all 3 blocks were the same size, I could use flexbox (as in the snippet), but they're not, so it doesn't produce the output I require.
Instead, flexbox puts equal space between the 3 blocks - resulting in the middle block being aligned off-center.
I was wondering if this could be achieved with flexbox, or if not, another solution. This needs to work robustly in production so a 'Grid' solution is not applicable as there is insufficient support.
.container {
margin: 20px 0;
}
.row {
background-color: lime;
display: flex;
justify-content: space-between;
}
.item {
background-color: blue;
color: #fff;
padding: 16px;
}
<div class="container">
<div class="row">
<div class="item">left, slightly longer</div>
<div class="item">center, this item is much longer</div>
<div class="item">right</div>
</div>
</div>
You can consider flex-grow:1;flex-basis:0% for the left and right elements then use text-align to align content inside. I have added an extra wrapper to keep the background only around the text.
The trick is to calculate the free space by removing only the middle content and split it equally to the left and right element.
.container {
margin: 20px 0;
padding-top:10px;
background:linear-gradient(#000,#000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:last-child {
text-align: right;
}
.item span{
background-color: blue;
display:inline-block;
padding: 16px;
border: 2px solid red;
box-sizing:border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
You can also do the same by keeping the element close. Simply adjust text-align:
.container {
margin: 20px 0;
padding-top: 10px;
background: linear-gradient(#000, #000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:first-child {
text-align: right;
}
.item span {
background-color: blue;
display: inline-block;
padding: 16px;
border: 2px solid red;
box-sizing: border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
I asked what seems to be a very similar question and stack overflow directed me here. The response from #Paolamoralesval inspired me to realise the required effect can be achieved in CSS grid. Now that grid support is pretty much universal I hope that this meets everyone's needs. This solution is I believe fully responsive to window size as well as height and width of the header items as you should see if you resize the window where you view the snippet.
.header {
grid-row: 1;
grid-column: 1;
display: grid;
grid-template-rows: min-content;
grid-template-columns: 1fr 1fr 1fr;
}
.header-left {
justify-self: start;
align-self: center;
text-align: left;
background-color: red;
}
.header-center {
justify-self: center;
align-self: center;
text-align: center;
background-color: green;
}
.header-right {
justify-self: end;
align-self: center;
text-align: right;
background-color: blue;
}
.shrink-kitty {
width: 200px;
}
<html>
<body>
<div class="page">
<div class="header">
<div class="header-left">
<img class="shrink-kitty" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Kittyply_edit1.jpg/1280px-Kittyply_edit1.jpg"/><br/>
By David Corby<br/>
Edited by: Arad<br/>Image:Kittyplya03042006.JPG<a><br/><a href="https://creativecommons.org/licenses/by/2.5" title="Creative Commons Attribution 2.5">CC BY 2.5, Link
</div>
<div class="header-center">In the middle</div>
<div class="header-right">
Much much much much more on the right hand side</br>
Indeed two lines
</div>
</div>
<div class="body">Body of the page</div>
<div class="footer">At the bottom</div>
</div>
</body>
</html>
can you give flex-grow:1 for the item class and check
.item {
background-color: blue;
color: #fff;
padding: 16px;
flex-grow:1;
}
Hope this is what you are looking for
Alternative using display table (an ancient supported grid).
Quote from https://www.w3schools.com/cssref/pr_tab_table-layout.asp
If no widths are present on the first row, the column widths are divided equally across the table, regardless of content inside the cells
.container {
display: table;
table-layout: fixed
} // would divide cells equally along table's 100% width.
.row {
display: table-row
}
.item {
display: table-cell
}

Parent DIV to inherit width (%) from child div

I am currently trying to figure out a way to be able to have a layout that has a bottom-up, content-oriented resizing behavior.
I have the following situation: https://codepen.io/Flash1232/pen/JJYPVQ
What is wrong here is obviously that the wrapper divs do not wrap around the table divs. Now is there any solution for this involving just plain CSS and HTML or do I have to write something in JS like "set wrapper width to the width of its inner div"?
Thanks in advance for any clues!
Man i solved my problem with display:flex on parent element :)
You may want to consider using a flexbox. Please see below. If there is anything that needs to be different, just let me know.
.outer-div {
position: absolute;
background: black;
width: 800px;
left: 0;
top: 0;
bottom: 0;
overflow: auto;
padding: 10px;
}
.area {
overflow: auto;
display: flex;
border: 5px solid red;
background: white;
margin: 10px 40px 10px 10px;
}
.column {
background: green;
border: 5px solid blue;
}
.wrapper {
display: flex;
border: 5px solid yellow;
justify-content: center;
align-items: center;
}
.table {
white-space: nowrap;
}
.violet {
background: violet;
width: 120%;
height: 80px;
}
.red {
background: red;
width: 150%;
height: 80px;
margin-bottom: 20px;
}
.icons {
Background: yellow;
float: right;
height: auto;
width: auto;
}
<div class="outer-div">
<div class="area">
<div class="column">
<div class="wrapper">
<div class="table red">
<span>***Table Content***</span>
</div>
</div>
<div class="wrapper">
<div class="table violet">
<span>***Table Content***</span>
</div>
</div>
</div>
<div class="column">
<div class="wrapper">
<div class="table violet">
<span>***Table Content***</span>
</div>
</div>
</div>
</div>
<div class="icons">
<p>Icon</p>
<p>Icon</p>
<p>Icon</p>
<p>Icon</p>
<p>Icon</p>
<p>Icon</p>
</div>
</div>
You should read the definition of the width attribute.
https://developer.mozilla.org/en/docs/Web/CSS/width
Percentages: refer to the width of the containing block
If you set width to 150%, you explicitly say, that the child should be bigger than the parent. You can not expect, that the parent has the same width like the child, if you force the child to be wider.

Automatic layout of block elements

I have layout similar to following one:
#first {
height: 100px;
float: left;
}
#second {
height: 200px;
float: left;
}
#third {
height: 100px;
float: left;
}
.column {
background: red;
width: 200px;
margin: 5px
}
<div id="parrent">
<div id="first" class="column">
FIRST
</div>
<div id="second" class="column">
SECOND
</div>
<div id="third" class="column">
THIRD
</div>
</div>
When we have enough space, it looks like that:
This is OK.
When we don't have enough space, it looks like that:
And this is not OK. I don't want this empty space between block 1 and 3.
I want to achieve something like this:
How can i do that?
This is not possible with your code alone - you need to specifiy at least one mediaquery for this:
#media (max-width: 480px) {
#second {
float: right;
}
}
You need to specify the max-width of the media-query according to your needs.
Using only CSS it is not possible to align the divs to take empty space.
If you do not want to leave any empty space then you should go for masonry layout that uses jQuery.
You can read more about it at:
http://masonry.desandro.com/layout.html
I think that's what you are looking for.
But, If you want to align your items in vertical columns then you can use Flexbox:
(This might not be the answer you are looking for but I still wanted to share that there is an option to align columns vertically using flexbox)
DEMO:
http://plnkr.co/edit/zjuveUTson3C6u45nVSH?p=preview
HTML:
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
</ul>
CSS:
ul {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 306px;
width: 200px;
}
li {
width: 100px;
height: 100px;
background:red;
color: white;
text-align: center;
font-size: 50px;
line-height: 100px;
font-weight: bold;
border: 1px solid white;
list-style: none;
}
DEMO:
http://plnkr.co/edit/zjuveUTson3C6u45nVSH?p=preview
Changes in your second style may it help you
#first {
height: 100px;
float: left;
}
#second {
float: right;
height: 200px;
margin-right: 190px;
}
#third {
height: 100px;
float: left;
}
.column {
background: red;
width: 200px;
margin: 5px
}
<div id="parrent">
<div id="first" class="column">
FIRST
</div>
<div id="second" class="column">
SECOND
</div>
<div id="third" class="column">
THIRD
</div>
</div>

Vertical align middle text in div not working

I have code like this:
<div class="more-options clearfix">
<div class="boxes">
<img alt="#" src="images/icons/onl-marketing.png">
<p>Online Marketing News</p>
</div>
<!-- end .boxes -->
<div class="boxes">
<img alt="#" src="images/icons/str-success.png">
<p>Stories Success</p>
</div>
<!-- end .boxes -->
I want to vertical align p tags middle in div, images float left and div.box:last-child has margin-left: 1%; I try this css but it doesn't work:
div.more-options {
margin: 15px 0;
div:first-child {
.fleft;
}
div:last-child {
margin-left: 1%;
}
div.boxes {
padding: 20px;
width: 49.5%;
background: #ecf0f1;
min-height: 25px;
display: table-cell;
vertical-align: middle;
img {
.fleft;
margin-right: 25px;
.img-responsive;
max-width: 25%!important;
}
p {
.fontfc(26px, #666666);
}
}
/* end div.boxes */
}
/* end div.more-options */
How can I vertical align text and keep margin 1% div.boxes:last-child?
here you have some fixes:
p and img with display:inline
it's working the vertical-align:middle;
making the parent display: table
EDIT: you are using padding and width: you will need an extra div for this, and with tables you need an extra cell for "separation", check this out:
updated link with images vertical aligned too:
the fiddle
html:
<div class="more-options clearfix">
<div class="boxes">
<div class="in">
<img alt="#" src="http://icons.iconarchive.com/icons/artbees/paradise-fruits/256/Banana-icon.png">
<p>Online Marketing News</p>
</div>
</div>
<!-- end .boxes -->
<div class="separation"></div>
<div class="boxes">
<div class="in">
<img alt="#" src="http://icons.iconarchive.com/icons/artbees/paradise-fruits/256/Banana-icon.png">
<p>Stories Success</p>
</div>
</div>
<!-- end .boxes -->
css:
div.more-options {
margin: 15px 0;
div:first-child {
}
div.separation {
width: 1%;
display: table-cell;
}
div.in{
padding:20px;
}
div.boxes {
width: 49.5%;
background: #ecf0f1;
min-height: 25px;
display: table-cell;
vertical-align: middle;
img {
display: inline-block;
margin-right: 25px;
.img-responsive;
max-width: 25%!important;
vertical-align: middle;
}
p {
.fontfc(26px, #666666);
display: inline-block;
}
}
/* end div.boxes */
}
/* end div.more-options */
the result screenshot:
p elements are paragraphs - so they have a default property of display:block. Either use another element, for example a span.
Alternatively you can change the display property of the p dom element, for example to display:inline.
Update - the property of vertical align 'vertical-align:middle' should be applied to the images.
Also - your nesting of styles seems wrong, see a working example below.
Example (updated):
http://jsfiddle.net/YwV54/2/
Your Structure is ok.
In order to use vertical-align:middle you need to use table structure:
#wrapper div#main-content div.more-options div.boxes{display:table;}
#wrapper div#main-content div.more-options div.boxes p{verticle-align:middle;}
#wrapper div#main-content div.more-options div.boxes img{max-width:25% !important; remove this}
Set padding margin according to content.

Resources