Flexbox overflowing out of parent div - css

I have a nested flexbox situation. The first one is to establish two responsive columns:
.ColWrap,
{
width: 100%;
box-sizing: border-box;
background-color: #fff;
padding: 50px 10px 50px 25px;
display: flex;
flex-wrap: wrap;
}
.ColWrap .col,
{
flex: 1;
padding: 20px 20px 20px 0;
margin: auto;
}
#media screen and (max-width: 600px) {
.ColWrap {
flex-direction: column;
}
.ColWrap .col,
{
width: 100%;
padding-left: 0;
}
}
The second is a series of what I'm called "nuggets" inside the right column. These should wrap as necessary:
.nuggetHolder {
width: 100%;
margin: 20px;
display: flex;
flex-wrap: wrap;
}
.nugget {
flex: 0 1 40%;
margin: 10px;
padding: 10px;
border: 2px solid rgba(0,0,0,.2);
}
Putting it together looks like this:
<div class="ColWrap">
<div class="col">
<h2>Left-hand text</h2>
</div>
<div class="col">
<div class="nuggetHolder">
<div class="nugget">Nugget NuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
</div>
</div>
The problem I am having is that the nugget with all the text is overflowing outside the container.
Do you think I should set up the 2-column container as a grid and then each "nugget" as a flexbox?

Use word-break: break-word;
word-break: break-word; keep all the text in the size the div already have.
for looking good I add:
flex-grow: 1; in .nugget - it also like change flex: 0 1 40%; to flex: 1 1 40%;
and in .nuggetHolder I replace the margin in padding and add box-sizing: border-box; that calculate the box size with border and padding, and it not break with scroll-x.
.ColWrap,
{
width: 100%;
box-sizing: border-box;
background-color: #fff;
padding: 50px 10px 50px 25px;
display: flex;
flex-wrap: wrap;
}
.ColWrap .col,
{
flex: 1;
padding: 20px 20px 20px 0;
margin: auto;
}
#media screen and (max-width: 600px) {
.ColWrap {
flex-direction: column;
}
.ColWrap .col,
{
width: 100%;
padding-left: 0;
}
}
.nuggetHolder {
width: 100%;
// margin: 20px;
padding: 20px;
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
}
.nugget {
flex: 0 1 40%;
margin: 10px;
padding: 10px;
border: 2px solid rgba(0,0,0,.2);
word-break: break-word;
flex-grow: 1;
}
<div class="ColWrap">
<div class="col">
<h2>Left-hand text</h2>
</div>
<div class="col">
<div class="nuggetHolder">
<div class="nugget">Nugget NuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNuggetNugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
<div class="nugget">Nugget</div>
</div>
</div>

Add the following to .nugget:
max-width: 40%;
overflow-wrap: break-word;
To center it add justify-content: center to .nuggetHolder.
Added max-width so that any overflowed content, i.e. over 40% will be consistent.

Related

How to remove the empty space between elements?

