How to positioning elements with CSS flexbox? - css

I have this code:
.top-row,
.bottom-row {
background: red;
padding: 10px;
display: flex;
}
.box1,
.box2,
.box3,
.box4 {
background: green;
padding: 10px;
flex: 1;
}
.header {
background: tan;
padding: 10px;
}
.column1 {
background: pink;
padding: 10px;
}
.column2 {
background: yellow;
padding: 10px;
}
<div class="top-row">
<div class="box1">
<div class="header">
<!-- this field should be left -->
<form>
<input type="text">
</form>
<!-- this button should be left -->
<button class="add">+</button>
<!-- this button should be right -->
<button class="edit">edit</button>
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
<div class="box2">
<div class="header">
<!-- this button should be left -->
<button class="add">+</button>
<!-- these buttons should be centered -->
<button class="edit">btn1</button>
<button class="edit">btn2</button>
<button class="edit">btn3</button>
<!-- this field should be right -->
<form>
<input type="text">
</form>
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
</div>
<div class="bottom-row">
<div class="box3">
<div class="header">
header
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
<div class="box4">
<div class="header">
header
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
</div>
I have made this codepen:
https://codepen.io/demiurgen/pen/zzygRb
I need help to get the left and right columns to be left and right columns.
They should take up 50% of the space inside their box. Each box is supposed to be a two column layout with a header spanning the top.
Also, how do I position elements like form fields and buttons whit in a flexbox?
Do I need to make another flexbox child for every element I want to position?

You can have nested flex-containers to achieve desired layout. You can use flex: 0 0 50% to make element 50% width and don't allow element to grow and shrink. Note that flex is shorthand for setting flex-grow, flow-shrink and flex-basis.
Also this can be achieved via setting flex: 1 0 0. This is forcing element to grow but don't grow based on content (default value is: flex: 0 1 auto, where auto means take width based on content).
Demo:
* {
box-sizing: border-box; /* new */
}
.top-row,
.bottom-row {
background: red;
padding: 10px;
display: flex;
}
.box1,
.box2,
.box3,
.box4 {
background: green;
padding: 10px;
flex: 1;
display: flex; /* new */
flex-wrap: wrap; /* new */
}
.header {
background: tan;
padding: 10px;
flex: 0 0 100%; /* new */
}
.column1 {
background: pink;
padding: 10px;
flex: 0 0 50%; /* new */
}
.column2 {
background: yellow;
padding: 10px;
flex: 0 0 50%; /* new */
}
/* new */
.header {
display: flex;
flex-wrap: wrap;
}
/* new */
.header form {
width: 100%;
}
/* new */
.header form input[type="text"] {
width: 100%;
}
/* new */
.header .add {
margin-right: auto;
}
<div class="top-row">
<div class="box1">
<div class="header">
<!-- this field should be left -->
<form>
<input type="text">
</form>
<!-- this button should be left -->
<button class="add">+</button>
<!-- this button should be right -->
<button class="edit">edit</button>
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
<div class="box2">
<div class="header">
<!-- this button should be left -->
<button class="add">+</button>
<!-- these buttons should be centered -->
<button class="edit">btn1</button>
<button class="edit">btn2</button>
<button class="edit">btn3</button>
<!-- this field should be right -->
<form>
<input type="text">
</form>
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
</div>
<div class="bottom-row">
<div class="box3">
<div class="header">
header
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
<div class="box4">
<div class="header">
header
</div>
<div class="column1">
left column
</div>
<div class="column2">
right column
</div>
</div>
</div>

I think you will need to use a column container for flex to work correctly.
Like this: https://codepen.io/anon/pen/OgdLLO
.col-container {
display: flex;
}

Related

Push the right aligned element down when the first left element is too long

