Flexbox using align-items: flex-start together with align-content: center - html

Good Day.
I'm trying to use flex box to enforce the following behavior in a flex container which contains excess space on the cross-axis:
If all flex items fit in one row, then they should align at the top of the cross axis; but
Once they wrap, the flex items should condense in the center of the cross axis.
To do this, I've tried the following markup at https://jsfiddle.net/ht5bue6s/
* {
box-sizing: border-box;
font-size: 1.5rem;
}
html {
background: #b3b3b3;
padding: 5px;
}
body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}
.flex-container {
height: 500px;
background: white;
padding: 10px;
border: 5px solid black;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: flex-start;
align-content: center;
}
.item-1 {
background: #ff7300;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-2 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-3 {
background: #ff9640;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-4 {
background: #f5c096;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-5 {
background: #d3c0b1;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-6 {
background: #d3c0b1;
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
<div class="flex-container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
<div class="item-6">6</div>
</div>
As you'll see, the flex items always condense to the center. That is, "align-content: center" is always applied even when the flex items do not wrap.
I've read the MDN quote, "For align-content to work you need more height in your flex container than is required to display the items. It then works on all the items as a set, and dictates what happens with that free space, and the alignment of the entire set of items within it".
With that, it seems that if there is excess space on the cross axis within the flex container, that you simply cannot apply align-items alongside align-content. Instead, align-content will always override align-items.
So my question: is there any combination of container or item CSS properties which will produce the behavior described in #1 and #2 requirements above?
Thank you.

To achieve the desired result, you can make use of a media query.
To make this work, remove the flex-wrap and align-content properties from the .flex-container element. We will nly add these properties on the .flex-container element at a particular width of the browser window.
For example, following media query
#media (max-width: 450px) {
.flex-container {
flex-wrap: wrap;
align-content: center;
}
}
will make a flex container a multi-line flex container when the width of the browser window equal to or smaller than 450px. We also add align-content: center to make sure that the flex-lines are aligned in the center of the flex container.
This ensures that for a width greater than 450px, flex container has only one flex-line and flex items are aligned at the start of that single flex-line. For a width smaller than or equal to 450px, we make the flex container a multi-line flex container and align those flex-lines at the center of the flex container using align-content: center.
Working Demo
* {
box-sizing: border-box;
font-size: 1.5rem;
}
html {
background: #b3b3b3;
padding: 5px;
}
body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}
.flex-container {
height: 500px;
background: white;
padding: 10px;
border: 5px solid black;
display: flex;
justify-content: space-evenly;
align-items: flex-start;
}
.flex-container div {
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}
.item-1 { background: #ff7300; }
.item-2 { background: #ff9640; }
.item-3 { background: #ff9640; }
.item-4 { background: #f5c096; }
.item-5 { background: #d3c0b1; }
.item-6 { background: #d3c0b1; }
#media (max-width: 450px) {
.flex-container {
flex-wrap: wrap;
align-content: center;
}
}
<div class="flex-container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
<div class="item-6">6</div>
</div>

Related

How to center an item with Flexbox?

I would like to center something in my code with flexbox. It works for all other elements, only here something seems to be wrong.
Does anyone have an idea?
.answer {
text-shadow: 0 0 2px gr;
display: flex;
justify-content: center;
border-radius: 5px;
margin-bottom: 20px;
padding: 20px;
border: 5px solid black;
border-radius: 5px;
width: 50%;
}
<section class="answer">
<p>Answer</p>
</section>
This is how it gets displayed in my live server
You can add body tag on css to make center on the page
to make horizontal center
body {
display: flex,
justify-content: center
}
or make vertical center
body {
display: flex,
align-items: center,
height: 100vh /* This is for full height of your screen */
}
or make horizontal and vertical center
body {
display: flex,
justify-content: center,
align-items: center,
height: 100vh
}
Your "Answer" is centered in the box. Are you trying to center the box on the page? In that case, you would need to apply flex styles to the parent. In this case, the body:
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.answer {
text-shadow: 0 0 2px gr;
display: flex;
justify-content: center;
border-radius: 5px;
margin-bottom: 20px;
padding: 20px;
border: 5px solid black;
border-radius: 5px;
width: 50%;
}
<section class="answer">
<p>Answer</p>
</section>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0px; /*add to remove body margin which always present and makes v-scroll if not removed*/
}
.answer {
display: flex;
justify-content: center;
margin-bottom: 20px; /*Remove it if their is no other content on page*/
padding: 20px;
border: 5px solid black;
border-radius: 5px;
width: 50%;
}
<section class="answer">
<p>Answer</p>
</section>

How to start a new line and align the newline with another item within flexbox?

I have a flexbox with different items inside.
When it wraps onto a new line I want to align this new line with the 2nd item on the first row of the flexbox, but I can't figure out how to do this. The width of the elements will be dynamic, based on the text inside.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
<div class="parent">
<div class="unique_element">First</div>
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
When it wraps onto a new line I want to align this new line with the 2nd item on the first row of the flexbox.
So, the real question is: How to re-arrange flex items when wrapping occurs?
Since HTML and CSS, by themselves, have no concept of when elements wrap, they have no control of this situation. You have to handle it, either with media queries or JavaScript.
Once you've selected your method for detecting the wrap, you can use the order property to re-arrange the items.
To expand on #MichaelBenjamin's fantastic answer:
Since HTML and CSS, by themselves, have no concept of when elements wrap, they have no control of this situation. You have to handle it, either with media queries or JavaScript.
You can work around this by setting a new parent element and nest the unique element as the first child. Set this new master-parent to display: flex;.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
height: 27px;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
.master-parent {
display: flex;
width: 400px;
}
<div class="master-parent">
<div class="unique_element">First</div>
<div class="parent">
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
</div>
You can create two divs inside the parent div, one that holds the unique element and one that holds generic children. That's how you get the separation
<div class="parent">
<div class="unique-wrapper">
<div class="unique_element">First</div>
</div>
<div class="child-wrapper">
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
</div>
Style the CSS as shown. Note .unique-wrapper has flex: 3 because you set the width of the element as 30%.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
width: 300px;
}
.unique_element {
background-color: Crimson;
padding: 10px 10px 10px 10px;
}
.unique-wrapper, .child-wrapper {
border: none;
margin: 0;
}
.unique-wrapper {
flex: 3;
}
.child-wrapper {
flex: 7;
display: flex;
flex-wrap: wrap;
}
.child {
width: auto;
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
Here is my codepen if you want to play with the code.
create a dummy element for spacing
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
.hideme{
visibility:invisible;
background-color:white;
border:none;
}
<div class="parent">
<div class="unique_element">First</div>
<div class="child">Second</div>
<div class="child">Third</div>
<div class="unique_element hideme"></div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>

Align items 2/3rd through div?

I have the following code in react:
.alignHorizontally {
display: flex;
}
.firstTitle {
align-items: center;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
.secondTitle {
margin-left: 80px;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
/* added by editor for demonstration purpose */
.alignHorizontally > * {
box-sizing: border-box;
}
.firstTitle {
border: 2px dashed red;
}
.secondTitle {
border: 2px dashed blue;
}
<div class="alignHorizontally">
<div class="firstTitle">Title
</div>
<div class="secondTitle">
Second title
</div>
</div>
I want the first div(firstTitle) to be on the far left hand side and the second div (secondTitle) to be about 2/3rds of the way through the screen. I know I can force this by adding padding-left: 100px but it feels ugly. Is there a nice way of doing this?
You can also use justify-content: space-between in your alignHorizontally class or try any of the other justify-content parameters that most closely match the layout you want.
.alignHorizontally {
display: flex;
justify-content: space-between;
}
.firstTitle {
align-items: center;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
.secondTitle {
margin-left: 80px;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
/* added by editor for demonstration purpose */
.alignHorizontally > * {
box-sizing: border-box;
}
.firstTitle {
border: 2px dashed red;
}
.secondTitle {
border: 2px dashed blue;
}
<div class="alignHorizontally">
<div class="firstTitle">Title
</div>
<div class="secondTitle">
Second title
</div>
</div>
It's not in English but it was the best tutorial I've seen so far about aligning items with CSS grid.
Alura's example justify-content CSS grid
https://www.alura.com.br/artigos/css-guia-do-flexbox
Add .secondTitle { width: 33%; } to occupy 1/3 of the space which means it will occupy 1/3 of the space.
with margin-left: auto you can push it then to the right to occupy that 1/3 at the right space.
Alternativly you could give the first div a width of 66% directly.
/* original CSS */
.alignHorizontally {
display: flex;
}
.firstTitle {
align-items: center;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
.secondTitle {
margin-left: 80px;
display: flex;
margin-top: 16px;
word-spacing: 2px;
line-height: 1;
}
/* CSS Chanegs !!! */
.secondTitle {
width: 33%;
margin-left: auto;
}
/* added by editor for demonstration purpose */
.alignHorizontally > * {
box-sizing: border-box;
}
.firstTitle {
border: 2px dashed red;
}
.secondTitle {
border: 2px dashed blue;
}
<div class="alignHorizontally">
<div class="firstTitle">Title
</div>
<div class="secondTitle">
Second title
</div>
</div>
.grid-container {
display: grid;
grid-template-columns: auto auto auto; // setting three columns in our grid layout
}
.grid-item2 {
grid-column-start: 3; // setting second div to start and end in 3d column
grid-column-end: 3;
}
<div class="grid-container">
<div class="grid-item1">Title #1</div>
<div class="grid-item2">Title #2</div>
</div>

Display content in between two div elements via CSS [duplicate]

This question already has answers here:
Fill the remaining height or width in a flex container
(2 answers)
Closed 2 years ago.
I'd like to display some "dots" in between a label and a price, like this:
from..........£2,000.49
total........£20,000.00
However, the dots must "adapt/reduce/increase", if the length of the price increases. (Like in the example above), as the prices are dynamic and not static/hardcoded.
I thought I would try this with flex. I have a working example below, where I have two columns, in two rows.
There is no width on the .price-big class, so the width of these divs increases/decreases, with the length of the numbers.
I am then adding the dots to the label class. However, this then pushes my divs onto separate lines/stacked, like in the example below.
.label {
content: ".............................................";
}
Any ideas on how to achieve this, would be helpful as I'm kinda getting stuck on this one.
Thank you,
Reema
.main {
display: flex;
flex-wrap: wrap;
align-items: baseline;
border: 1px solid green;
width: 200px;
}
.label {
font-size: 14px;
/* flex: 0 50%; */
flex-basis: 50%;
flex-shrink: 1;
flex-grow: 1;
border: 1px red solid;
/* width: 100%; */
text-align: left;
font-size: 14px;
}
.label:after {
content: ".............................................";
}
.price-big {
flex-basis: 0;
flex-shrink: 1;
flex-grow: 1;
border: 1px red solid;
text-align: right;
font-size: 20px;
}
<div class="main">
<div class="label">price</div>
<div class="price-big total">£2,000.49</div>
<div class="label">total</div>
<div class="price-big">£20,000.00</div>
</div>
You may combine float and flex to modify the formating context layout of the non floatting element and use a pseudo to fill that empty space inside it:
your CSS code modified :
.main {
/*display: flex;
flex-wrap: wrap;
align-items: baseline;*/
border: 1px solid green;
width: 200px;
overflow:hidden; /* because of the float label */
}
.label {
font-size: 14px;
/* flex: 0 50%;
flex-basis: 50%;
flex-shrink: 1;
flex-grow: 1; */
border: 1px red solid;
/* width: 100%;
text-align: left;*/
font-size: 14px;
margin-top:0.4em;
float:left;
clear:left;
}
.price-big {
border: 1px red solid;
font-size: 20px;
display:flex;
}
.price-big:before {
content:'';
border-bottom:dotted;
margin-bottom:0.2em;
flex-grow:1;
}
<div class="main">
<div class="label">price</div>
<div class="price-big total">£2,000.49</div>
<div class="label">total</div>
<div class="price-big">£20,000.00</div>
</div>
Omg, I literally figured out the answer one minute after posting this. I added overflow: overlay; to the label class:
.label {
font-size: 14px;
flex-basis: 50%;
flex-shrink: 1;
flex-grow: 1;
border: 1px red solid;
text-align: left;
font-size: 14px;
overflow: overlay; <--- added this
}
.main {
display: flex;
flex-wrap: wrap;
align-items: baseline;
border: 1px solid green;
width: 200px;
}
.label {
font-size: 14px;
/* flex: 0 50%; */
flex-basis: 50%;
flex-shrink: 1;
flex-grow: 1;
border: 1px red solid;
/* width: 100%; */
text-align: left;
font-size: 14px;
overflow: overlay;
}
.label:after {
content: ".............................................";
}
.price-big {
flex-basis: 0;
flex-shrink: 1;
flex-grow: 1;
border: 1px red solid;
text-align: right;
font-size: 20px;
}
<div class="main">
<div class="label">price</div>
<div class="price-big total">£2,000.49</div>
<div class="label">total</div>
<div class="price-big">£20,000.00</div>
</div>

Having trouble with flexbox properties

I have few problems to fix, that are
1- Why logo class properties not working ?
2- Why class title does not move to right, ie justify-content: flex-end not working OR which other way this can be done ?
3- Do I have to write display: flex; in all parent classes or simply container, which has all of them inside is enough ?
4- How it effect if I use display: flex; on all parent classes ?
Many Thanks
---HTML---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name = "viewport" content = "width=device-width", initial-scale = 1.0>
<title>My Portfolio</title>
<link rel="stylesheet" type="text/css" href="port.css">
</head>
<body>
<div class="container">
<div class="header">
<div id="logo"> Logo </div>
<div class="title">JAMES O BRAIN
<div class="sub-title">FRONT-END MONK</div> </div>
</div>
<div class="container2">
<div class="centre-picture">Central Pic</div>
<div class="left-boxs">
<div class="blue-box">Blue Box</div>
<div class="grey-box">Grey Box</div>
<div class="green-box">Green Box</div>
</div>
</div>
<div class="bottom-boxs">
<div class="featured-work">Featured Work</div>
<div class="appify">APPIFY</div>
<div class="sunflower">SUNFLOWER</div>
<div class="bokeh">BOKEH</div>
</div>
</div>
</body>
</html>
---CSS---
.container {
display: flex;
flex-direction: column;
border: 5px solid black;
margin: 10px;
padding: 50px;
}
.header {
display: flex;
border: 5px solid green;
}
.logo {
/* why these all properties not working at all ? */
border: 3px solid black;
padding: 10px;
margin: 10px;
}
.title {
border: 3px solid orange;
justify-content: flex-end; /* why this property not working, how can i get this to right ?*/
padding: 10px;
margin: 10px;
}
.sub-title {
border: 3px solid black;
padding: 5px;
margin: 5px
}
.container2 {
display: flex;
border: 5px solid red;
margin: 10px;
padding: 10px;
height: 300px;
}
.centre-picture {
border: 3px solid black;
margin: 10px;
padding: 10px;
}
.left-boxs {
border: 3px solid goldenrod;
margin: 10px;
padding: 10px;
order: -1;
}
.green-box {
background-color: green;
padding: 5px;
margin: 5px
}
.blue-box {
background-color: blue;
padding: 5px;
margin: 5px
}
.grey-box {
background-color: grey;
padding: 5px;
margin: 5px
}
.bottom-boxs {
display: flex;
border: 5px solid blue;
}
.appify {
border: 3px solid black;
margin: 10px;
padding: 10px;
}
.sunflower {
border: 3px solid black;
margin: 10px;
padding: 10px;
}
.bokeh {
border: 3px solid black;
margin: 10px;
padding: 10px;
}
As Daniel stated, you should make sure that you are not confusing #id and .class selectors in your markup/CSS. In your stylesheet you should be using #logo instead of .logo.
There are several ways you can align the items in your header. In the example below I attached justify-content: space-between; to the .header div which will align any direct child elements with an even amount of left over space between them. There are other ways you can do this...this is just one option. You can play around with margins, padding, and other flexbox values to see what works best for you.
Giving a container display: flex will have effect on all of the children elements inside the container, but not the contents inside each of those children. For example: If you have a container with three div elements inside it, and you give the container display: flex; justify-content: center; this will center each div horizontally, but not the text, images, etc, inside each div. In your case, at least in this example, yes, you need to add display: flex; to each of the divs inside the header in order to apply flexbox properties to the text inside.
Hope that helps a little. See the snippet below for one example. Good luck!
.container {
display: flex;
flex-direction: column;
border: 5px solid black;
width: 80%;
padding: 50px;
}
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border: 5px solid green;
padding: 10px;
}
#logo {
display: flex;
justify-content: center;
align-items: center;
border: 3px solid black;
padding: 10px;
}
.title {
display: flex;
justify-content: center;
align-items: center;
border: 3px solid orange;
padding-left: 10px;
}
.sub-title {
display: flex;
justify-content: center;
align-items: center;
margin: 10px;
padding: 10px;
border: 3px solid black
}
<div class="container">
<div class="header">
<div id="logo">Logo</div>
<div class="title">JAMES O BRAIN
<div class="sub-title">
FRONT-END MONK
</div>
</div>
</div>
</div>
It's because in your HTML you are using an id, #, but your CSS is targeting a class .. Change your CSS to this instead:
#logo {
/* why these all properties not working at all ? */
border: 3px solid black;
padding: 10px;
margin: 10px;
}