I have made a calculator using one parent div and plenty of child divs, the children are in html. After that I styled it using flex-box and it is almost done; nevertheless there is an empty space between first div (.result) and the rest of the divs (.btn).
I want to remove that empty space which is shown in picture below:
I tried to use flex-box method to arrange these div elements like blocks.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Apply align-content: flex-start to the flex container.
The default setting is align-content: stretch, which will spread the items across the container. With flex-start, they'll be packed together at the top.
Your code:
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
border: 2px dashed red;
background-color: yellow;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Modified code:
.kalkulator {
display: flex;
flex-wrap: wrap;
height: 50vh;
width: 30vw;
margin: 0 auto 0 auto;
border: 2px dashed red;
background-color: yellow;
align-content: flex-start;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
It seems too much* for one flexbox. Create the layout with two nested ones: one for the vertical partition of the calculator to the result and the buttons, and another one for the fluid positioning of the buttons within the buttons div:
<div class="kalkulator">
<div class="result">wynik</div>
<div class="buttons">[...]</div>
</div>
.kalkulator {
display: flex;
flex-direction: column;
}
.result {
flex-basis: 10vh;
}
.buttons {
flex-grow: 1; /* Fill the rest */
display: flex;
flex-wrap: wrap;
}
.btn {
flex-grow: 1;
flex-basis: 33%;
justify-content: center;
align-items: center;
display: flex;
}
For placing the buttons under the result box you need a flexbox with a vertical main axis (flex-direction: column). For placing the buttons in a row, a flexbox with a horizontal main axis (the default flex-direction: row).
See the following code, here I removed height: 50vh; property from .kalkulator class:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
h1 {
margin: 0 auto 0 auto;
background-color: gray;
text-align: center;
margin-bottom: 5vh;
}
.kalkulator {
display: flex;
flex-wrap: wrap;
/* height: 50vh; */
width: 30vw;
margin: 0 auto 0 auto;
}
.kalkulator .result {
flex-basis: 100%;
height: 10vh;
background-color: #333;
}
.kalkulator div {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 33%;
background-color: #666;
border: 1px solid black;
}
.btn:nth-last-child(2),
.btn:nth-last-child(1) {
flex-basis: 50%;
}
<h1>kalkulator</h1>
<div class="kalkulator">
<div class="result">wynik</div>
<div class="btn">1</div>
<div class="btn">2</div>
<div class="btn">3</div>
<div class="btn">4</div>
<div class="btn">5</div>
<div class="btn">6</div>
<div class="btn">7</div>
<div class="btn">8</div>
<div class="btn">9</div>
<div class="btn">+</div>
<div class="btn">0</div>
<div class="btn">-</div>
<div class="btn">/</div>
<div class="btn">.</div>
<div class="btn">*</div>
<div class="btn">C</div>
<div class="btn">=</div>
</div>
Viewport Height (vh): This unit is based on the height of the viewport. A value of 1vh is equal to 1% of the viewport height.
Height of container is 50vh and height of result is 10vh. This leaves 40vh for button panel, or 6.67vh per row. If you want to preserve container height, you can just add height: 6.67vh; to .kalkulator div. This will set button height to fixed value, so there won't be any empty space.

Make child div fill parent div with scroll

I am having problems with flexbox layout parenting a child control.
html, body, .frame{
margin: 0;
height: 100%;
}
* {
box-sizing: border-box;
}
.frame{
display: flex;
flex-flow: column;
}
.header{
background-color: yellow;
height: 40px;
}
.body-outer{
background-color: green;
flex: 1;
display: flex;
flex-flow: column;
}
.body-inner{
border: 1px solid red;
flex: 1;
}
.big-text{
height: 2000px;
border: 1px solid lightblue;
overflow: auto;
margin: 5px;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner>">
<div class="big-text">big text</div>
</div>
</div>
</div>
The 'body-inner' div is meant to fill the remaining space with flex: 1 and the 'big-text' is supposed to fill the whole space of 'body-inner' without expanding it but showing scroll bars.
You have the overflow applied to the content. It should be applied to the container that will be overflowed.
Also, you need a fixed height, so that the overflow property has something to overflow.
Try this:
.frame {
display: flex;
flex-flow: column;
height: 100vh;
}
.header {
background-color: yellow;
height: 40px;
}
.body-outer {
height: calc(100vh - 40px); /* new */
background-color: green;
/* flex: 1; */
display: flex;
flex-flow: column;
}
.body-inner {
border: 1px solid red;
flex: 1;
overflow: auto; /* moved here */
}
.big-text {
height: 2000px;
border: 1px solid lightblue;
/* overflow: auto; */
margin: 5px;
}
body {
margin: 0;
}
* {
box-sizing: border-box;
}
<div class="frame">
<div class="header">header</div>
<div class="body-outer">
<div>subheader</div>
<div class="body-inner">
<div class="big-text">big text</div>
</div>
</div>
</div>

Center flex divs horizontally [duplicate]

This question already has answers here:
Special div shrinking
(2 answers)
Closed 5 years ago.
I have three divs that have different flex-basis. In order to make page responsive I want to put them centered one under one if width of the screen is less then 1000px.
Here's my example on Codepen:
.wrapper {
display: flex;
margin: 0 auto;
max-width: 1310px;
}
.left {
flex-basis: 555px;
}
.left__nav {
display: inline-block;
padding: 5px;
text-decoration: none;
}
.wrapper .right {
flex-basis: 462px;
display: flex;
justify-content: flex-end; /* align right (at end) */
}
.wrapper .button {
flex-basis: 193px;
text-align: center;
}
/* style for this demo */
.wrapper > div {
box-sizing: border-box;
border: 1px solid black;
border-collapse: collapse;
}
.mark-center {
text-align: center;
font-size: 30px;
color: red;
}
.container-small {
text-align: center;
background-color: lightgray;
max-width: 1100px;
margin: auto;
}
<div class="wrapper">
<div class="left">
<div class="links">
<a class="left__nav" href="#">Left Nav </a>
</div>
</div>
<div class="right">
Right
</div>
<div class="button">
Button
</div>
</div>
<div class="mark-center">
↑
</div>
<div class="container-small">
Center
</div>
Help me to put them that way if width < 1000px next way:
Seems to me you don't want flex-basis, you want width since these elements don't grow or shrink.
If so, you can use a media query and change the flex-direction to column after switching the flex-basis properties to width.
#media (max-width:1100px) {
.wrapper {
flex-direction:column;
align-items: center;
}
}
.wrapper {
display: flex;
margin: 0 auto;
max-width: 1310px;
}
.left {
width: 555px;
}
.left__nav {
display: inline-block;
padding: 5px;
text-decoration: none;
}
.wrapper .right {
width: 462px;
/* display: flex; */
/* justify-content: flex-end; */
/* align right (at end) */
}
.wrapper .button {
width: 193px;
text-align: center;
}
/* style for this demo */
.wrapper>div {
box-sizing: border-box;
border: 1px solid black;
border-collapse: collapse;
}
.mark-center {
text-align: center;
font-size: 30px;
color: red;
}
.container-small {
text-align: center;
background-color: lightgray;
max-width: 1100px;
margin: auto;
}
#media (max-width:1100px) {
.wrapper {
flex-direction: column;
align-items: center;
text-align: center;
}
}
<div class="wrapper">
<div class="left">
<div class="links">
<a class="left__nav" href="#">Left Nav </a>
</div>
</div>
<div class="right">
Right
</div>
<div class="button">
Button
</div>
</div>
<div class="mark-center">
↑
</div>
<div class="container-small">
Center
</div>

