How can I set a customized distance between child of flexbox - html

<div class="container">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
</div>
.container{
display: flex;
flex-direction: column;
justify-content: space-between;
height: 140;
}
.a{
margin-top: 10px;
height: 17px;
}
.b{
//??
height: 40px;
}
.c{
margin-bottom: 10px;
height: 18px;
}
I have three <div>s a, b and c in the container <div>. I want an element a to be positioned 10px to the top of the container, b to be positioned 50px to the top of the container and c to be positioned 10px to the bottom of the container.
How should I set b's style in order to achieve this? I want to avoid using absolute position if possible since when I tried to use it, somehow the width of b changed. I want to know if there is a way to set a customized distance between children of a flexbox.

Its easier that you adjust the distances here with margins - so you can remove justify-content: space-between.
Add margin-top: 23px to b and margin-top: auto to c. Check the below demo (you can inspect the red lines to verify that the distances are correct):
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-direction: column;
/*justify-content: space-between;*/
height: 140px;
border: 1px solid;
position: relative;
}
.a {
margin-top: 10px;
height: 17px;
}
.b {
height: 40px;
margin-top: 23px; /* ADDED */
}
.c {
margin-bottom: 10px;
height: 18px;
margin-top: auto; /* ADDED */
}
/* STYLING */
.a,.b,.c {
border: 1px solid blue;
background: cadetblue;
}
.a:before,.b:before,.c:before {
content: '';
top: 0;
width: 2px;
position: absolute;
left: 100px;
background: red;
}
.a:before {
height: 10px;
}
.b:before {
height: 50px;
left: 200px;
}
.c:before {
left: 100px;
top: unset;
bottom: 0;
height: 10px;
}
<div class="container">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
</div>

Related

How can I draw a line from my left and right box down to the middle of a text in CSS?

I need your help. I've this three boxes including a text below:
#boxes {
display: flex;
margin-right: -20px;
}
.box {
width: 33.33333%;
margin-right: 20px;
height: 300px;
border-radius: 3px;
border: 1px solid;
}
#footer {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 25px;
}
#headline {
font-size: 16px;
font-weight: 700;
padding-bottom: 12px;
}
<div id="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div id="footer">
<span id="headline">Headline</span>
<span>Small text</span>
</div>
Now I need to somehow connect the boxes together with the text below. For that I want to draw a line down and to the middle text (vertical center) from the left and right box. The problem is that the lines should start at the middle of the left and right boxes and be also centered when the width of the boxes changes - for example when I resize the browser (responsive).
I've first tried using ::before and ::after but I was only able to draw the horizontal lines with total imperfection...
Does anyone has an idea how I can do this?
Go ahead and create a DIV underneath, margin it up, and add borders! You can add a background to the text to section it out.
Big thanks to XLIME for the right hint. This is the answer for my problem:
#boxes {
display: flex;
margin-right: -20px;
}
.box {
width: 33.33333%;
margin-right: 20px;
height: 300px;
border-radius: 3px;
border: 1px solid;
}
#footer {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 25px;
position: relative;
}
#footer-inner {
display: flex;
flex-direction: column;
align-items: center;
background: #ffffff;
z-index: 1;
padding: 0 25px;
}
#headline {
font-size: 16px;
font-weight: 700;
padding-bottom: 12px;
}
#connection-border {
position: absolute;
width: 68%;
height: 98%;
border: 3px solid;
border-top: none;
top: -25px;
}
<div id="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div id="footer">
<div id="footer-inner">
<span id="headline">Headline</span>
<span>Small text</span>
</div>
<div id="connection-border"></div>
</div>
While the "just make another <div> with borders" answer will probably make your life easier, here's an example built with pseudoelements.
In short, it hangs both the vertical and the horizontal lines off of the first and last .box elements, and makes use of both the :before and :after pseudoelements to create those lines.
The last bit of the illusion (lines stopping before the footer text) is accomplished by setting a page-color background on the footer spans, and giving them enough padding to create the appearance of a gap.
In this snippet, I've made the vertical lines green and the horizontal lines blue so it's easier to trace what's happening.
/* Original styling ===================== */
#boxes {
display: flex;
margin-right: -20px;
}
.box {
width: 33.33333%;
margin-right: 20px;
height: 300px;
border-radius: 3px;
border: 1px solid;
}
#footer {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 25px;
}
#headline {
font-size: 16px;
font-weight: 700;
padding-bottom: 12px;
}
/* Additional styling ===================== */
:root {
--footer-gap-height: 48px;
}
.box {
position: relative;
}
/* vertical lines */
.box:first-child:before,
.box:last-child:before {
border-left: 1px solid #0f0; /* green */
content: '';
display: block;
height: var(--footer-gap-height);
left: 50%;
position: absolute;
top: 100%;
transform: translateX(-50%);
width: 0;
}
.box:first-child:after,
.box:last-child:after {
border-bottom: 1px solid #00f; /* blue */
content: '';
position: absolute;
top: calc(100% + var(--footer-gap-height));
width: 100%;
}
.box:first-child:after {
left: 50%;
right: auto;
}
.box:last-child:after {
left: auto;
right: 50%;
}
#footer {
position: relative;
}
#footer span {
background-color: #fff;
display: block;
padding-left: 1em;
padding-right: 1em;
}
<div id="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div id="footer">
<span id="headline">Headline</span>
<span>Small text</span>
</div>

