Vertically Center & Stretch Row-Oriented Flexbox - css

I am trying to create what is basically a horizontally/row-oriented version of Bootstrap v4's cards using flexbox (flex-direction: row). Instead of having a header, I'd like to have a left column that would contain the card's icon while the right column would contain the text for the card. I have this about 95% complete, except for the fact that when I vertically center the left column, it no longer takes up the entire vertical spacing (see the black areas surrounding the yellow .icon div in the CodePen example below). If I tell the column to stretch itself (change the align-self property of the .icon class to stretch), the column loses its vertical centering.
How can I make the left/yellow/.icon column be vertically centered and cover all vertical space?
The CodePen example has the parent and child divs colored to show the area they are occupying, but in my final product only the .icon div will have a background color. The other two divs (.wrapper and .content) will not have any background color. I prefer to not have to set the vertical height of the card, but if that is the only way to do what I want to accomplish, it won't be a deal breaker.
CodePen.io example

You can inbricate flex boxe to use alignements also in children.
Not too sure of what you look for exactly, but here an example of inbrication and use of flexbox to center things:
wrapper in middle of screen and content icon also in middle
html {
display:flex;
height:100%;/* give an height or min-height to that flex boxe */
}
body {/* single element, easy to middle center */
margin:auto;/* or justify-content+align-items center on html */
}
.wrapper {
background-color: black;
color: white;
display: flex;
flex-flow: row nowrap;
min-height: 100%;
width: 300px
}
.icon {
display:flex;/* flex child can be a flex boxe too */
align-items:center;
background-color: yellow;
color: black;
flex: 1 1 auto;
font-size: 32px;
padding: 20px;
}
.content {
background-color: lightgreen;
color: black;
flex: 12 1 auto;
padding: 20px;
}
h4 {
margin:0 0 10px;
}
/* where is body ? */
body {
box-shadow:0 0 0 5px white, 0 0 0 15px tomato;
}
<div class="wrapper">
<div class="icon">
#
</div>
<div class="content">
<h4>Application #1</h4>
<p>This is an application of flexbox. Tomato color is shadowed from body.</p>
</div>
</div>
pen forked

Related

Center text above wrapped, fixed-width items, ignoring container's leftover space

We want the layout that's shown below but don't know how to center the "Center here" text like that. Currently, we're centering it according to the width of the parent container. It's appearing too far to the right. In this example, only two items fit on a row, thus leaving empty space to the right of the items. We want the parent container's width to be as per the min width of the child flexbox to center the text above it. The flex box is flex row with wrapping for items that don't fit in. We basically want to ignore that extra space on the right where the item can't fit and set the width of the parent div accordingly
The blue color represents the flex-box's width. Here's the tailwind CSS classes that we're currently using:
className="flex flex-row overflow-x-hidden flex-wrap 3xl:flex-shrink 2xl:block 2xl:grid 2xl:grid-cols-3 3xl:grid-cols-3 justify-items-end "
Hard no sample code, but here I tried my best, hope it helps
This is my code sample, you can try it :
body{
padding: 5%;
}
.container{
border: 5px solid #000;
width: 300px;
height: 400px;
}
.container-box{
margin: auto;
display: flex;
flex-wrap: nowrap;
padding: 10px;
width: 200px;
height: 200px;
}
.box-1, .box-2{
margin: auto;
border: 5px solid #000;
width: 40%;
height: 40%;
}
<div class="container">
<div class="container-box">
<div class="box-1"></div>
<div class="box-2"></div>
</div>
</div>

Why is bottom margin inside element box for button but not p element?

Why is it that adding a bottom margin for a p element adds space beyond the element's box (that is not affected by the background color set in CSS), but the inverse is true (the margin remains colored) when adding a bottom margin for a button? (I fixed this by using padding only and setting margin to 0 for the p element, so I'm only asking out of curiosity.)
This CSS:
.about p {
padding: 0 4em 2em 4em;
margin: 0 0 2em 0;
text-align: left;
}
button {
margin-top: 1em;
margin-bottom: 2em;
}
Resulted in (note the white space above the "PORTFOLIO" section but not below the button at the bottom):
To view the rest of my code, view CodePen.
I can't seem to find any suitable question to close this as a duplicate of, so here's an answer.
You are the victim of margin collapsing in the case of the p.
See this example. The outer element has a yellow background, and you would expect to see this behind the p (above and below), but it "inherits" the p's margin, so what you're seeing is the white background of the body.
.outer {
background: yellow;
}
.inner {
background: lime;
margin: 2em 0;
}
<div class="outer">
<p class="inner">two block elements</p>
</div>
The button in your example, however, is not a block element. It has display:inline-block by default, so no margin collapsing takes place and the outer div's background is visible around it.
.outer {
background: yellow;
}
.inner {
background: lime;
margin: 2em 0;
}
<div class="outer">
<button class="inner">inline-block in a block</button>
</div>
For more information, see Mastering margin collapsing on MDN.

Prevent CSS3 flex-shrink from crushing content

