I want to create a grid of blocks using css flex.
The blocks need to be in three columns and they should be a 3rd of the width of the parent container.
My problem is I need a right margin on the blocks.
The blocks need to be a percentage of the container so I cant use space between.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
}
.block__item {
background: grey;
height: 20px;
margin-right: 2px;
//margin-bottom: 2px;
width: 33.33%;
}
.block__item:nth-child(3n){
margin-right: 0;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
A bit late to the party, but I found a working hack:
Have the overflow auto on a container element around it and give the element itself an invisible border of 8px on the side(s) where you expect the scrollbar to appear. When the scrollbar does show, it will be displayed on top of the invisible border instead of on top of the content.
Judging by your question, I believe this is what you are trying to accomplish:
.block {
border: 1px solid lightgrey;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.block__item {
background: grey;
height: 20px;
margin-right: 2px;
margin-bottom: 2px;
width: 33%;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
I added the vendor prefixes so that it displays consistently across all browsers. You can adjust the spacing between boxes by adjusting the percentage (i.e. 31% width). If you plan on using Flexbox often you should check out this site for quick vendor versions: http://the-echoplex.net/flexyboxes/
Maybe you can simply decrease the width of the blocks, and the rest of the witdh assign it to the margin.
Like this:
.block__item {
background: grey;
height: 20px;
margin-right: 3%;
width: 30%;
}
The problem is the padding on the container. But you can use width: calc((100% - 10px) / 3); to calculate the correct 33,33% of the container width excluding the padding.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
}
.block__item {
background: grey;
height: 20px;
margin-right: 2px;
margin-bottom: 2px;
width: calc((100% - 10px) / 3);
}
.block__item:nth-child(3n){
margin-right: 0;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
Very Good Question
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
max-width: 900px;
margin-left: -1px;
margin-right: -1px;
}
.block__item {
background: grey;
background-clip: content-box;
height: 20px;
flex-basis: 33.33%;
box-sizing: border-box;
padding-left: 1px;
padding-right: 1px;
margin-bottom: 2px;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
Actually, it's good practice to split layout and content in html.
.b-row {
display: flex;
flex-wrap: wrap;
margin-left: -1px;
margin-right: -1px;
}
.b-row > .b-col {
flex-basis: 33.33%;
box-sizing: border-box;
padding-left: 1px;
padding-right: 1px;
margin-bottom: 2px;
}
.block__item {
background-color: grey;
height: 20px;
}
<div class="block">
<div class="b-row">
<div class="b-col">
<div class="block__item">asdfasfasdf</div>
</div>
<div class="b-col">
<div class="block__item">asdfasfdasf</div>
</div>
<div class="b-col">
<div class="block__item">asdfasdfas</div>
</div>
<div class="b-col">
<div class="block__item">asdfasdfa</div>
</div>
<div class="b-col">
<div class="block__item">asdfasdfadsf</div>
</div>
</div>
</div>
Anyway, you can choose your preference.
Related
html,
body {
margin: 0;
height: 100%;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
height: 50px;
background-color: #2D4256;
}
.nav-centre {
margin: 0 auto;
width: 40%;
height: 100%;
}
.nav-container {
display: flex;
height: 100%;
align-items: center;
/* vertically centre */
}
.nav-item {
color: white;
width: 40px;
text-align: center;
}
.main-content {
height: calc(100% - 50px);
width: 100%;
position: absolute;
bottom: 0;
overflow-y: overlay;
display: flex;
justify-content: center;
}
.main-wrap {
width: 40%;
border-left: 1px solid black;
border-right: 1px solid black;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
The main-wrap div is not expanding to fill the parent main-content div, how can I get the main-wrap element to expand to the full height of the parent?
https://codepen.io/woooof/pen/VwBLprj
The .main-wrapper is getting by default display:block, which doesn't match with the display:flex parent.
To get the value from the parent, you can use display: inherit. Once done, the elements inside won't respect their width. To fix that, you must wrap the elements, and for making it total height, You can use max-content.
.main-wrapper {
display: inherit;
flex-wrap: wrap;
height: max-content;
}
Result:
html,
body {
margin: 0;
height: 100%;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
height: 50px;
background-color: #2D4256;
}
.nav-centre {
margin: 0 auto;
width: 40%;
height: 100%;
}
.nav-container {
display: flex;
height: 100%;
align-items: center;
/* vertically centre */
}
.nav-item {
color: white;
width: 40px;
text-align: center;
}
.main-content {
height: calc(100% - 50px);
width: 100%;
position: absolute;
bottom: 0;
overflow-y: overlay;
display: flex;
justify-content: center;
}
.main-wrap {
width: 40%;
border-left: 1px solid black;
border-right: 1px solid black;
display: inherit;
flex-wrap: wrap;
height: max-content;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
I am not a huge fan of making the size of one element (navbar) determine the position of the second element main-content (margin-top). where you have height: calc(100% - 50px); I would rather if the style of the first changes. Say for example we increase navbar font size, you would not need to adjust the second manually.
Here in this example I set the font-size on an ancestor block to change the nav buttons size and not have to change the content. font-size: 1.5rem;
Change it even larger; again no change to the content CSS;
I put a lot of comments in and some borders just to show where things line - that can and should all be removed for a production version.
html,
body {
margin: 0;
height: 100%;
/* stack the nav and the content blocks */
display: grid;
grid-template-rows: 1fr auto;
}
.navbar {
/* put the navbar at the top */
position: sticky;
top: 0;
background-color: #2D4256;
/* flex, default vertical/horizontal centers nav-centre in the flex */
display: flex;
}
.nav-centre {
margin: 0 auto;
display: flex;
}
.nav-container {
display: flex;
/* again these are the default here
flex-direction: row;
align-items: center;
justify-content: center;
*/
/* how much space above and below the yellow border nav container */
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.nav-item {
color: white;
/* 2 times font-size for cyan border items */
width: 2em;
text-align: center;
}
.main-content {
display: grid;
justify-content: center;
}
.main-wrap {
border-left: 1px solid black;
border-right: 1px solid black;
}
.box {
width: 200px;
height: 200px;
background: white;
border: 1px solid black;
margin: 10px;
}
/* below here is just for visual clarification and can be removed */
.navbar {
/* just to show you can style and not effect content block *
/* this can be on any of the three containers */
font-size: 1.5rem;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
.nav-centre {
border: 1px solid magenta;
padding: 2px;
}
.nav-container {
border: 1px solid yellow;
}
.nav-item {
border: 1px solid cyan;
/* you can space out the nav buttons */
margin: 0 0.25rem;
}
.main-content {
/* just to show it is below the navbar and separate */
border: solid red 1px;
margin-top: 0.25rem;
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.box {
background-color: #ffffdd;
}
<body>
<div class="navbar">
<div class="nav-centre">
<div class="nav-container">
<div class="nav-item">1</div>
<div class="nav-item">2</div>
<div class="nav-item">3</div>
<div class="nav-item">4</div>
</div>
</div>
</div>
<div class="main-content">
<div class="main-wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
In the following code:
HTML
<div class="cards-wrapper">
<div class="cards_item">
<div class="card">
<div class="card__header">
<div class="=card__title">
<div>title</div>
</div>
</div>
<div class="card__content">
<p class="card__description">Some text</p>
<p class="card__frequency">more text</p>
</div>
<div class="card__footer">
<div class="card__tick"><input type="hidden" value="0"><label class="checkbox-container"><input type="checkbox" class="list-checkbox" value="false"><span class="checkmark"></span></label></div>
<div class="card__see">Even more</div>
</div>
</div>
</div>
</div>
SCSS
.cards-wrapper {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
outline: 2px solid blue
}
.cards_item {
display: flex;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
padding: 0.5rem;
}
.card {
position: relative;
flex: 0 1 100%;
justify-self: stretch;
box-sizing: border-box;
padding: 0.625rem;
overflow: hidden;
&__header {
display: flex;
flex-direction: row;
align-items: center;
}
&__title {
margin: 0;
}
&__frequency {
margin-bottom: 80px;
}
&__footer {
position: absolute;
bottom: 0.8rem;
display: inline-flex;
align-items: center;
justify-content: space-between;
width: 100%;
outline: 2px solid red;
}
}
Why does .card__footer div with a width of 100% wider than its container?
It fits in the container if you change its width to 90%.
But something seems to be not right here.
Can someone help me please with this?
I see that the container div has padding to it.
can you try this width value on your footer?
width: calc(100% - 1.25rem);
since you are using scss
calc(100% - 2*0.625rem)
I want to achieve the following scenario with flexbox
the green element is a text element and the width is flexible. The blue elements should have 100% of the remaining width beside the green element.
My current solution looks like this:
<div class="container">
<span class="title">title</span>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
and the css:
.container {
display: flex;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
.title {
padding: 20px;
background-color: #48CFAE;
}
.fullwidth {
background-color: #87BDFF;
flex: 0 0 100%;
height: 60px;
margin: 10px 0;
}
}
But it looks currently like this
here is a codepen example
Without changing the HTML this can be managed with CSS-Grid as an alternative to flexbox.
.container {
display: grid;
grid-template-columns: max-content 1fr;
grid-gap: 1em;
background-color: #EAEBEF;
margin-bottom: 1em;
}
.title {
padding: 10px;
grid-row: 2;
background-color: #48CFAE;
}
.fullwidth {
grid-column: 2;
background-color: #87BDFF;
height: 40px;
}
<div class="container">
<div class="title">title</div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
<div class="container">
<div class="title">Longer title</div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
Try this HTML and CSS markup. Basically You need to keep the left side in one div and the right side elements in another div.
.container {
display: flex;
align-items: center;
flex-wrap: nowrap;
background-color: #eaebef;
}
.container .title {
padding: 20px;
background-color: #48cfae;
}
.container .div1 {
width: 20%;
}
.container .div2 {
width: 80%;
}
.container .fullwidth {
background-color: #87bdff;
height: 60px;
margin: 10px 0;
}
<div class="container">
<div class="div1">
<span class="title">title</span>
</div>
<div class="div2">
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
</div>
See code below:
You have to warp fullwidth in div and set width to this div
also set width and margin to title
.container {
display: flex;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
}
.title {
width: 20%;
padding: 20px;
background-color: #48CFAE;
margin-left: 15px;
}
.fullwidth {
background-color: #87BDFF;
flex: 0 0 100%;
height: 60px;
margin: 10px 0;
}
.a{
margin: 50px;
width: 50%;
}
<div class="container">
<span class="title">title</span>
<div class="a">
<div class="fullwidth"></div>
<div class="fullwidth"></div>
<div class="fullwidth"></div>
</div>
</div>
If you want to achive this without change your html but only your less, try this:
.container {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
background-color: #EAEBEF;
justify-content: flex-end;
.title {
padding: 20px;
background-color: #48CFAE;
margin-right: 20px;
flex-grow: 1
}
.fullwidth {
background-color: #87BDFF;
height: 60px;
margin: 10px 0;
width: 80%;
}
}
your codepen edited
I would like to have the parent (orange border) only grow to the size of the first child (grey background) and have the second child overflow vertically.
This is what I have:
This is what I want:
Codepen: https://codepen.io/gbucher/pen/wPGBpN
HTML:
<div class='parent'>
<div class='child1'>
</div>
<div class='child2'>
<div class='elem'>
A
</div>
<div class='elem'>
B
</div>
<div class='elem'>
C
</div>
<div class='elem'>
D
</div>
<div class='elem'>
E
</div>
</div>
</div>
CSS:
.parent {
border: 2px solid orange;
display: flex;
/* How to make it work without a fixed
height ?
height:60px;
*/
}
.child1 {
height: 60px;
width: 300px;
background: #888;
}
.child2 {
display: flex;
flex-direction: column;
overflow-y: auto;
}
.elem {
border: 1px solid black;
margin-top: -1px;
padding: 3px;
width: 10rem;
}
When computing the size of a parent, absolute positioned children are ignored.
The solution is thus to use a scroll wrapper around the second child. The wrapper should have position: relative and the scrolling child should have position: absolute.
.parent {
border: 2px solid orange;
display: flex;
}
.child1 {
height: 70px;
flex-grow: 1;
background: #888;
}
.child2 {
display: flex;
flex-direction: column;
position: absolute;
background: orange;
}
.scroll {
position: relative;
overflow-y: scroll;
overflow-x: hidden;
width: 323px;
background: green;
}
.elem {
border: 1px solid black;
margin-top: -1px;
padding: 3px;
width: 300px;
}
<div class='parent'>
<div class='child1'>
one
</div>
<div class='scroll'>
<div class='child2'>
<div class='elem'>
A
</div>
<div class='elem'>
B
</div>
<div class='elem'>
C
</div>
<div class='elem'>
D
</div>
<div class='elem'>
E
</div>
</div>
</div>
</div>
I have such code:
https://plnkr.co/edit/ZAEzfAOCO0ZcSq2OR4Lp?p=preview
but this isn't working in ie, until I add height:0 (it's a very bad idea on parent element)
<body>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</body>
body, html {
min-height: 100%;
height: 100%;
}
.container {
width: 100%;
min-height: calc(100% - 80px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.container-item {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
content: "someText";
border-bottom: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
everything works fine in chrome and ff
(my parents should expand to fit parent)
Important!
I need a flexible solution, my code can have a lot of nested div's (not a constant value) between body and content divs.
for example:
<body>
<div>
<div>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</div>
</body>
or
<body>
<div>
<h3>text</h3>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</body>
If you have an unknown or nested markup before the container, you could add an extra wrapper within it (here inner), to overcome IE's min-height bug.
Fiddle sample 1 -- Fiddle sample 2
Stack snippet sample 1
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<h3>text</h3>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
Stack snippet sample 2
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<div>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
</div>