How to position absolute element vertically in the center?

As you can see in the snippet below, I have a .square-container which is positioned absolutely and it contains a square. I'm trying to vertically position the .square-container in the center of the parent div.
.container {
position: relative;
background-color: blue;
}
.square-container {
position: absolute;
top: 0;
right: 0;
height: 30px;
width: 30px;
}
.square {
width: 100%;
height: 100%;
background-color: red;
}
.hello {
padding: 15px;
}
<div class='container'>
<p class='hello'>Hello</p>
<div class="square-container">
<div class='square'></div>
</div>
</div>
For positioning absolute elements in the middle use top: 50%
And then use transform: translateY(-50%); and its centered
.container {
position: relative;
background-color: blue;
}
.square-container {
position: absolute;
right: 10px;
top: 50%;
height: 30px;
width: 30px;
transform: translateY(-50%);
}
.square {
width: 100%;
height: 100%;
background-color: red;
}
.hello {
padding: 15px;
}
<div class='container'>
<p class='hello'>Hello</p>
<div class="square-container">
<div class='square'></div>
</div>
</div>
.container{
display:flex;
align-items:center;
}
You wouldn't need absolute positioning here. If you set the container as a flex wrapper, you won't also need to position it relatively and can get rid of the square-container div as well that currently wraps the div.square element.
To push the square to the right, we could
A) use auto-margins inside the flex layout. So all that our div.square needs, is margin-left: auto, which tells the browser to push it as far as possible from its left siblings.
B) Use justify-content: space-between on our container. This tells the flex container to space out the elements to the sides.
The approaches differ very slightly and don't really matter in this example until we start adding more elements.
An updated example:
A
.container {
display: flex;
align-items: center;
background-color: skyblue;
padding: 15px;
}
.square {
height: 30px;
width: 30px;
margin-left: auto;
background-color: tomato;
}
<div class='container'>
<p class='hello'>Hello</p>
<div class='square'></div>
</div>
B
.container {
display: flex;
align-items: center;
justify-content: space-between;
background-color: skyblue;
padding: 15px;
}
.square {
height: 30px;
width: 30px;
background-color: tomato;
}
<div class='container'>
<p class='hello'>Hello</p>
<div class='square'></div>
</div>

Vertical Divider As Pseudo Element With CSS Grids

