Centering grid child regardless of siblings width - html

I have a CSS grid container with 3 children, all with a different width. I want the 2 side children to be at the 2 sides of the container and the middle child to be at the center.
I tried setting the first one to justify-self: start, the middle one to justify-self: center;, and the last one to justify-self: end;, but it doesn't get centered, it just divides the space evenly.
.container {
display: grid;
grid-template-columns: auto auto auto;
height: 100px;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
justify-self: center;
background-color: green;
width: 70px;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>
Am I'm missing something? Is this not possible?

You could use the grid for the outer elements and center the middle one using absolute position and transforms like so:
.container {
display: grid;
grid-template-columns: auto auto;
height: 100px;
position:relative;
width:100%;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
background-color: green;
width: 70px;
position:absolute;
left: 50%;
transform: translateX(-50%);
height:100%;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>
But be aware that elements could overlap using this method.

Use 1fr instead of auto since you are explicitly defining the width of your elements
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
height: 100px;
/* The center */
padding-bottom: 5px;
background: linear-gradient(black, black) bottom center/5px 5px no-repeat;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
justify-self: center;
background-color: green;
width: 70px;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>

Related

How to align 2 by 2 divs around a centre? E.g. internal corners should be in parent centre

looking for some help with html and css (more with css) I want to make that work as a template to be use with a parent div in my app, but having problems to center 4 divs in a centre of sub parent. I need they align in central point by they inner corners.
E.g. corner of 1st right bottom, 2nd - left bottom, 3rd - right top, 4th - left top should be centered.
1-2-3-4 div size may vary
I have this https://codepen.io/Kvark/pen/zYzEgWo (updated) to explain:
But don't know how to make cantering stuff I need,
now its look like as that:
But I want it to be look like as that:
any advice or help on that?
You can position each of the squares within the right hand box by making the right hand box have a position (I've given it relative) and the colored boxes positioned in relation to that.
As the boxes have differing dimensions, which may not be overtly known at run time, this snippet uses a translation of each to get them in the right positions as a translate with a % uses the relevant dimension of the item itself (not its parent) if you use % units.
html,
body,
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
div .item {
display: flex;
justify-content: center;
align-items: center;
border: 2px dashed #f69c55;
}
#container {
height: 50%;
}
.column {
float: left;
padding: 10px;
height: 300px;
}
.left {
width: 50%;
}
.right {
width: 45%;
}
.column.right.square {
position: relative;
}
#chart_1 {
height: 100px;
width: 100px;
}
#chart_2 {
height: 60px;
width: 60px;
}
#chart_3 {
height: 150px;
width: 120px;
}
#chart_4 {
height: 50px;
width: 180px;
}
.square {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.square::after {
content: '';
width: 100%;
}
.square .item:nth-child(n + 3) {
order: 1;
}
<div class="row">
<div class="column left" style="background-color:#aaa;">
<h2>tbd</h2>
<div id="container"></div>
</div>
<div class="column right square" style="background-color:#bbb;">
<div class="item" id="chart_1" style="background-color:red;position: absolute; left: 50%; top: 50%;transform: translate(-100%, -100%);">1</div>
<div class="item" id="chart_2" style="background-color:blue;position: absolute; left: 50%; top: 50%;transform: translate(0, -100%);">2</div>
<div class="item" id="chart_3" style="background-color:green;position: absolute; left: 50%; top: 50%;transform: translate(-100%, 0%);">3</div>
<div class="item" id="chart_4" style="background-color:yellow;position: absolute; left: 50%; top: 50%;transform: translate(0, 0);">4</div>
</div>
</div>
If I understand your question correctly you want the boxes to be tightly placed together, and then you want the "box of boxes" to be placed in the middle of their parent?
If so, here is one way to solve it: using an additional wrapping div to group the boxes together, they can then be placed together.
.item {
height: 50px;
width: 50px;
display: flex;
justify-content: center;
align-items: center;
border: 2px dashed #f69c55;
}
/* This puts the boxes in two columns. */
.boxwrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
.wrapper {
background-color: slategray;
height: 80vh;
/* This puts the boxes in the middle, and restricts the width and height
of the boxwrapper, so that the boxes end up close together. */
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="boxwrapper">
<div class="item" style="background-color:tomato;">1</div>
<div class="item" style="background-color:royalblue;">2</div>
<div class="item" style="background-color:forestgreen;">3</div>
<div class="item" style="background-color:gold;">4</div>
</div>
</div>
You need Grid to make a template here. Try this
.container {
display: grid;
grid-template-columns: auto auto;
grid-row-gap: 20px;
justify-content: center;
}
.item {
width: 50px;
height: 50px;
display: grid;
justify-content: center;
align-content: center;
background-color: red;
border: 1px solid black;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
Working example:
.container {
display: grid;
grid-template-columns: auto auto;
justify-content: center;
}
.item {
width: 50px;
height: 50px;
display: grid;
justify-content: center;
align-content: center;
background-color: red;
border: 1px solid black;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>

Is it possible to use flexbox order in two different sections?

I have a page designed like this:
main {
display: flex;
}
div {
width: 50px;
height: 50px;
margin: 2px;
text-align: center;
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<main>
<section>
<div class="div1">A</div>
<div class="div1">B</div>
<div class="div1">C</div>
</section>
<section>
<div class="div2">D</div>
<div class="div2">E</div>
<div class="div2">F</div>
</section>
</main>
I am applying responsiveness. I would like to know if it is possible to use only css to organize the divs this:
The only way I see to achieve the layout with a <section> tag present separating each div1 and div2 would be to use positioning each child elements left and top positions relative to the parent. It is very static and likely has a high potential of breaking with content and scrolling, etc...
Not recommended... see the hidden snippit below to see that working
.main section {
position: relative;
}
.one {
position: absolute;
left: 0;
top: 0;
}
.four {
position: absolute;
left: 55px;
top: 0;
}
.two {
position: absolute;
left: 0;
top: 55px;
}
.three {
position: absolute;
left: 55px;
top: 55px;
}
.five {
position: absolute;
left: 0;
top: 110px;
width: 210%;
overflow: auto;
}
.six {
position: absolute;
left: 0;
top: 165px;
width: 210%;
overflow: auto;
}
div {
width: 50px;
height: 50px;
margin: 2px;
text-align: center;
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<div class="main">
<section>
<div class="div1 one">1</div>
<div class="div1 two">2</div>
<div class="div1 three">3</div>
</section>
<section>
<div class="div2 four">4</div>
<div class="div2 five">5</div>
<div class="div2 six">6</div>
</section>
</div>
A more cohesive approach would be to get rid of the <section> tags and use a grid layout...
You still have the classes div1 and div2 for alternate styling. Using the grid layout you can create a grid-template-area using the grid-area on individual class names for each element.
While you still have your child elements laid out incrementally one, two, three, four, etc... You can move a child element anywhere in the grid pattern using the grid-template-area calling on the elements grid-area value.
In the following example, each div has a class representing its position in the original layout, one, two, three, etc...
Note the column and row fr units... very literal in its approach. Visualize two columns each separated equally per column, then four rows, each separated equally per row, then we add the elements with the grid-template-area...
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-area:
"one four"
"two three"
"five five"
"six six";
}
html {
--width: 100%;
--height: 100%;
}
#main {
display: flex;
justify-content: center;
}
div {
display: flex;
align-items: center;
justify-content: center;
}
.grid-container {
height: 400px;
width: 200px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-gap: 2px 2px;
grid-template-areas: "one four" "two three" "five five" "six six";
}
.one {
grid-area: one;
width: var(--width);
height: var(--height);
}
.two {
grid-area: two;
width: var(--width);
height: var(--height);
}
.three {
grid-area: three;
width: var(--width);
height: var(--height);
}
.four {
grid-area: four;
width: var(--width);
height: var(--height);
}
.five {
grid-area: five;
width: var(--width);
height: var(--height);
}
.six {
grid-area: six;
width: var(--width);
height: var(--height);
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<div id="main">
<div class="grid-container">
<div class="div1 one box">A</div>
<div class="div1 two box">B</div>
<div class="div1 three box">C</div>
<div class="div2 four box">D</div>
<div class="div2 five box">E</div>
<div class="div2 six box">F</div>
</div>
</div>
yes you could by using orders like this .div1 {order: __}

Flex last row to take available vertical space [duplicate]

This question already has answers here:
Stretch columns in two columns layout with shared header using flexbox
(2 answers)
Closed 4 years ago.
I have this layout, where a row wrap flex container has a first child with 100% width and 2 more children on the second row. The container has a fixed height and the first child (Filters block below) is collapsible (i.e. has 2 possibles values for height).
I would like the blocks on the last line to take all available height in all cases (filters block collapsed or expanded), but I can't find a solution.
I've tried various combinations of height, align-items/align-self: stretch, to no avail. Setting the pdt/list blocks height to 100% makes them effectively 100% of parent container, so they overflow due to the filters.
I know I could achieve it by making the first container flex column and throw in a second one with flex row,but I'd like to keep the current markup if possible. Any idea?
JSfiddle: https://jsfiddle.net/Lp4j6cfw/34/
HTML
<div id="lp-tag">
<div id="header">HEADER</div>
<div id="lp-ctnr">
<div id="filters" onclick="toggle()">FILTERS</div>
<div id="pdt">PDT</div>
<div id="list">LIST</div>
</div>
CSS
#lp-tag{
display: flex;
flex-flow: column nowrap;
width: 350px;
margin: auto;
border: 1px solid red;
height: 250px;
}
#header{
background: lightblue;
height: 80px;
}
#lp-ctnr{
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-content: flex-start;
align-items: stretch;
border: 1px solid green;
flex: 1;
}
#filters{
width: 100%;
background: lightgreen;
height: 45px;
}
.close{
height: 20px !important;
}
#pdt, #list {
flex: 1;
border: 1px solid blue;
text-align: center;
align-self: stretch;
}
#pdt{
background: yellow;
}
#list{
background: pink;
}
If you are open to alternative layout methods, I'd recommend CSS-Grid
.lp-tag {
width: 250px;
margin: 1em auto;
border: 1px solid red;
height: 250px;
display: inline-grid;
grid-template-rows: auto 1fr;
}
.header {
background: lightblue;
height: 80px;
}
.header.small {
height: 40px;
}
.lp-ctnr {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: repeat(2, 1fr);
border: 1px solid green;
flex: 1;
}
.filters {
grid-column: 1 / span 2;
background: lightgreen;
height: 45px;
}
.filters.large {
height: 80px;
}
.pdt,
.list {
border: 1px solid blue;
text-align: center;
}
.pdt {
background: yellow;
}
.list {
background: pink;
}
<div class="lp-tag">
<div class="header">HEADER</div>
<div class="lp-ctnr">
<div class="filters" onclick="toggle()">FILTERS</div>
<div class="pdt">PDT</div>
<div class="list">LIST</div>
</div>
</div>
<div class="lp-tag">
<div class="header small">HEADER</div>
<div class="lp-ctnr">
<div class="filters large" onclick="toggle()">FILTERS</div>
<div class="pdt">PDT</div>
<div class="list">LIST</div>
</div>
</div>
This is the only solution I can see without an intermediary container. https://jsfiddle.net/5j38ouvs/
However, I would probably do like Nandita and add a surrounding container like here: https://jsfiddle.net/8md4oyLx/
CSS
#lp-ctnr{
display: flex;
flex-direction: column;
border: 1px solid green;
height: 550px;
width: 350px;
margin: auto;
}
#filters{
width: 100%;
background: lightgreen;
}
.close{
height: 20px !important;
}
#pdt{
flex-grow: 1;
background: yellow;
}
#list{
flex-grow: 1;
background: pink;
}
.list-container {
flex-grow: 1;
border: 1px solid blue;
text-align: center;
display: flex;
flex-direction: row;
}
HTML
<div id="lp-ctnr">
<div id="filters" onclick="toggle()">FILTERS</div>
<div class="list-container">
<div id="pdt">PDT</div>
<div id="list">LIST</div>
</div>
</div>