How to expand background from flexbox grid text & images with equal height

I have done a flexbox grid, it combines text cells with image cells. All the cells have the same height in each resolution, also text cells. Text cells have the text centered vertically, and this is a must. Now I need to assign each text cell a different background-color, but here I have the problem.
With align-items: center the text is centered vertically, but the background color is only applied to the text. Without align-items: center the background expands to all the cell, but the content is not centered vertically.
Here is the codepen
Any suggestions in how to achieve the two features at same time?
vertically centered text
different background-color for each text cell
Thanks!
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
margin: 0;
background: #333;
padding: 30px;
font-family: Helvetica;
}
a {
color: white;
text-decoration: none;
}
h2 {
font-size: 1.2em;
}
.wrap-items {
background-color: #ccc;
padding: 0;
margin: 0 auto;
display: -ms-flexbox;
-ms-flex-wrap: wrap;
-ms-flex-direction: row;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
display: -webkit-box;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
}
.wrap-items .item {
-webkit-box-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 1 0 33.333%;
width: 33.33333%;
margin: 0;
padding: 0;
color: white;
font-size: 0;
border: none;
background-color: steelblue;
}
.wrap-items .item.span-2 {
-webkit-box-flex: 2 0 auto;
-ms-flex: 2 0 auto;
flex: 2 0 auto;
width: 66.6666%;
height: auto;
}
.wrap-items .item img {
width: 100%;
height: auto;
}
.wrap-items .item > .text {
padding: 10px;
font-size: 20px;
height: 100%;
}
.item.un .text{
background-color: orange;
}
.item.dos {
background-color: brown;
}
.item.tres {
background-color: violet;
}
#media screen and (max-width: 760px) {
.wrap-items .item {
margin: 0;
flex: 50%
}
}
#media screen and (max-width: 400px) {
.wrap-items .item {
margin: 0;
flex: 100%;
}
}
Use transforms instead of flexbox to vertically center the text.
1) Remove align-items: center from the .wrap-items class
2) Adjust the .wrap-items .item > .text class like this:
.wrap-items .item > .text {
padding: 10px;
font-size: 20px;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Updated Codepen
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
margin: 0;
background: #333;
padding: 30px;
font-family: Helvetica;
}
a {
color: white;
text-decoration: none;
}
h2 {
font-size: 1.2em;
}
.wrap-items {
background-color: #ccc;
padding: 0;
margin: 0 auto;
display: -ms-flexbox;
-ms-flex-wrap: wrap;
-ms-flex-direction: row;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
display: -webkit-box;
display: flex;
justify-content: center;
//align-items: center;
//align-content: center;
}
.wrap-items .item {
-webkit-box-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 1 0 33.333%;
width: 33.33333%;
margin: 0;
padding: 0;
color: white;
font-size: 0;
border: none;
background-color: steelblue;
position: relative;
}
.wrap-items .item.span-2 {
-webkit-box-flex: 2 0 auto;
-ms-flex: 2 0 auto;
flex: 2 0 auto;
width: 66.6666%;
height: auto;
}
.wrap-items .item img {
width: 100%;
height: auto;
}
.wrap-items .item > .text {
padding: 10px;
font-size: 20px;
position: absolute;
top: 50%;
transform: translate(0, -50%);
}
.item.un {
background-color: orange;
}
.item.dos {
background-color: brown;
}
.item.tres {
background-color: purple;
}
#media screen and (max-width: 760px) {
.wrap-items .item {
margin: 0;
flex: 50%
}
}
#media screen and (max-width: 400px) {
.wrap-items .item {
margin: 0;
flex: 100%;
}
}
<div class="wrap-items">
<!-- row 1 -->
<div class="item span-2">
<div class="text">
<h2>THE TITLE</h2>
<p>Just be water my friend</p>
<p>Small people can do very big things.</p>
</div>
</div>
<div class="item">
<img src="https://placekitten.com/g/800/600" alt>
</div>
<!-- row 2 -->
<div class="item un">
<div class="text ">
one or more lines of text inside the box
</div>
</div>
<div class="item">
<img src="https://placekitten.com/g/800/600" alt>
</div>
<div class="item dos">
<div class="text">
text in the middle
</div>
</div>
<!-- row 3 -->
<div class="item">
<img src="https://placekitten.com/g/800/600" alt="">
</div>
<div class="item tres">
<div class="text">
three lines of text centered vertically in the middle of the box
</div>
</div>
<div class="item">
<img src="https://placekitten.com/g/800/600" alt>
</div>
</div>