I am using CSS Grids. I have a requirement to have a vertical separator between two DIVs. However, the vertical separator needs to be smaller than the height of the actual DIVs, so I don't believe I can use the DIV's border.
.content-container {
display: grid;
width: 100%;
text-align: center;
}
.content {
display: grid;
grid-template-columns: 750px 21px 550px;
margin: auto;
}
.block {
background-color: #fff;
padding-top: 10px;
padding-bottom: 10px;
background-color: #eee;
height: 100px;
}
.divider {
content: '';
margin-top: 20px;
margin-bottom: 20px;
margin-left: 10px;
margin-right: 10px;
border-left: 1px solid black;
}
<div class="content-container">
<div class="content">
<div class="block">test</div>
<div class="divider"></div>
<div class="block">test</div>
</div>
</div>
This works and I'm able to use the margin-top and margin-bottom to control the divider's height.
Ideally, I'd prefer this divider to be a CSS pseudo element but I can't get this working in any way. Is this possible to achieve the desired result or must I stick with an actual element in the HTML code.
Remove the divider element and make content:after your divider by adding grid-column: 2 and grid-row: 1 to this pseudo element (forces it into the middle column).
See demo below:
.content-container {
display: grid;
width: 100%;
text-align: center;
}
.content {
display: grid;
grid-template-columns: 750px 21px 550px;
margin: auto;
}
.block {
background-color: #fff;
padding-top: 10px;
padding-bottom: 10px;
background-color: #eee;
height: 100px;
}
.content:after { /* Now a pseudo element */
content: '';
margin-top: 20px;
margin-bottom: 20px;
margin-left: 10px;
margin-right: 10px;
border-left: 1px solid black;
grid-column: 2; /* ADDED */
grid-row: 1; /* ADDED */
}
<div class="content-container">
<div class="content">
<div class="block">test</div>
<div class="block">test</div>
</div>
</div>
If you want a divider after each block then you can have a grid-gap between each block and put an absolutely positioned pseudo element in that space - see demo below:
.content-container {
display: grid;
width: 100%;
text-align: center;
}
.content {
display: grid;
grid-template-columns: repeat(3, 150px); /* CHANGED */
margin: auto;
grid-gap: 20px; /* ADDED */
}
.block {
background-color: #fff;
padding-top: 10px;
padding-bottom: 10px;
background-color: #eee;
height: 100px;
position: relative; /* ADDED */
}
.block:after { /* ADDED */
content: '';
position: absolute;
border-left: 1px solid black;
right: -10px; /* adjust this */
height: 80%; /* adjust this */
}
.block:last-child:after { /* ADDED */
display: none; /* Hide the divider for the last block */
}
<div class="content-container">
<div class="content">
<div class="block">test</div>
<div class="block">test</div>
<div class="block">test</div>
</div>
</div>
one way to do it
.content-container{
display: grid;
width: 100%;
text-align: center;
}
.content{
display: grid;
grid-template-columns: 75px 55px;
margin:auto;
grid-gap: 20px;
}
.block{
background-color: #fff;
padding-top: 10px;
padding-bottom: 10px;
background-color: #eee;
height: 100px;
position: relative;
}
.block:not(:last-child):after {
position: absolute;
content: '';
left: calc(100% + 9px) ;
color:red;
width: 2px;
height: 80%;
top: 10%;
background-color: black;
}
.divider{
content: '';
margin-top: 20px;
margin-bottom: 20px;
margin-left: 10px;
margin-right: 10px;
border-left:1px solid black;
}
<div class="content-container">
<div class="content">
<div class="block">
test
</div>
<div class="block">
test
</div>
</div>
</div>
The following is an amelioration of #kukkuz's answer.
#kukkuz's answer is not responsive because his right property's value's expressed in px instead of vw. If the final user decreases or increases his browser's width, your vertical separators will move at a different rate than the grid layout's columns are resized. They won't be visually synchronized. Results: your separators would overflow your columns' content.
Solution: use vw instead of px for the right property of #kukkuz.