I'm trying to create a flexible layout in CSS3 with 3 boxes stacked on each other. The boxes are siblings and thus have the same parent element. The height of the first box must fit its content. The height of the following two boxes shall grow to fit their respective content until they're about to overflow their parent. In that case, they shall shrink so that they don't overflow.
The problem is that I can't figure out how to prevent one of the shrinking boxes from becoming crushed if its content is small in relation to the other shrinking box. I want those boxes to shrink down to a certain point where they won't shrink anymore – let's say the equivalent of two rows of text for example. Setting min-width isn't an option because I don't want the boxes to be taller than their content in case the content is only one row for example. If any of the boxes has come to the point where it shall not shrink anymore and the parent can't hold them without overflowing, the parent shall get a scrollbar.
I don't know the content in advance so the layout has to be dynamic. I want to solve this only with CSS, if possible.
Here's an example of the problem where box3 is too small:
p {
margin: 0;
}
.container, .box {
border: 1px solid black;
}
.box {
background-color: white;
margin: 1em;
overflow: auto;
}
#container {
background-color: yellow;
display: flex;
flex-direction: column;
height: 15em;
overflow: auto;
}
#box1 {
flex: 0 0 auto;
}
#box2 {
}
#box3 {
}
<div id="container" class="container">
<div id="box1" class="box">
<p>◼</p>
</div>
<div id="box2" class="box">
<p>◼◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◻◻◻◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◻◻◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◻◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◻◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◻◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◻◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◻◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◻◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◻◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◻◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◻◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◼◻◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◻◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◻◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◻</p>
<p>◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼</p>
</div>
<div id="box3" class="box">
<p>◼◻◻</p>
<p>◼◼◻</p>
<p>◼◼◼</p>
</div>
</div>
IF I understand your question correctly, the flex-shrink property should be what you are looking for.
Set #box1 to flex-shrink: 0
Set #box2 to flex-shrink: 1
Set #box3 to flex-shrink: 1

Fill remaining horizontal space (or max-width) AND wrap on min-width

#fit and #wrap illustrate two different behaviors that I want to have for one element depending on the situation. The element should work like #fit if there is room, but should work like #wrap if there is not enough room.
http://jsfiddle.net/benstenson/dN8VJ/
<div id="print">
Printable
</div>
<div id="fit">
Looks good on same line
</div>
<div id="wrap">
Looks good on new line
</div>
css
body{overflow:hidden;padding:1em;}
div
{
/*display:inline-block;*/
float:left;
height:1in;
margin:.5em;text-align:center;line-height:1in;
white-space:nowrap;box-shadow:0 0 .5em gray;
}
#print
{
width:5in;
background-color:black; color:white;
}
#fit
{
/* when on same line
Size to min-width
OR fill remaining space
(like flexible box style).
Either way is fine.
*/
min-width:3in;
background-color:gold;
}
#wrap
{
/* when wrapped to next line */
/* fill 100% OR to max width */
width:100%;
min-width:3in;
max-width:5in;
background-color:orange;
}
What you're looking for is Flexbox, but most browsers that support Flexbox don't support wrapping. The ones that do are IE10, Chrome, and Opera.
http://codepen.io/cimmanon/pen/lqrGB
<div class="container">
<div id="print">
Printable
</div>
<div id="either">
Looks good on either line
</div>
</div>
.container {
display: -ms-flexbox;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
#supports (flex-wrap: wrap) {
.container {
display: flex;
}
}
.container div {
height: 1in;
margin: .5em;
text-align: center;
line-height: 1in;
white-space: nowrap;
box-shadow: 0 0 .5em gray;
}
#print {
/*-webkit-flex: 1 5in;
-ms-flex: 1 5in;
flex: 1 5in;*/
width: 5in;
background-color: black;
color: white;
}
#either {
-webkit-flex: 1 3in;
-ms-flex: 1 3in;
flex: 1 3in;
max-width: 5in;
background-color: gold;
}
Assuming I've understood your question correctly, I think you can achieve what you want with inline-block.
You'll need to put your content in a paragraph inside another div, like this:
<div class="wrap-or-fit">
<p>This is where your content goes.</p>
</div>
Then just set the min-width and max-width properties on the paragraph, as well as display:inline-block.
.wrap-or-fit > p {
max-width:5in;
min-width:3in;
display:inline-block;
...
}
If the content fits on a single line less than 3 inches wide, the container will expand to be at least 3 inches. If the content is wider than 5 inches, it is forced to wrap within a container of exactly 5 inches.
If the content is between 3 and 5 inches, the container width matches the content width. I'm not sure if that is what you wanted, but that may be the best you can do.
You can see an expanded example showing both narrow and wide content samples, and styling that more closely matching your original example in this codepen.

Center Div Tags in another Div Tag

I'm trying to get a parent div tag to hold n children div tags such that they are all on the same line, yet grouped together in the center. For example:
Here the children are blue, and the parent is red.
Here are the things I've tried:
Making blue divs display:inline to get them on the same line. Problems: doesn't display even with its width and height both set to 10px.I tried adding , but it only was a couple pixels wide.
Making blue divs float:left. Problems: Have to programmatically resize red parent to child contents since the divs are floated and then center in its parent to get what I want. There should be a solution that doesn't involve javascript.
For IE6 and IE7 compatibility you might have to add zoom:1; and *display:inline; to your child CSS
jsFiddle
.parent {width:100%;border:1px solid red;text-align:center;}
.child {width:15%;display:inline-block;border:1px solid blue;}
<style>
.container {
width: 100%;
padding: 0;
text-align: center;
border: 1px solid red;
}
.inner {
display: inline-block;
margin: 0 5px;
border: 1px solid blue;
}
</style>
<div class="container">
<div class="inner">
one
</div>
<div class="inner">
two
</div>
<div class="inner">
three
</div>
</div>
Stick the blue divs in a container div. Find their widths (margin and padding included) and give the container div that width. Then set the container div's margin to 0 auto, stick it in the red div and you should be fine.
Try to use display: inline-block;:
.child {
display: inline-block;
...
}
http://jsfiddle.net/mupuR/

Resources