How to add elements around an already center-justified element? - html

I have created a form with some text elements aligned vertically like so:
They are centered horizontally and vertically on the page using flexbox:
.my-class {
display: flex;
justify-content: center;
align-items: center;
flex-direction:column;
}
What I'm trying to do now is maintain this alignment (i.e. keep everything that's on the page already exactly where it is) while adding some elements on either side of the first text box. I tried wrapping everything in a div but since the elements on either side of the text box are not the same width, the text box loses its alignment:
As you can see, the long text boxes are now out of alignment. How can I add elements before and after the first text box without moving where it is?

Assuming it is the url/pass/button that are the one's to be centered, and the https/path stick on each side, I would do it like this, where I use a flex row container and pseudo elements to break each group of item into lines of their own.
With this markup one also have full control to move around the items based on screen width's etc.
The 2 main things making this work is the pseudo elements, that, with their full width, force them into rows of their own, and at the same time push content down, together with the order property, enable to position them before the pass and auth respectively.
Stack snippet
.flex {
display: flex;
flex-flow: row wrap;
justify-content: center; /* horiz. center items */
align-content: center; /* vert. center wrapped items */
/*align-items: center;*/ /* vert. center unwrapped items */
}
.flex div:nth-child(1),
.flex div:nth-child(3) { /* https/path item */
flex: 1; /* share space left equal */
}
.flex div:nth-child(2),
.flex div:nth-child(4) { /* url/pass item */
flex-basis: 300px; /* need equal width */
}
.flex::before { /* 1st line breaker */
content: ''; width: 100%;
order: 1;
}
.flex div:nth-child(4) {
order: 2;
}
.flex::after { /* 2nd line breaker */
content: ''; width: 100%;
order: 3;
}
.flex div:nth-child(5) {
order: 4;
}
/* styling */
.flex {
height: 200px;
border: 1px solid red;
}
.flex span {
display: inline-block;
border: 1px solid gray;
padding: 2px;
margin: 2px;
}
.flex div:nth-child(2) span,
.flex div:nth-child(4) span {
width: calc(100% - 10px);
}
.flex div:nth-child(1) {
text-align: right;
}
<div class="flex">
<div><span>http(s)</span></div>
<div><span>url</span></div>
<div><span>path</span></div>
<div><span>***</span></div>
<div><span>authenticate</span></div>
</div>
If the width of the url/pass should scale with parent's width, use percent combined with CSS Calc.
Stack snippet
.flex {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-content: center;
}
.flex div:nth-child(1),
.flex div:nth-child(3) {
flex: 1;
}
.flex div:nth-child(2),
.flex div:nth-child(4) {
flex-basis: 60%;
}
.flex::before {
content: ''; width: 100%;
order: 1;
}
.flex div:nth-child(4) {
order: 2;
}
.flex::after {
content: ''; width: 100%;
order: 3;
}
.flex div:nth-child(5) {
order: 4;
}
/* styling */
.flex {
height: 200px;
border: 1px solid red;
}
.flex span {
display: inline-block;
border: 1px solid gray;
padding: 2px;
margin: 2px;
}
.flex div:nth-child(2) span,
.flex div:nth-child(4) span {
width: calc(100% - 10px);
}
.flex div:nth-child(1) {
text-align: right;
}
<div class="flex">
<div><span>http(s)</span></div>
<div><span>url</span></div>
<div><span>path</span></div>
<div><span>***</span></div>
<div><span>authenticate</span></div>
</div>
Another option would be to keep the initial flex column direction, and with an extra wrapper use absolute positioning for the http(s)/path items.
.flex {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.flex > div:nth-child(-n+2) {
position: relative;
width: 60%;
}
.flex div div:nth-child(1) {
position: absolute;
top: 0;
right: 100%;
}
.flex div div:nth-child(3) {
position: absolute;
top: 0;
left: 100%;
}
/* styling */
.flex {
height: 200px;
border: 1px solid red;
}
.flex span {
display: inline-block;
width: calc(100% - 10px);
border: 1px solid gray;
padding: 2px;
margin: 2px;
}
.flex div div:nth-child(1) {
text-align: right;
}
.flex div div:nth-child(1),
.flex div div:nth-child(3) {
width: auto;
}
<div class="flex">
<div>
<div><span>http(s)</span></div>
<div><span>url</span></div>
<div><span>path</span></div>
</div>
<div><span>***</span></div>
<div><span>authenticate</span></div>
</div>
Updated (based on another question with a similar need)
One can also keep the simpler markup, with no extra wrapper, and use inline-flex combine with making the flex parent also a flex container.
Stack snippet
body {
text-align: center;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.flex {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: center;
}
.flex div:nth-child(2),
.flex div:nth-child(4) {
width: 300px;
}
.flex div:nth-child(1) {
position: absolute;
top: 0;
right: 100%;
}
.flex div:nth-child(3) {
position: absolute;
top: 0;
left: 100%;
}
/* styling */
.flex {
border: 1px solid red;
}
.flex span {
display: inline-block;
width: calc(100% - 10px);
border: 1px solid gray;
padding: 2px;
margin: 2px;
text-align: left;
}
.flex div div:nth-child(1) {
text-align: right;
}
.flex div div:nth-child(1),
.flex div div:nth-child(3) {
width: auto;
}
<div class="flex">
<div><span>http(s)</span></div>
<div><span>url</span></div>
<div><span>path</span></div>
<div><span>***</span></div>
<div><span>authenticate</span></div>
</div>

Related

CSS Make Div Expand to Fill Parent but not Overflow

I am working on a project which requires some basic HTML/CSS. I have a code pen which may be easier to visualize: https://codepen.io/Sean713/pen/yLEZVEe
My objective is to make the innerBottomHalf element expand to fully fill the bottomHalf element (barring any padding). I would also like the navbar + wholePage element to take up the full VH.
I currently have it set so that the wholePage takes up the full VH, I'm not sure how to subtract the navbar height from this.
I also see that my innerBottomHalf expands outside of my BottomHalf, I do not know why this is, because I've set its height to be 100%.
I tried a lot of solutions online, the GPT chatbot, and prodding around with the code, but have been unable to figure it out. I appreciate any help.
My code is as follows:
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
height: 100vh;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.bottomHalf {
background-color: grey;
height: 100%;
}
.innerBottomHalf {
background-color: brown;
height: 100%;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>
With height: 100% on nested elements you'll get an overflow because there are heights from other elements being added. Instead of percentage heights, just use flex properties all the way.
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0; /* remove default margins */
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
/* height: 100vh; */
flex: 1; /* new */
}
.bottomHalf {
background-color: grey;
/* height: 100%; */
display: flex;
flex-direction: column;
flex: 1;
}
.innerBottomHalf {
background-color: brown;
/* height: 100%; */
flex: 1;
}
/* no adjustments below this line */
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>

Flexbox items alignment with same height & item aligment

I have a simple layout with image on Left and Title of blog on right with light grey background for large screen or were width is minimum 800px. for smaller screens it should show image on top and Title below image. It is working fine except two thing
It show extra space under image which is shown as yellow background in this case.
I want Title Item to be same height as Image element with light grey background, in this case which is represented as red.
.flex-container {
display: flex;
align-items: stretch;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
color: #555;
width: 50%;
height: 100%;
margin: 0px;
text-align: center;
align-self: center;
font-size: 30px;
}
.title-wrapper {
background-color: #f00 !important;
}
.imgx {
width: 100%;
}
#media (max-width: 800px) {
.flex-container {
flex-direction: column;
}
.flex-container>div {
width: 100%;
margin: 0px;
}
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
To avoid the gap under the image, 2 classical options :
reset vertical-align: to top or bottom
or reset display to block.
To center content inside the second box, make it also a grid or flex box
Possible fix :
.flex-container {
display: flex;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
color: #555;
width: 50%;
text-align: center;
font-size: 30px;
}
.flex-container .title-wrapper {
background-color: #f00;
display:flex;
align-items:center;
justify-content:center;
margin:0;
}
.imgx {
width: 100%;
display:block;
}
#media (max-width: 800px) {
.flex-container {
display:grid;/* or block*/
}
.flex-container>div ,
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
To get rid of the space beneath the image, the image needs to be display: block, then to make the title full height and still aligned centre, you need to remove the height and then make the title itself flex and use align and justify on it (see comments in css below):
.flex-container {
display: flex;
align-items: stretch;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
/* remove height from here */
color: #555;
width: 50%;
margin: 0px;
font-size: 30px;
}
.title-wrapper {
background-color: #f00 !important;
/* add the following to here */
display: flex;
justify-content: center;
align-items: center;
}
.imgx {
width: 100%;
display: block; /* add this */
}
#media (max-width: 800px) {
.flex-container {
flex-direction: column;
}
.flex-container>div {
width: 100%;
margin: 0px;
}
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
you have to remove height and align-self in .flex-container > div
.flex-container > div {
background-color: yellow;
color: #555;
width: 50%;
margin: 0px;
text-align: center;
font-size: 30px;
}
are you sure to use align-self or did you mean align-items and justify-content?

flexbox - center items for 1/3 and 2/3 proportion

I need to center item (one) in 1/3 row space and center another item (two) in the rest of the row space (2/3).
https://jsfiddle.net/gpe9a5qb/1/
How to center items to the specific space they fit so they will NOT center depends on their size but depend on the size of the space they are signed (1/3 and 2/3)?
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
.one should be center inside 1/3 and .two must be center inside 2/3 space.
If i get this correctly, you are speaking about center horizontally.
the css will look like this
body
{border:1px dotted yellow;
margin:0;
padding:0;
width:100%;
height:100%;
background:brown;}
.container{
background:red;
width:250px;
height:100px;}
.box
{display:flex;
}
.box > div{
display:flex;
justify-content:center;
}
.one
{
background:green;
flex-basis:33.33%;
}
.two
{background:blue;
flex-basis:66.66%;}
Hope this helps.
What i did here, is that i put flex on the inside divs, and center their content(not the parent container, which you cant center , because they take up the space).
You were almost there. Just one modification needed:
Make each flex item a flex container with justify-content: center.
That's it.
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
/* justify-content: space-around */ /* remove; doing nothing */
}
.one {
background: green;
flex: 1 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
.two {
background: blue;
flex: 2 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
If I understand you correctly, you want both your .one and .two elements to be vertically centered inside of .box, whilst still taking up one-third and two-thirds of the space respectively.
In order to achieve this, you simply need to ensure that .box takes up the full height of .container.
You can achieve this by either setting display: flex on .container along with flex: 1 on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
display: flex;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
flex: 1;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
Or simply by setting height: 100% on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
height: 100%;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>

Flexbox wrap items on demand?

I currently have a model like this
.parent
.child1
.child2
.child3
.child4
The request is: 'parent' is a row that takes full width of the device.
In big screen, there is one row with 4 children.
In smaller screen, there are 2 rows with 2 columns each.
And in the extra small screen there are 1 column with 4 rows.
Is there any way that I can achieve the request using only Flexbox? (because I hate Boostrap so much...)
I tried flex-wrap: wrap for the parent and flex: 1 for the children, but failed :(
Thank you :)
This is a SCSS mixin that does that:
#mixin n-columns($min-width, $gutter, $last-equal:false, $max-cols:5, $selector:'.colItem'){
display: flex;
flex-wrap: wrap;
margin-left: -$gutter;
// margin-top: -$gutter;
position: relative;
top: -$gutter;
> #{$selector} {
flex: 1 0 auto;
margin-left: $gutter;
margin-top: $gutter;
#if $last-equal {
#for $i from 2 through $max-cols {
$screen-width: ($min-width*$i)+($gutter*$i);
$column-width: (100%/$i);
#media( min-width: $screen-width) {
max-width: calc(#{$column-width} - #{$gutter});
}
}
$column-width: (100%/$max-cols);
#media( min-width: $min-width*$max-cols) {
min-width: calc(#{$column-width} - #{$gutter});
}
}
}
}
You use it like so:
.parent{
#include n-columns(200px, 3px, true, 5);
}
You'll understand all the things it can do after you use it with different settings and see the results, it's pretty straightforward.
.container {
display: flex;
}
.box {
flex: 1;
}
#media ( max-width: 800px ) {
.container { flex-wrap: wrap; }
.box { flex: 0 0 50%; box-sizing: border-box; }
}
#media ( max-width: 500px ) {
.box { flex-basis: 100%; }
}
/* non-essential decorative styles */
.box {
height: 50px;
background-color: lightgreen;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
<div class="container">
<div class="box"><span>1</span></div>
<div class="box"><span>2</span></div>
<div class="box"><span>3</span></div>
<div class="box"><span>4</span></div>
</div>
jsFiddle

Vertical CSS Flexbox with squares

I'm trying to achieve a responsive Layout with:
- A fixed header width width 100% and an height of e.g. 50px
- 3 equal squares on the right, taking over the whole space from the top to the bottom of the page.
- A main content are taking over the remaining space on the page
Currently my code looks like this (jsfiddle) but I can't get the width of the boxes on the right to be set automatically based on the current height in order to be displayed as squares... Does anybody know a solution for this in pure CSS?
HTML:
<div id="mainView">
<div id="content">
</div><!-- content -->
<div id="squaressWrapper">
<div id="square1"></div><!-- dummy -->
<div id="square2"></div><!-- dummy -->
<div id="square3"></div><!-- dummy -->
<div id="square4"></div><!-- dummy -->
</div><!-- squaressWrapper -->
</div><!-- mainView -->
</div><!-- wrapper -->
CSS:
html {
height: 100%;
margin: 0;
padding: 0;
}
body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#wrapper {
width: 100%;
height: 100%;
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
-webkit-align-content: stretch;
align-content: stretch;
}
#header {
height: 50px;
width: 100%;
background: #ffb8c4;
}
#mainView {
flex: 1;
-webkit-flex: 1;
position: relative;
background: #666;
}
#squaressWrapper {
position: absolute;
height: 100%;
background: green;
right: 0;
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
-webkit-align-content: stretch;
align-content: stretch;
}
#square1 {
position: relative;
flex: 1;
-webkit-flex: 1;
width: 100px;
border: 2px solid white;
background: green;
}
#square2 {
position: relative;
flex: 1;
-webkit-flex: 1;
width: 100px;
border: 2px solid white;
background: green;
}
#square3 {
position: relative;
flex: 1;
-webkit-flex: 1;
width: 100px;
border: 2px solid white;
background: green;
}
I get a solution, using vh units as suggested by Nicho.
The CSS
#squaressWrapper {
position: absolute;
height: 100%;
width: 33vh;
right: 0;
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
-webkit-align-content: stretch;
align-content: stretch;
}
.squares {
position: relative;
flex: 1;
-webkit-flex: 1;
width: calc(100% - 15px);
border: 2px solid white;
background: green;
right: -11px;
}
demo
The dimensions are a little bit strange because setting the width of the container to calc(33vh - 15px) didn't work.
May be in a near future that will be easier.
I don't know what is the browser support for this, I tested it only in Chrome.
Note : 15px is the dimension of the header (45px) divided by the number of squares.
Well I took a shot at this...
I changed your sizes up on your css
here is the link to the fiddle.
http://jsfiddle.net/D7RSP/2/
#header {
height: 20%;
width: 100%;
background: #ffb8c4;
}
#mainView {
flex: 1;
width: 69%;
height: 100%;
float: left;
background: green;
}
.square {
flex: 1;
-webkit-flex: 1;
width: 30%;
border: 1px solid white;
background: green;
height: 25%;
float:right;
}