Creating overlays in CSS

I am trying to create an overlay similar to this image but can't seem to figure it out.
I tried using the absolute positioning but it doesn't seem to work for more than 1 child element.
Any way around this, please?
body, html {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.parent {
border: 2px solid #0074d9;
color: #0074d9;
padding: 20px;
width: 100%;
}
.element {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
}
.element2 {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="parent">
Parent element
<div class="element">Child element</div>
<div class="element2">Second Child element</div>
</div>
</body>
</html>
Here's a brief take on it.
I set the main container to position: relative;, so that any position: absolute; children are positioned relatively to the parent.
I make a child-container to hold all the children, and place it at the bottom (and slightly extending out of) the main container, by doing top: 100%; combined with transform: translateY(-50%);. This also has display: flex; on it, so that its children will align themselves side-by-side.
You can add or remove children as necessary and it will automatically accommodate.
.container {
position: relative;
height: 125px;
background-color: #42b6f4;
}
.container>.main-text {
padding: 20px;
color: white;
font-family: Arial;
font-size: 24px;
}
.child-container {
position: absolute;
display: flex;
justify-content: space-between;
width: 100%;
top: 100%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
.child-container > .child {
flex-grow: 1; /* Children should grow to fill unoccupied space */
padding: 20px;
margin: 20px; /* Amount of space between children */
border: 1px solid #ccc;
background-color: white;
border-radius: 5px;
}
<div class="container">
<div class="main-text">This is some main text</div>
<div class="child-container">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
</div>
Below is a version with borders on all elements, as to explain the concept a bit.
.container {
position: relative;
height: 125px;
border: 2px solid red;
margin-bottom: 60px;
}
.container>.main-text {
padding: 20px;
color: white;
font-family: Arial;
font-size: 24px;
}
.child-container {
position: absolute;
display: flex;
justify-content: space-between;
top: 100%;
left: 50%;
width: 100%;
transform: translateY(-50%) translateX(-50%);
border: 2px dotted green;
}
.child-container > .child {
flex-grow: 1; /* Children should grow to fill unoccupied space */
padding: 20px;
margin: 20px; /* Amount of space between children */
border: 2px dashed blue;
border-radius: 5px;
}
<div class="container">
<div class="main-text">This is some main text</div>
<div class="child-container">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
<span style="color: red;">Parent Container</span><br>
<span style="color: green; margin-left: 15px;">Child Container</span><br>
<span style="color: blue; margin-left: 30px;">Child</span>
Your second child element is on top of the first child element.
1) Add position : relative to parent element
2) You have to use top, bottom, left, right css attributes to place your children elements wherever you want.
body, html {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.parent {
border: 2px solid #0074d9;
color: #0074d9;
padding: 20px;
width: 100%;
position : relative;
}
.element {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
top : 20;
right : 0;
}
.element2 {
border: 1px dotted #000;
background-color: #eee;
padding: 20px;
color: #000;
position: absolute;
width: 40%;
top : 20;
left : 20;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="parent">
Parent element
<div class="element">Child element</div>
<div class="element2">Second Child element</div>
</div>
</body>
</html>

Child elements expanding outside parent element with flex

I have used CSS flex to display two divs side by side which are contained inside a wrapper and I have been trying so that inside #myClippetWrapper is where I set the height, so in the child elements of #myClippetWrapper I can just set height: 100%;.
But as you can see from running the snippet below all of the elements inside #myClippetWrapper go outside of the main section, they are all hanging out of the main content div?
I don't want to use overflow: auto because I do not want a scroll bar there, I just need the child elements of #myClippetWrapper to not be outside of the main section/ div.
main {
margin: 0 auto;
margin-top: 10px;
margin-bottom: 10px;
padding: 8px;
background-color: red;
width: 100%;
max-width: 50%;
height: auto;
}
#myClippetWrapper {
display: flex;
height: 700px;
}
#clippetNav {
padding: 10px;
width: 250px;
height: 100%;
background-color: #222222;
margin-right: 10px;
}
#codeAndNotesWrapper {
display: flex;
width: 100%;
}
#codeAndNotesWrapper>div {
flex-basis: 100%;
height: 100%;
}
#codeView {
padding: 10px;
/*flex: 0 0 40%;*/
height: 100%;
background-color: #222222;
margin-right: 10px;
}
#noteView {
padding: 10px;
/*flex: 1;*/
height: 100%;
background-color: #222222;
}
#codeNotesEditor {
height: 100%;
background-color: #EAEAEA;
}
<main>
<div id="myClippetWrapper">
<div id="clippetNav">
</div>
<div id="codeAndNotesWrapper">
<div id="codeView">
</div>
<div id="noteView">
<div id="codeNotesEditor">
</div>
</div>
</div>
</div>
</main>
In many cases, flexbox eliminates the need to use percentage heights.
An initial setting of a flex container is align-items: stretch. This means that in flex-direction: row (like in your code) flex items will automatically expand the full height of the container.
Alternatively, you can use flex-direction: column and then apply flex: 1 to the children, which can also make a flex item expand the full height of the parent.
main {
max-width: 50%;
margin: 10px auto;
padding: 8px;
background-color: red;
}
#myClippetWrapper {
display: flex;
height: 700px;
}
#clippetNav {
display: flex;
padding: 10px;
width: 250px;
margin-right: 10px;
background-color: #222222;
}
#codeAndNotesWrapper {
display: flex;
width: 100%;
}
#codeAndNotesWrapper>div {
display: flex;
flex-basis: 100%;
}
#codeView {
display: flex;
padding: 10px;
margin-right: 10px;
background-color: #222222;
}
#noteView {
display: flex;
flex-direction: column;
padding: 10px;
background-color: #222222;
}
#codeNotesEditor {
flex: 1;
background-color: #EAEAEA;
}
<main>
<div id="myClippetWrapper">
<div id="clippetNav"></div>
<div id="codeAndNotesWrapper">
<div id="codeView"></div>
<div id="noteView">
<div id="codeNotesEditor"></div>
</div>
</div>
</div>
</main>
jsFiddle
Add
box-sizing: border-box;
To your child elements. This will make the padding show on the inside of the box rather than the outside and will not increase the overall size.
Add the box-sizing property..
* {
box-sizing: border-box;
}
main {
margin: 0 auto;
margin-top: 10px;
margin-bottom: 10px;
padding: 8px;
background-color: red;
width: 100%;
max-width: 50%;
height: auto;
}
#myClippetWrapper {
display: flex;
height: 700px;
}
#clippetNav {
padding: 10px;
float: left;
width: 250px;
height: 100%;
background-color: #222222;
margin-right: 10px;
}
#codeAndNotesWrapper {
display: flex;
width: 100%;
}
#codeAndNotesWrapper>div {
flex-basis: 100%;
height: 100%;
}
#codeView {
padding: 10px;
/*flex: 0 0 40%;*/
height: 100%;
background-color: #222222;
margin-right: 10px;
}
#noteView {
padding: 10px;
/*flex: 1;*/
height: 100%;
background-color: #222222;
}
#codeNotesEditor {
height: 100%;
background-color: #EAEAEA;
}
<main>
<div id="myClippetWrapper">
<div id="clippetNav">
</div>
<div id="codeAndNotesWrapper">
<div id="codeView">
</div>
<div id="noteView">
<div id="codeNotesEditor">
</div>
</div>
</div>
</div>
</main>
A big factor with setting your
display: flex;
Is padding and height can make a nasty couple;
Take this example into account:
display: flex;
height: 100%;
padding-top: 1vh;
This would essentially make your element the pages height, plus 1% of the view height, and of course give you a child element thats taller than its parent element.
This isn't a direct answer to your question, instead one to people looking here for why their child elements may be acting up.