How do I align two flexbox elements? [duplicate] - html

This question already has answers here:
Center and bottom-align flex items
(3 answers)
Closed 4 years ago.
I have a problem with flexbox. I attempted to align two elements; the one to the top of the container, and another one to the center. Most of the flexbox examples were using three elements, not two elements. So I tried my own solution.
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
height: 100px;
background-color: #dfdfdf;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
}
#box2 {
display: flex;
background-color: #00ff00;
}
#dummy {
display: flex;
opacity: 0;
}
<div id="main">
<div id="box1">box1</div>
<div id="box2">box2</div>
<div id="dummy">dummy</div>
</div>
...and I also applied it to horizontal case.
#main {
display: flex;
flex: 1;
flex-direction: row;
justify-content: space-between;
height: 100px;
background-color: #dfdfdf;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
width: 200px;
}
#box2 {
display: flex;
background-color: #00ff00;
width: 100px;
}
#dummy {
display: flex;
opacity: 0;
width: 200px;
}
<div id="main">
<div id="box1">box1</div>
<div id="box2">box2</div>
<div id="dummy">dummy</div>
</div>
However, it needs a useless dummy element. I think it is not a good idea :(
Is there any better way to solve this?

you don't have to add this 'dummy' div. According to me you should keep display flex in you container, but change justify-content: space-between to justify-content: center.
Then simply add position absolute to you first, child element and display it on the top of the container. Also remember to add relative position to your container.
Here is working code:
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
height: 100px;
background-color: #dfdfdf;
position: relative;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
position:absolute;
top:0;
width:100%;
}
#box2 {
display: flex;
background-color: #00ff00;
}
Fiddle: https://jsfiddle.net/95Lwcbuk/1/

If you want to use flex-box only, you could wrap another .container element around each of your boxes, set these to use flex also, but set the first one to justify-content: flex-start, the last one to justify-content: flex-end.
See example
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
height: 100px;
background-color: #dfdfdf;
}
.container {
flex-basis:50%;
display:flex;
flex-direction:column;
}
.container:first-child {
justify-content: flex-start;
}
.container:last-child {
justify-content: flex-end;
}
#box1 {
background-color: #ff0000;
}
#box2 {
background-color: #00ff00;
}
<div id="main">
<div class="container">
<div id="box1">box1</div>
</div>
<div class="container">
<div id="box2">box2</div>
</div>
</div>

Related

Centering a justify-content space-between once it becomes a single column

