I have a two column flexbox layout. However, sometimes there is only one column, in which case the column should be aligned to the right. Currently the column is aligned to the left.
https://codepen.io/sleepydada/pen/rzVRxL
HTML:
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
&:first-of-type {
background: #ccc;
}
.answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
}
You can add this CSS:
.answer:only-of-type {
margin-left: auto;
}
From MDN
The :only-of-type CSS pseudo-class represents an element that has no
siblings of the same type.
codepen
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.answers:first-of-type {
background: #ccc;
}
.answers .answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
.answers .answer:only-of-type {
margin-left: auto;
}
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
</div>
You can add an invisible div with height set to 0
* {
box-sizing: border-box;
}
.invisible {
height: 0;
border: none !important;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.answers:first-of-type {
background: #ccc;
}
.answers .answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex: 0 0 33.3333%;
}
<div class="answers">
<div class="answer">first answer</div>
<div class="answer invisible"><!--invisible div--></div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer invisible"><!--invisible div--></div>
<div class="answer">first answer</div>
</div>
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>
I am trying to center text inside a parent element of limited width. However the text is set in a large font, which might cause a line-break. However the element line-break does not decrease the width of the element. Is there a way to center a text inside a parent wrapper if the text does not fit?
You can find a failing example in the stack-overflow code sample. The top box has a line-break and should still be centered.
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 200px;
border: 1px solid green;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box"><h3>Lorem Ipsum</h3></div>
<div class="box"><h3>Lorem Ipsum</h3></div>
</div>
Just add the text-align: center;
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
/* text-align: center; */
width: 300px;
height: 200px;
border: 1px solid green;
}
.box > * {
flex: 0 0 50%;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box"><h3>Lorem Ipsum</h3></div>
<div class="box"><h3>Lorem Ipsum</h3></div>
</div>
You can use width:min-content; with the first child (https://caniuse.com/#feat=intrinsic-width)
.wrapper {
width: 900px;
margin: 0 auto;
background: lightgrey;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 200px;
border: 1px solid green;
}
.box:nth-child(1) h3 {
width:-webkit-min-content;
width:-moz-min-content;
width:min-content;
border:1px solid;
}
.box:nth-child(1) {
background: green;
font-size: 45px;
}
.box:nth-child(2) {
background: orange;
}
<div class="wrapper">
<div class="box">
<h3>Loreme Ipsum</h3>
</div>
<div class="box">
<h3>Lorem Ipsum</h3>
</div>
</div>
This question already has answers here:
Chrome / Safari not filling 100% height of flex parent
(5 answers)
Closed 4 years ago.
I have code with nested flexboxes: https://jsfiddle.net/tomrhodes/8pf1q706/ and I expect that "content 2" are always fills the remaining space. It works on Firefox, but it does not work in Google Chrome, why it is not working?
It is very important not to use one div element both as the item and as the parent of the flexbox, so - I have clearly separated these role.
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.row2 {
background: #f8f9fa;
margin-top: 20px;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
}
.container {
display: flex;
display: -webkit-flex;
flex-flow: column;
-webkit-flex-flow: column;
height: 100%;
border: solid blue;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
border: solid blue;
}
.outsidebox {
display: flex;
flex-flow: column;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex: 1 1 auto;
border: solid green;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
.wrapper {
flex: 1 1 auto;
border: solid yellow;
}
<div class="outsidebox">
<div class="box">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>
</div>
I think this is what you are after - I have made the content style flex with a column direction and flex grow so it fills the parent container:
* {box-sizing:border-box;}
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.row2 {
background: #f8f9fa;
margin-top: 20px;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
}
.container {
display: flex;
display: -webkit-flex;
flex-flow: column;
-webkit-flex-flow: column;
height: 100%;
border: solid blue;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
border: solid blue;
}
.outsidebox {
flex-grow:1;
display: flex;
flex-flow: column;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex-grow:1;
display:flex;
flex-direction:column; /* make this flex and column */
border: solid green;
width:100%;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
.wrapper {
flex: 1 1 auto;
border: solid yellow;
}
<div class="outsidebox">
<div class="box">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>
</div>
Or simplified:
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
border: solid magenta;
}
.outsidebox {
display: flex;
flex-flow: column;
flex-grow: 1;
height: 100%;
border: solid purple;
}
.headerstyle {
flex: 0 1 auto;
border: solid green;
}
.contentstyle {
flex-grow: 1;
display: flex;
flex-direction: column;
border: solid green;
width: 100%;
}
.footerstyle {
flex: 0 1 40px;
border: solid green;
}
<div class="outsidebox">
<div class="headerstyle">header</div>
<div class="contentstyle">
<div class="outsidebox">
<div class="headerstyle">header 2</div>
<div class="contentstyle">content 2</div>
<div class="footerstyle">footer 2</div>
</div>
</div>
<div class="footerstyle">footer</div>
</div>
I have a simple layout with varying size elements that I am trying to put together for a dashboard.
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
display: flex;
}
div.first {
border: 1px dotted lightpink;
}
div.second {
border: 1px dotted orange;
}
div.third {
border: 1px dotted green;
}
div.fourth {
border: 1px dotted fuchsia;
}
<div style="display: flex; height: 500px">
<div class="first" style="flex: 0 60%;flex-wrap: wrap;align-items;stretch;align-content:stretch">
<div class="first" style="flex: 1 100%; align-self: flex-start">
Title text
</div>
<div class="second" style="flex: 2 auto">
Content A
</div>
<div class="third" style="flex: 1 auto">
Content B
</div>
<div class="fourth" style="flex: 1 auto">
<div style="height: 66px; align-self:flex-end">
<div style="align-self: flex-end">
Content C
</div>
</div>
</div>
</div>
<div class="second" style="flex: 1 auto; align-items: flex-end">
Content D
</div>
</div>
Codepen link:
http://codepen.io/korgmatose/pen/qqKzry?editors=1100
I want to fill the second row (Content A,B,C) so that it starts just beneath Title Text.
But making align-items flex-start will not allow the second row to fill the remaining space, and setting a height to 100% on one of the items in that row only sets the height to the parent container, thus rendering the div's outside the bottom border.
Like #kukkuz said I would also recommend doing it this way. Just put the content A, B, C in a separate container, in this case #content and add display: flex, flex-direction: column and flex: 1 to it and please do not use inline styling for styling your HTML since it makes your code muss less readable. Most recommended way is to put your CSS code into a separate file and link it to your HTML.
The following code is an example of how you could do the markup of your desired layout without any inline styles.
HTML
<div id="wrapper">
<div class="left">
<div class="title">Title text</div>
<div id="content">
<div class="second">Content A</div>
<div class="third">Content B</div>
<div class="fourth">Content C</div>
</div>
</div>
<div class="right">Content D</div>
</div>
CSS
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
}
#wrapper {
display: flex;
height: 500px;
}
.left {
flex: 3;
display: flex;
flex-direction: column;
}
#content{
flex: 1;
display: flex;
padding: 0;
}
.second,
.third,
.fourth {
flex: 1;
}
.third {
border: 1px dotted green;
}
.fourth {
display: flex;
align-items: flex-end;
border: 1px dotted fuchsia;
}
.right {
flex: 2;
}
.left,
.title {
border: 1px dotted lightpink;
}
.right,
.second {
border: 1px dotted orange;
}
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
}
#wrapper {
display: flex;
height: 500px;
}
.left {
flex: 3;
display: flex;
flex-direction: column;
}
#content {
flex: 1;
display: flex;
padding: 0;
}
.second,
.third,
.fourth {
flex: 1;
}
.third {
border: 1px dotted green;
}
.fourth {
display: flex;
align-items: flex-end;
border: 1px dotted fuchsia;
}
.right {
flex: 2;
}
.left,
.title {
border: 1px dotted lightpink;
}
.right,
.second {
border: 1px dotted orange;
}
<div id="wrapper">
<div class="left">
<div class="title">Title text</div>
<div id="content">
<div class="second">Content A</div>
<div class="third">Content B</div>
<div class="fourth">Content C</div>
</div>
</div>
<div class="right">Content D</div>
</div>
div {
padding: 5px 5px 5px 5px;
margin: 1px 1px 1px 1px;
display: flex;
}
div.first {
border: 1px dotted lightpink;
}
div.second {
border: 1px dotted orange;
}
div.third {
border: 1px dotted green;
}
div.fourth {
border: 1px dotted fuchsia;
}
<div style="display: flex;">
<div class="first" style="flex: 0 60%;flex-wrap: wrap;align-items;stretch;align-content:stretch">
<div class="first" style="flex: 1 100%; align-self: flex-start">
Title text
</div>
<div class="second" style="flex: 2 auto">
Content A
</div>
<div class="third" style="flex: 1 auto">
Content B
</div>
<div class="fourth" style="flex: 1 auto">
<div style="height: 66px; align-self:flex-end">
<div style="align-self: flex-end">
Content C
</div>
</div>
</div>
</div>
<div class="second" style="flex: 1 auto; align-items: flex-end">
Content D
</div>
</div>
Something like this?
Is there a way to do the elements in this flexbox grid / tabs without putting them in a wrapper?
http://jsfiddle.net/mu98yotk/
.test {
border: 1px solid #ccc;
}
.test, .test .wrapper {
display: flex;
}
.test .wrapper {
flex: 1;
}
.test .wrapper * {
margin: 0 auto;
padding: 0 15px;
}
<div class="test">
<div class="wrapper">
<p>Lorem</p>
</div>
<div class="wrapper">
Ipsum
</div>
</div>
.test {
border: 1px solid #ccc;
display: flex;
}
.test > * {
margin: 0 auto;
padding: 0 15px;
}
.test > p {
border-bottom: 2px solid blue;
}
<div class="test">
<p>Lorem</p>
Ipsum
</div>