How do I send 1 item to the end while the rest are centered in a flexbox container [duplicate]

This question already has answers here:
Center one and right/left align other flexbox element
(11 answers)
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 2 years ago.
Using a flexbox container, how can I have the first child centered and the second child at the end? I tried the following but it didn't work:
.flexbox {
display: flex;
justify-content: center;
height: 200px;
}
.box1 {
width: 100px;
}
.box2 {
width: 100px;
justify-self: end; /* does nothing */
}
div{ border: 1px solid black; } /* to help see the divs */
<div class="flexbox">
<div class="box1"></div>
<div class="box2"></div>
</div>
Justify-self only works with grid not flexbox
.flexbox {
display: grid;
grid-template-columns: auto auto;
height: 200px;
width: 500px;
background: orange;
}
.box1 {
width: 100px;
height: 200px;
background: red;
justify-self: end;
}
.box2 {
width: 100px;
justify-self: end;
height: 200px;
background: blue;
}
<div class="flexbox">
<div class="box1"></div>
<div class="box2"></div>
</div>
For your problem though, you can solve it using absolute positioning
.flexbox {
position: relative;
display: flex;
justify-content: center;
height: 200px;
width: 500px;
background: orange;
}
.box1 {
width: 100px;
height: 200px;
background: red;
}
.box2 {
position: absolute;
width: 100px;
height: 200px;
background: blue;
top: 0;
right: 0;
}
<div class="flexbox">
<div class="box1"></div>
<div class="box2"></div>
</div>
Use align-self property. It will work
.box2 {
width: 100px;
align-self: flex-end;
}
You could make a first box that's invisible and then using flex: space-between. Here's how I did it.
.flexbox {
display: flex;
justify-content: space-between;
height: 200px;
}
.flexbox-again {
display: flex;
justify-content: flex-end;
height: 200px;
}
.box0 {
width: 100px;
background: none;
}
.box1 {
width: 100px;
background: blue;
}
.box2 {
background: red;
width: 100px;
justify-self: end; // does nothing
}
<div class="flexbox">
<div class="box0"></div>
<div class="box1"></div>
<div class="box2"></div>
</div>
You can do center the first element using margin-left: 50%; and right align the second element using margin-right: 0; Remove justify-contect: center from your main div.
.flexbox {
display: flex;
height: 200px;
background: yellow;
}
.box1 {
width: 100px;
margin-left: 50%;
background: blue;
}
.box2 {
width: 100px;
margin-left: auto;
margin-right: 0;
background: green;
}
<div class="flexbox">
<div class="box1">fdgdfg</div>
<div class="box2">dfgdg</div>
</div>

