Boostrap 3 css vertical align two divs one top one bottom - css

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%;
}

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>

I want a div of specific height to grow in width as necessary to accommodate text

As shown in the example bellow, I want a div of specific height to grow in width only as much as necessary to accommodate it's text, but I can't do it
I want it to look like this
body{
overflow-x: scroll;
}
.container{
display: flex;
flex-direction: row;
width: max-content;
}
.item{
width: min-content ;
max-height: 3em;
border: 1px solid red;
}
<body>
<div class="container" >
<div class="item"> sid jkodasjkadf kadsf kas</div>
<div class="item"> salkf hjahsadkjhfgadsakjsl</div>
<div class="item"> saf nasd kmfgdn skjdsj</div>
<div class="item"> sjfn sdnf sdmfosdj md faikmoa fia</div>
<div class="item"> siiojasd oiasdi </div>
<div class="item"> alksj fksdafja</div>
<div class="item"> sid jkodas jkadf kadsf kas</div>
<div class="item"> salkf hjahsadkjhfga dsakjsl</div>
<div class="item"> saf nasd kmfgdn skjdsj</div>
<div class="item"> sjfn sdnf sdmfosdj md faikmoa fia</div>
<div class="item"> siiojasd oiasdi </div>
<div class="item"> alksj fksdafja</div>
</div>
</body>
try this,
.container{
display:grid;
grid-template-columns:repeat(3,1fr);
}
.item{
max-height: 3em;
border: 4px solid red;
padding:1rem;
}

remove margin bottom from the last line in wrapped elements

How can I keep the margin-bottom only for the elements that are not in the last line ?
.container {
display: flex;
flex-flow: row wrap;
background: green;
justify-content: space-between;
}
.block {
height: 60px;
max-width: calc((100% - (12px * 2)) / 3);
flex-basis: calc((100% - (12px * 2)) / 3);
background: orange;
box-shadow: inset 0 0 0 3px black;
margin-bottom: 12px;
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
Thanks in advance.
This is what you are looking for:
.container .block:nth-last-child(-n+3){
margin-bottom: 0px;
}
for flex and grid, you can use the gap propertie to avoid playing with margins:
https://developer.mozilla.org/en-US/docs/Web/CSS/gap
The gap CSS property sets the gaps (gutters) between rows and columns. It is a shorthand for row-gap and column-gap.
Applies to multi-column elements, flex containers, grid containers
see https://www.caniuse.com/?search=gap for support
to set 3 elements on a line, give a min-width bigger than 25% and set them to grow via flex-grow. for the demo i used 26%, should be small enough to leave room for the gaps .
Demo of your code witout margins but still a gap in between elements
.container {
display: flex;
flex-flow: row wrap;
background: green;
gap: 12px;
/* see https://www.caniuse.com/?search=gap for support */
}
.block {
height: 60px;
flex: 1 1 0; /* or flex:1; */
/* to stretch them at the most and even their sizes*/
min-width: 26%;
/* it cannot be more than 3 on a row */
background: orange;
box-shadow: inset 0 0 0 3px black;
padding:5px; /* padding is fine */
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">A single line
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">a second and last line
</div>
<div class="block">
</div>
<div class="block">
</div>
</div>
<hr>
<div class="container">
<div class="block">2 blocks , is that okay ?
</div>
<div class="block">
</div>
</div>
You can also use CSS grid:
.container {
display: grid;
grid-template-columns:repeat(3,1fr);
grid-gap:12px;
background: green;
}
.block {
height: 60px;
background: orange;
box-shadow: inset 0 0 0 3px black;
}
<div class="container">
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</div>
<div class="block">
</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;

Nested, centered, CSS grid column appears off the screen in the negative X axis, even with "overflow-x: scroll"

The requirement here is to display a series of nested, centered CSS grid items. We're rendering something like a hierarchical tree, with the head node on top, then second level nodes, third level nodes, and so on.
The problem is that later levels run off the div in the negative and positive X-axis directions.
Setting overflow-x: scroll solves the problem only for the positive X-axis direction. That is to say, you can scroll to the right, but not to the left.
The example below is a greatly simplified example of the real problem I'm trying to address. The red element on the 3rd level is off the page in the negative X-axis. You can scroll to the right, but not the left.
What can be done to make it so the entire tree, and all nodes, are able to be scrolled to?
Code follows(Link to JS Fiddle.):
#tree {
overflow-x: scroll;
}
.flex-col {
display: flex;
flex-direction: column;
align-items: center;
}
.grid {
display: grid;
}
.content {
width: 300px;
border-radius: 5px;
background-color: blue;
color: white
}
<div id="tree" class="flex-col">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1;">
<div class="content" style="background-color: red;">** This is off the screen **</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
</div>
</div>
You can create an extra wrapper inside the tree element which will be an inline flexbox container so that it takes as much space as its contents. Use text-align: center to center the tree when there is no scroll - see demo below:
#tree {
overflow-x: auto; /* overflow horizontally here */
text-align: center; /* align horizontally */
}
#tree > .flex-col {
display: inline-flex; /* inline flex container */
text-align: initial; /* reset text align to default left */
}
.flex-col {
display: flex;
flex-direction: column;
align-items: center;
}
.grid {
display: grid;
}
.content {
width: 300px;
border-radius: 5px;
background-color: blue;
color: white
}
<div id="tree">
<div class="flex-col"> <!-- <-- extra wrapper -->
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1;">
<div class="content" style="background-color: red;">** This is off the screen **</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
</div>
</div>
</div>
You need to make sure that the grid elements don't expand wider than their container.
To resolve this, you can set max-width: 100% on .grid:
#tree {
overflow-x: scroll;
}
.flex-col {
display: flex;
flex-direction: column;
align-items: center;
}
.grid {
display: grid;
max-width: 100%;
}
.content {
width: 300px;
border-radius: 5px;
background-color: blue;
color: white
}
<div id="tree" class="flex-col">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1;">
<div class="content" style="background-color: red;">** This is off the screen **</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
<div class="grid">
<div class="flex-col" style="grid-column: 1">
<div class="content">Content</div>
</div>
<div class="flex-col" style="grid-column: 2">
<div class="content">Content</div>
</div>
</div>
</div>
</div>
</div>

Resources