I am trying to style a div that has two children, with flexbox and flex-wrap, without media-queries, that at a certain width is space-between, but once it is a single column is centered (as opposed to currently where once it wraps it's like flex-start). Hopefully that makes sense.
I think this is the relevant code, basically when it wraps, i would like space between to become center:
HTML and CSS
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I hope this fits your needs.
Since I don't believe that there is a way to solve your problem using only native CSS (i.e. no media queries, and I assume no JS), I let myself change the space-between to space-around (since you gave .content 82% there is not much of a difference).
if you do not want to use space-around, I find it hard for me to believe that there is a solution without media-queries \ JS.
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
place-items: center;
justify-content: space-around;
width: 100%;
}
h1 {
width: min-content;
}
h6 {
width: min-content;
}
<div class="content-container">
<div class="content">
<h1 class="content__1">'content1'</h1>
<h6 class="content__2">'content2'</h6>
</div>
</div>
Do you want like this:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I'm afraid it's impossible to achieve what you want the way you want (i.e., CSS without a #media query).
Solution 1: CSS without a #media query
If you don’t want to use a #media query, then look at Solution 1. But space-around is a different thing than space-between because space-between will push your two elements all the way to the left and right when they’re not stacked above each other, while space-around will not do so.
An example of space-between:
An example of space-around:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
If Solution 1 is good enough for you, then you don’t need to read further. But there are many better options on the table. If you’re not limited and can make changes to your code, then I think you should look at other possible solutions below. You can use different approaches to achieve what you want if you want your two elements to be pushed all the way to the left and right when they’re not stacked above each other.
The reason why this can’t be done without using a #media query, JavaScript or jQuery is that CSS on its own can’t “switch” from space-between to space-around when your two elements get stacked above each other. You need to define some rules using a #media query, JavaScript or jQuery so that CSS will change from space-between to space-around at a specific window width (i.e., exactly when your two elements get stacked above each other). See other possible solutions below.
Solution 2: CSS with a #media query
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
#media only screen and (max-width: 708px) {
.content {
justify-content: space-around;
}
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 3: JavaScript
window.onload = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
window.onresize = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content" id="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 4: jQuery
$(window).on('load', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
$(window).on('resize', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
P.S. I added text-align: center; and line-height: 50px; to the .content class because if you really want to have your content centered then you also need to center text horizontally and vertically inside your containers. This is a quick fix, you can remove that if you want. Also, border: 2px solid red; is added to the .content class so you can better understand the difference between space-between and space-around.
Try this.
.content-container {
display: flex;
justify-content: center;
width: 100%;
text-align:center;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align:center;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Here is an idea using clamp() where I will toggle between a fixed width and full width based on a parameter (50rem in this case)
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content > * {
width: clamp(15rem, (50rem - 100vw)*9999, 100%);
outline: 1px solid red;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Related article if you want more detail: https://css-tricks.com/responsive-layouts-fewer-media-queries/
The following solution uses only flexbox, no media queries or JavaScript. Does this do what you want?
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content h1,
.content h6 {
flex: 1;
}
.horizontal-spacing {
flex: 1;
min-width: calc(20rem + 15.5rem);
height: 0;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<span class="horizontal-spacing"></span>
<h6>'content2'</h6>
</div>
</div>

aligning the last object in css-grid or flexbox

I'm trying to tidy up my code and I have a menu that I would like to organise a little better.
Is there a way of aligning the menu at the start, end or or center while having the last item in the menu aligned to the end?
I've currently stripped out everything and kept the basics. If I remove margin-top: auto from the last div, all items are aligned in the center as stated in the .menu css.
If I keep margin-top: auto from the last div, the last div is aligned where I want it but the other items are aligned at the top and not where it's supposed to.
Here's my code:
HTML
<div class="header">
<div class="one">one</div>
<div class="two">two</div>
</div>
<div class="menu">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
</div>
CSS
.header{
height:70px;
background: red;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
}
.header .one {
background: blue;
display: flex;
align-items: center;
padding: 0.5rem 1rem;
}
.header .two {
background: green;
display: flex;
align-items: center;
padding: 0.5rem 1rem;
}
.menu {
width:70px;
height: 100vh;
background: blue;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
.three {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.menu div:last-of-type {
margin-top: auto;
}
Here it is in action: Fiddle
Add the following and this will work. You may want to add a padding to match your header, in this case 70px.
.menu {
padding-top: 70px;
}
.menu div {
margin-top: auto;
margin-bottom: auto;
}
.menu div:last-of-type {
margin-top: auto;
margin-bottom: 0;
}

Vertically align input when using Flexbox [duplicate]

This question already has answers here:
Flexbox: center horizontally and vertically
(14 answers)
Closed 4 years ago.
How do I get the input box to be vertically aligned to the middle? I tried adding vertical-align: "middle" to a few places but I am not getting any success. I feel like flexbox is a part of the problem here?
.container {
/* Flex Properties */
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
}
.item {
background-color: orange;
}
label {
width: 100px;
display: inline-block;
}
<div class="container">
<div class="item">
<label>Gee my iefwaf fwats: </label>
<input>
</div>
</div>
Give the .item div display: flex and align-items: center, since it's the parent of the input element:
.container {
/* Flex Properties */
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
}
.item {
display: flex; /* added */
align-items: center; /* added */
background-color: orange;
}
label {
width: 100px;
/*display: inline-block; not necessary*/
}
<div class="container">
<div class="item">
<label>Gee my iefwaf fwats: </label>
<input type="text">
</div>
</div>
Try this css code with your html.
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
}
.item {
background-color: orange;
display: flex;
align-items: center;
}
label {
width: 100px;
display: inline-block;
}
input {
display: inline-block;
}
Please check with the added CSS::
.container {
/* Flex Properties */
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
}
.item {
background-color: orange;
}
label {
width: 100px;
display: inline-block;
vertical-align: middle;
}
input {
width: 100px;
display: inline-block;
vertical-align: middle;
}
<div class="container">
<div class="item">
<label>Gee my iefwaf fwats: </label>
<input>
</div>
</div>

CSS Flexbox annoying slight offset of row elements [duplicate]

This question already has answers here:
White space under image [duplicate]
(5 answers)
Remove white space from image
(3 answers)
Closed 5 years ago.
So I have two divs in a full width container that I want to give variable sizing with flexbox, but no matter what I do, there is an annoying offset at the bottom. Using margins I can come close to fixing the problem, but it's never perfect.
If you run the code snippet below and scroll to the bottom you can see it, the image and the black content container are not aligned at the bottom.
What's going on?
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
margin-bottom:7px;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg"/>
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</container>
There is some space below the image since the image is an inline-element and as such there is some space reserved below the (invisble) baseline that the image is aligned to vertically. To avoid that, there are two possible solutions:
1.) Apply display: block; to the image (see first snippet)
or
2.) Apply font-size: 0 to the image container (see second snippet)
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
img {
display: block;
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg" />
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</div>
SECOND SOLUTION:
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
font-size: 0;
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg" />
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</div>
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
margin-bottom:4px;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg"/>
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</container>
Looks like the margin is just a bit off

Flex with first child centred and second child at the end

How can I push .right all the way to the right while keeping .centred in the center? (It doesn't need to be with flex, but I would need to keep .centred above .right on mobile view)
https://codepen.io/anon/pen/rjZLOv
<div class="flex">
<div class="centred">
<div class="a">asdfasdf</div>
<div class="b">asdfasdf</div>
</div>
<div class="right">asdfasfad</div>
</div>
.flex {
display: flex;
align-items: center;
justify-content: center;
}
.centred {
justify-content: center;
}
.right {
justify-content: flex-end;
}
You can make .centred inline-block and use text-align: center; on the parent to center it, then float .right to the right.
.container {
width: 1024px;
margin: auto;
text-align: center;
}
.centred {
display: inline-block;
}
.right {
float: right;
}
<div class="container">
<div class="centred">
<div class="a">asdfasdf</div>
<div class="b">asdfasdf</div>
</div>
<div class="right">asdfasfad</div>
</div>
You can do it like this: https://codepen.io/anon/pen/dNqXjo
The code:
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex > * {
flex: 1;
}
.flex::before {
content: "";
flex: 1;
background: red;
}
This makes the items inside the flex container (.flex) use flex.
Then we add another item to use up the rest of the space on the left site so that the rest of the content is pushed to the right.
Configure width with flex-basis.
You almost have it you just need margin-left and direction base:
.flex {
display: flex;
align-items: center;
flex-direction: column;
}
.centred {
}
.right {
margin-left: auto;
}