Move flex item to far right of next row

I have a flexbox container that has 4 elements: C1,C2,C3,C4.
Currently, it is displayed all in one line.
My goal is to make C4 to display under C3.
Can someone guide me how to accomplish my goal? Thanks in advance.
The following are my code: https://jsfiddle.net/vvqhejt3/3/
.flexbox {
display: flex;
border: 1px solid black;
width: 330px;
}
.content1 {
width: 100px;
margin-right: 10px;
background-color: blue;
height: 50px;
}
.content2 {
width: 100px;
margin-right: 10px;
background-color: yellow;
}
.content3 {
width: 100px;
margin-right: 10px;
background-color: red;
}
.content4 {
width: 100px;
background-color: green;
height: 10px;
}
<div class="flexbox">
<div class="content1">C1</div>
<div class="content2">C2</div>
<div class="content3">C3</div>
<div class="content4">C4</div>
</div>
When you create a flex container (display: flex or display: inline-flex), it comes with several default settings. Among them are:
flex-direction: row - flex items will align horizontally
justify-content: flex-start - flex items will stack at the start of the line
align-items: stretch - flex items will expand to cover the cross-size of the container
flex-wrap: nowrap - flex items are forced to stay in a single line
Note the last setting.
Your four divs are forced to remain in a single line.
You can override this setting with flex-wrap: wrap.
Then you can use an auto margin to space the item to the right.
.flexbox {
display: flex;
flex-wrap: wrap; /* NEW */
border: 1px solid black;
width: 330px;
}
.content1 {
width: 100px;
margin-right: 10px;
background-color: blue;
height: 50px;
}
.content2 {
width: 100px;
margin-right: 10px;
background-color: yellow;
}
.content3 {
width: 100px;
margin-right: 10px;
background-color: red;
}
.content4 {
width: 100px;
background-color: green;
height: 10px;
margin-left: auto; /* NEW */
margin-right: 10px; /* NEW */
}
<div class="flexbox">
<div class="content1"> C1 </div>
<div class="content2"> C2 </div>
<div class="content3"> C3 </div>
<div class="content4"> C4 </div>
</div>
References:
Methods for Aligning Flex Items along the Main Axis
5.2. Flex Line Wrapping: the flex-wrap property
Add flex-flow: row wrap; and justify-content: flex-end; to the container and margin-right: 10px; to div class .content4. Also be sure to correct the class in the last container. Currently it says conten4
Also, here is a link to a simple guide for flexbox.
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
HTML
<div class="flexbox">
<div class="content1"> C1 </div>
<div class="content2"> C2 </div>
<div class="content3"> C3 </div>
<div class="content4"> C4 </div>
</div>
CSS
.flexbox {
display: flex;
border: 1px solid black;
width: 330px;
flex-flow: row wrap;
justify-content: flex-end;
}
.content1 {
width: 100px;
margin-right: 10px;
background-color: blue;
height: 50px;
}
.content2 {
width: 100px;
margin-right: 10px;
background-color: yellow;
}
.content3 {
width: 100px;
margin-right: 10px;
background-color: red;
}
.content4 {
width: 100px;
background-color: green;
height: 10px;
margin-right: 10px;
}