How to make equal space between boxes in one row via CSS

I have a requirement that there are 4 boxes in one row.
the boxes have fixed width and height
but the width of the row will change by screen size.
the first box should be aligned to the left border of the row
last box aligned to right border.
Also the space between any two boxes should be equal.
Is there a pure CSS way to make that happen? Here is the jsfiddle code.
HTML:
<div class="row">
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
<div class ="col">
<div class="box"></div>
</div>
</div>
CSS:
.row {
display: table;
border: 1px solid green;
width: 400px; /* it changes by screen size actually */
padding: 5px;
}
.row:before, .row:after {
content: "";
}
.row:after {
clear: both;
}
.col {
float: left;
width: 25%;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
margin: 0 auto;
}
.col:first-child .box {
margin-left: 0;
}
.col:last-child .box {
margin-right: 0;
}
Use text-align:justify on the container, this way it will work no matter how many elements you have in your div (you don't have to work out % widths for each list item
Updated CSS
.row {
text-align: justify;
min-width: 412px;
border: 1px solid green;
width: 80%; /* it changes by screen size actually */
height: 90px;
padding: 5px;
}
.row:after {
content: '';
display: inline-block;
width: 100%;
}
.col {
display: inline-block;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
margin: 0 auto;
}
FIDDLE
You can make use of css3 flex boxes which is supported in modern browsers.
.row {
display: flex;
justify-content: space-between;
border: 1px solid green;
}
.box {
border: 1px solid #DDD;
width: 80px;
height: 80px;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
jsfiddle demo
more about flex boxes # css tricks
Why not use flexbox ?
Demo
css
.flex-container {
padding: 5px;
margin: 0;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: space-between; /* this make the end divs at sides and equal space between other divs */
}
.flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 150px;
margin-top: 10px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
html
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
Read here for more detail on flexbox
you simply have to remove the padding attribute from the following
.row {
display: table;
border: 1px solid green;
width: 400px; /* it changes by screen size actually */
/*padding: 5px;*/
}
here is the demo.
Let me know if this was helpful or if you have anymore queries.

Resources