I'm trying to achieve this, where brown gets pushed down when pink is too long, and pink is dynamically sized based on its text content.
I was only able to achieve this using javascript and two templates, if pink length is over X use second template, but I'm wondering if there's a way to achieve this using CSS only?
I tried meddling with grid auto-fill/auto-fit with minmax, float, flex with wrap, but I couldn't get to the desired result with these.
.parent {
width: 170px;
}
.flex {
display: flex;
}
div {
outline: 2px solid rgba(255, 0,0, 0.3);
}
<div>
<p>scenario A</p>
<div class="parent flex">
<div>
<div class="one">A short title</div>
<div class="three">Some text here</div>
<div class="three">some more text</div>
</div>
<div>
<button>A button</button>
</div>
</div>
</div>
<div>
<p>scenario B</p>
<div class="parent">
<div class="one">Testing a very long title</div>
<div class="flex">
<div>
<div class="three">Some text here</div>
<div class="three">some more text</div>
</div>
<div>
<button>A button</button>
</div>
</div>
</div>
</div>
<p>can a component achieve both a and b with only css?
I found a solution, it requires having fixed height in the first row, and the right side button will basically overflow when needed.
Will wait a bit before accepting my own solution in case someone came with a better one.
.container {
width: 300px;
display: flex;
gap: 10px;
padding: 16px;
font-size: 14px;
font-family: Arial;
}
.text {
flex: 1;
min-width: 0;
}
.first-row {
height: 22px;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
}
.image {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #444;
}
.title {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
<h2>Long title</h2>
<div class="container">
<div class="image"></div>
<div class="text">
<div class="first-row">
<div class="title">Test title test title test title</div>
<button>Visit store</button>
</div>
<div class="three">in the stores</div>
<div class="three">sponsored</div>
</div>
</div>
<h2>Short title</h2>
<div class="container">
<div class="image"></div>
<div class="text">
<div class="first-row">
<div class="title">Short title</div>
<button>Visit place</button>
</div>
<div class="three">in the stores</div>
<div class="three">sponsored</div>
</div>
</div>
<h2>Very long title</h2>
<div class="container">
<div class="image"></div>
<div class="text">
<div class="first-row">
<div class="title">Test title test titleTest title test titleTest title test title</div>
<button>Visit place</button>
</div>
<div class="three">in the stores</div>
<div class="three">sponsored</div>
</div>
</div>

How set dynamic margin?

i have one div and three child div, check out the code below
<div class="parent">
<div class="child">
<icontag />
<texttag />
</div>
<div class="child">
<icontag />
<texttag />
</div>
<div class="child">
<icontag />
<texttag />
</div>
</div>
each child tag composed of icontag and texttag and text tag is of dynamic height.
but, each icon tag margin must be same, even if text tag height is different.
for more explanation, refer to the picture.
as the above picture, the last text is multiline. so, last child tag height is diffent from other tags.
how can I do that?
Here is an example with grid and flexbox.
Try this, it might fit your needs
.child {
display: flex;
align-items: center;
}
.parent {
display: grid;
grid-template-rows: 33% 33% 33%;
}
.child .icon {
border-radius: 50%;
border: 1px solid blue;
height: 40px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20px;
}
.child p {
max-width: 100px;
}
.wrapper {
display: flex;
align-items: center;
}
.same {
margin-right: 30px;
}
<div class="wrapper">
<p class="same">Same height</p>
<div class="parent">
<div class="child">
<div class="icon">1</div>
<p>Bla bla bla bla bla bla bla bal dsfafda af afas fa faf af</p>
</div>
<div class="child">
<div class="icon">1</div>
<p>Bla bla bla</p>
</div>
<div class="child">
<div class="icon">1</div>
<p>Bla bla bla bla bla bla bla bal dsfafda af afas fa faf af</p>
</div>
</div>
</div>
Try adding max-height to all child div..
.child {
--
--
max-height: 300px; // give max height as per your design
overflow-y: auto;
}
You can use display: flex on child items and align-items: center to vertically center the content.
Then use padding property (or margin could work as well) to have some space between .child items as in the following snippet.
.child{
display: flex;
flex-direction: row;
align-items: center;
width: 500px;
padding: 15px 0;
}
.icon{
width: 30px;
height: 30px;
border-radius: 100%;
border: 2px solid #0000ff;
display: flex;
align-items:center;
justify-content: center;
margin-right: 15px;
}
.text{
flex: 1;
}
.child.third .icon{
width: 50px;
height: 50px;
}
<div class="parent">
<div class="child first">
<div class="icon">1</div>
<div class="text">Foo bar baz</div>
</div>
<div class="child second">
<div class="icon">2</div>
<div class="text">Foo bar baz</div>
</div>
<div class="child third">
<div class="icon">3</div>
<div class="text">Foo bar baz<br/>Foo bar baz</div>
</div>
<div class="child fourth">
<div class="icon">4</div>
<div class="text">Foo bar baz<br/>Foo bar baz</div>
</div>
</div>
But note that, if the texts are much longer than the icons, it could break the layout and you need to give static height to child items. But this way texts may overlap.
Try this :
<div class="parent">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 child">
<icontag />
<texttag />
</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 child">
<icontag />
<texttag />
</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 child">
<icontag />
<texttag />
</div>
</div>
You can set padding for child class.
padding: 10px;

Make a vertical bar reaching both the top and bottom of a page

I'm creating a vertical bar to split the sidebar and the main-section.
I employed the grid bootstrap 3:
<div class="container">
<div class="row">
<aside class="col-md-2 left-sidebar">
<ul>
<li>Javascript</li>
<li>jQuery</li>
<li>Bootstrap</li>
</ul>
</aside>
<div class="col-md-10 main-section">
....
</div>
<div>
the css code:
.left-sidebar {
padding-top: 50px;
border-right: 1px solid red;
}
I found the official docs of Bootstrap 4.1 has a nicely structured left-side.
How to produce a vertical var reaching both the top and bottom of the page?
Use the below snippet to get the equal height columns to your bootstrap grid.
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.row-eq-height > [class*='col-'] {
display: flex;
flex-direction: column;
}
.left-sidebar {
box-shadow: 1px 0 0 0 #ccc;
background: #eee;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet"/>
<div class="row row-eq-height">
<div class="col-sm-2 left-sidebar">
some content
</div>
<div class="col-sm-10" style="height: 100vh">
some more content
</div>
</div>
Boostrap4 main difference from BS3 is that it's using flexbox instead of floats. And with flexbox you can make columns inside a row have equal height. So you could make 2 columns and if the main-column will have for ex 1000px height, the left column will have that height as well.
See snippet
.row {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.main-section {
height:200vh;
background: blue;
}
.left-sidebar {
border-right: 2px solid red;
background:green;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-md-2 col-sm-2 col-xs-2 left-sidebar">
<ul>
<li>Javascript</li>
<li>jQuery</li>
<li>Bootstrap</li>
</ul>
</div>
<div class="col-md-10 col-sm-10 col-xs-10 main-section">
....
</div>
</div>
</div>
IF you want to have the same effect as the one from the BS4 docs, then the left column has the height of the screen. You can do that with viewport units. And it also has position:sticky.
See below ( for some reason in the code snippet position:sticky doesn't work, check it here - > jsfiddle sticky )
.row {
display: flex;
width: 100%;
}
.main-section {
height:200vh;
background: blue;
}
.left-sidebar {
border-right: 2px solid red;
height:100vh;
position:sticky;
top:0;
background:green;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-md-2 col-sm-2 col-xs-2 left-sidebar">
<ul>
<li>Javascript</li>
<li>jQuery</li>
<li>Bootstrap</li>
</ul>
</div>
<div class="col-md-10 col-sm-10 col-xs-10 main-section">
....
</div>
</div>
</div>

Boostrap 3 css vertical align two divs one top one bottom

Issue: So vertical alignment issue is I have two divs in the last column and I'm trying to get one to stay at top and one to stay at the bottom regardless of how the central column grows. I can work this out by using fixed heights but that's no good in this case.
Here is my code example : JS Fiddle
HTML:
<div class="row" class="property-bundle"><!-- (x) number of these -->
<div class="col-xs-11 wrapper">
<div class="row">
<div class="col-xs-2 pull-left vendor">
<img src="http://placehold.it/100x100" />
</div>
<div class="col-xs-8 properties-list">
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 1</p></div>
</div>
<div class="row"><hr/></div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 2</p></div>
</div>
<div class="row"><hr/></div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10"><p>Flat 3</p></div>
</div>
</div>
<div class="col-xs-2 costs"><!-- costs column -->
<div class="row total">
<h3 class="text-right">TOTAL: £1,2M</h3><!--stay at top-->
</div>
<div class="row" class="fees"> <!--stay at bottom-->
<div class="col-xs-12">
<hr/>
<p class="text-right">+ Materials £300K</p>
<p class="text-right">+ Build £100K</p>
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.wrapper {border: 1px solid black; padding: 10px; margin: 15px;}
.vendor {min-width: 120px;}
.properties-list {background-color: aquamarine}
.costs {vertical-align: top; min-width: 150px; vertical-align: center}
.fees {vertical-align: bottom; }
h3 {font-weight: 400}
h4 {color: green}
.total { margin-right: 0px; }
Hi you can try using flexbox
I just change your html like this:
<div class="col-xs-2 costs">
<!--stay at top-->
<div class="total">
<h3 class="text-right">TOTAL: £1,2M</h3>
</div>
<hr/>
<div class="materials">
<p class="text-right">+ Materials £300K</p>
<p class="text-right">+ Build £100K</p>
</div>
</div>
</div>
Then I add on costs div display:flex;and on total div flex-grow: 1 This flex-grow will push materials on bottom of div.
You just need to add on body, html, row and costs div height:100%
Here is css:
.costs {
vertical-align: center;
display: flex;
flex-direction: column;
height: 100%;
}
.total {
flex-grow: 1;
}
You can see example on this link: https://jsfiddle.net/3L5Lbwhn/9/
Ok I simplified this a bit, but essentially flex did what I needed so many thanks to Edin Puzic for putting me on the right lines! It also allowed me to fix the 1st and last col width and make the middle one dynamic horiontally too.
JsFiddle
<div class="row-flex">
<div class="col-flex-1">
<img src="http://placehold.it/100x100" />
</div>
<div class="col-flex-2">
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 1</p>
</div>
</div>
<div class="row">
<hr/>
</div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 2</p>
</div>
</div>
<div class="row">
<hr/>
</div>
<div class="row" class="property-line">
<div class="col-xs-2"><img src="http://placehold.it/80x140" /></div>
<div class="col-xs-10">
<p>Flat 3</p>
</div>
</div>
</div>
<div class="col-flex-3">
<div class="pos-top">
<div class="row right-text">
TOP right
</div>
</div>
<div class="pos-bottom">
<div class="row right-text">
<p>
BOTTOM right
</p>
</div>
</div>
</div>
</div>
CSS
.row-flex {
height: auto;
display: flex;
flex-flow: row column;
}
.col-flex-1 {
min-width: 200px;
border-left: 1px #ccc solid;
flex: 0 0;
}
.col-flex-2 {
width: 80%;
border-left: 1px #ccc solid;
flex: 1 1;
}
.col-flex-3 {
min-width: 200px;
border-left: 1px #ccc solid;
flex: 0 0;
}
.flex-container {
display: -webkit-flex;
display: flex;
width: 100%;
height: 100%;
background-color: lightgrey;
}
.pos-top {
display: -webkit-flex;
display: flex;
height: 50%;
width: 100%;
-webkit-align-items: flex-start;
align-items: flex-start;
background-color: yellow;
}
.pos-bottom {
display: -webkit-flex;
display: flex;
height: 50%;
width: 100%;
-webkit-align-items: flex-end;
align-items: flex-end;
background-color: green;
}
.right-text {
text-align: right;
width: 100%;
}

How do I float these fieldsets?

I am working with an existing system, and am trying to modify the CSS in order to arrange the three columns correctly.
What css changes do I need to make in order to display the third column correctly?
View in this JSFiddle
CSS
.test .repeater {
border: none;
margin: 0;
}
.test .indent1 .wizard-parentcontrol .controlkl {
width: 33%;
float: left;
display: block;
}
.test .wizard-controls .indent1 .control:first-child {
margin-top: 17px;
}
.test .indent1 .wizard-parentcontrol .popupbrowser {
width: 30%;
float: left;
border: 1px solid red;
display: block;
}
HTML
<div class="test wizard-parentcontrol">
<div>
<div>
<fieldset></fieldset>
</div>
<div>
<div>
<fieldset>
<div>
<div class="repeater indent1">
<div class="wizard-parentcontrol">
<div>
<div>
<div class="controlkl">Column 1</div>
</div>
</div>
<div>
<div>
<fieldset>
<div id="p0t2c4dpopupbrowserControl" class="popupbrowser">Column 2</div>
</fieldset>
</div>
<div>
<div class="">
<p class="ctrlinvalidmessage"></p>
<fieldset>
<div id="p0t2c5dpopupbrowserControl" class="popupbrowser">Column 3</div>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</fieldset>
</div>
</div>
</div>
</div>
Check If you can do the following changes.
I just added class
.wizard-parentcontrol div
{
float:left;
}
and removed the hardcoded width's of 33% and 30% from your code.
Check the demo

Resources