CSS Make last child to dynamically take width which left in parent - html

In my case childs number is returned from server side. In case there are less than 6 childs I need to add dummy child which would take left place of parent.
For example :
1 situation with two childs
2 situation with three childs
fiddle
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>
#container{
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
float: left;
background-color: black;
width: 100px;
height: 100px;
margin-right: 20px;
}
.big-child {
width: 59%!important;
margin-right: 0px!important;
}
How could I achieve this with only CSS and withoud dinamically changing child width with javascript?
UPDATE
Found good website which generates CSS code depending on your boxes needs.

On modern browser you could use flexbox
http://codepen.io/anon/pen/yyMgQL
CSS:
#container {
display: -ms-flexbox; /* IE 10 syntax */
display: flex;
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
background-color: black;
width: 100px;
height: 100px;
margin-right: 20px;
}
#container > div.big-child {
-ms-flex-grow: 1; /* IE 10 syntax */
flex-grow: 1;
margin-right: 0;
}
Further info:
- http://css-tricks.com/snippets/css/a-guide-to-flexbox/
- http://css-tricks.com/old-flexbox-and-new-flexbox/
Browser support: http://caniuse.com/#feat=flexbox
(note that IE10 is supported but it implements an older syntax)

If you want to use floats, you can use overflow:hidden; on the last child to force it to occupy the remaining space.
Alternative solutions could be to use flexbox (depending on your required browser support) or CSS tables.
#container {
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
box-sizing: border-box;
margin-right: 0;
height: 100px;
}
#container > div:not(:last-child) {
margin-right: 10px;
}
.child {
float: left;
background-color: black;
width: 100px;
}
.big-child {
overflow: hidden;
background-color: black;
margin: 0 20px;
}
<h4>Three Blocks</h4>
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>
<h4>Two Blocks</h4>
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>

Related

Inline-block does not line up the same line [duplicate]

This question already has answers here:
How to remove the space between inline/inline-block elements?
(41 answers)
Closed 3 years ago.
I use display: inline-block for div.left - div.right and div.red - div.yellow but none of them are in the same line. I set the width exactly. But it does not work at all.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
margin: 0 auto;
width: 800px;
}
.left, .right, .red, .yellow {
display: inline-block;
vertical-align: top;
}
.left {
width: 250px;
height: 500px;
background: gray
}
.right {
width: 550px;
height: 550px;
background: blue;
}
.red {
background: red;
width: 275px;
height: 200px;
}
.yellow {
background: yellow;
width: 275px;
height: 200px;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="red-yellow">
<div class="red"></div>
<div class="yellow"></div>
</div>
</div>
</div>
Update
If you need to keep inline-block styles, you need the .left and .right divs to add up to 800px. The thing with inline-block is that it will include white space and add it to the width. This is why the wrapping is still occurring. The following image shows the white space that is causing the wrapping.
There are many ways to remove white space and make this fit. One way is to add an HTML comment between the .left and right div, which removes all white space.
<div class="container">
<div class="left"></div><!--
--><div class="right">
<div class="red-yellow">
<div class="red"></div>
<div class="yellow"></div>
</div>
</div>
</div>
Demo
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
margin: 0 auto;
width: 800px;
}
.left, .right, .red, .yellow {
display: inline-block;
vertical-align: top;
}
.left {
width: 250px;
height: 500px;
background: gray
}
.right {
width: 550px;
height: 550px;
background: blue;
}
.red {
background: red;
width: 275px;
height: 200px;
}
.yellow {
background: yellow;
width: 275px;
height: 200px;
}
<div class="container">
<div class="left"></div><!--
--><div class="right">
<div class="red-yellow">
<div class="red"></div>
<div class="yellow"></div>
</div>
</div>
</div>
If you add display: flex to the .container, the immediate children (.left and .right) will align in the same row. The .right div is 50px taller than the .left div because of the explicit width being set (550px for .right, 500px for .left).
Also, you can remove this, as it will no longer have any effect due to the flexbox container.
.left, .right, .red, .yellow {
display: inline-block;
vertical-align: top;
}
Demo
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
margin: 0 auto;
width: 800px;
display: flex;
}
.left {
width: 250px;
height: 500px;
background: gray
}
.right {
width: 550px;
height: 550px;
background: blue;
}
.red {
background: red;
width: 275px;
height: 200px;
}
.yellow {
background: yellow;
width: 275px;
height: 200px;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="red-yellow">
<div class="red"></div>
<div class="yellow"></div>
</div>
</div>
</div>
if use display: inline-block , there will be some space between the elements. In order to overcome that u can use float property so that every element will be aligned in the same line.
If u want to go with display: inline-block property, you have to reduce the width of .red and .yellow,say for example
.red,.yellow{ width: 270px}

How to restrict the dynamic height of the tallest descendant in a flexbox layout?

I have a flexbox wrapper which has two descendants. They both have dynamic height. The second block could be higher than the first one, and I would like to limit the height of the second block to the same as the height of the first one.
.wrapper {
border: 1px solid black;
display: flex;
width: 400px;
margin-bottom: 100px;
}
.left {
background-color: blue;
height: 100px;
width: 200px;
}
.right {
width: 200px;
}
.first {
height: 70px;
background-color: yellow;
}
.second {
height: 70px;
background-color: green;
}
/*desired result */
.fixed-height {
height: 100px;
}
.overflow-value {
overflow: auto;
}
<div class="wrapper">
<div class="left"></div>
<div class="right">
<div class="first"></div>
<div class="second"></div>
</div>
</div>
<div class="wrapper fixed-height">
<div class="left"></div>
<div class="right overflow-value">
<div class="first"></div>
<div class="second"></div>
</div>
</div>
In the provided example, there two wrappers: the first one is the current wrapper, where the wrapper has the height of the tallest child. And the second one is the desired result (I added height to the wrapper, but I couldn't do it in real application)
CodePen Example
If you insist on using flexbox then there is a way to force the container to just take the height of specific child into account - this can be done by forcing the contents of the second item out of layout context with position: absolute. Unfortunately, this requires adding another wrapper inside the .right element. In addition, having the items positioned absolutely inside the second item will mean that the width of the contents will not be propagated to the .right element, but since your example has an explicit width set, then it works in this case. The code with those modifications is below:
.wrapper {
border: 1px solid black;
display: flex;
width: 400px;
margin-bottom: 100px;
}
.left {
background-color: blue;
height: 100px;
width: 200px;
}
.right {
width: 200px;
position: relative;
overflow: auto;
}
.first {
height: 70px;
background-color: yellow;
}
.second {
height: 70px;
background-color: green;
}
.right-wrapper {
position: absolute;
width: 100%;
}
<div class="wrapper">
<div class="left"></div>
<div class="right">
<div class="right-wrapper">
<div class="first"></div>
<div class="second"></div>
</div>
</div>
</div>

Three column layout with an auto-width center column

I'm trying to create 3 columns layout, where structure should be main, left column, right column. The main column is auto-width to fill rest of page.
Unfortunately I cannot change the HTML, which is currently like this:
<div class="wrap">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
Yes: That means I cannot change the order of divs.
I've found some solutions, one of these is by using display: table-cell, but there is issue when using float. Second solutions is layout by using flexbox, it is pretty good solution, but I cannot use it because of IE9 where this CSS style isn't supported.
Just to restate the aim: My need is to have left and right with fixed width, and main will fill rest of free space.
<---250px--><----------------auto-width-------------><---200px--->
<---Left-----><------------------main------------------><---right----->
Have anyone any solutions for this in pure CSS without any JavaScript?
Here you go. A simple CSS solution. Remember you should always clear your floats.
HTML
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
<div class="clear"></div>
CSS
.main, .left, .right {
min-height: 250px;
}
.left {
float: left;
background-color: green;
width: 50px;
}
.right {
float: right;
background-color: blue;
width: 50px;
}
.clear {
clear: both;
}
.main {
background-color: gray;
}
JSFiddle: http://jsfiddle.net/18rvc23q/
You could try floating the sidebars to the left and right respectively, and then applying some padding to the .main div to keep it from overlapping them.
<style>
.left {float: left; width: 250px;}
.right {float: right; width: 200px;}
.main {padding: 0 200px 0 250px;}
</style>
<div class="wrap">
<div class="right">right</div>
<div class="left">left</div>
<div class="main">main</div>
</div>
https://jsfiddle.net/1ofqkLmw/
Note that in this markup I've moved the main div to be the last child of wrap.
Also note that you can just as well use margin instead of padding - if you don't want the border and background to overlap the sidebars, then margin is the way to go.
You could use a mix of left and right margin on .main and then absolute position the .left and .right columns.
HTML
<div class="wrap">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
CSS
.wrap {
position: relative;
}
.main {
border: 1px dashed red;
margin: 0 100px;
min-height: 300px;
}
.left,
.right {
width: 100px;
min-height: 300px;
position: absolute;
top: 0;
}
.left {
left: 0;
background-color: yellow;
}
.right {
right: 0;
background-color: blue;
}
Here's a jsFiddle of it in action: http://jsfiddle.net/1u9gzyh6/
Two ways to do this:
HTML
<div class="wrap">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
The better (but unsupported in IE9-) way
.wrap {
display:flex;
}
.left {
flex-basis:250px;
}
.right {
flex-basis:200px;
}
.main {
flex-grow:1;
}
The somewhat hackier, but supported in IE9 (but not IE8- or certain mobile browsers) way
.wrap {
display:block;
}
.left {
width:250px;
}
.right {
width:200px;
}
.main {
width:calc(100% - 450px);
}
UPDATE: if you wanted to dynamically add / remove columns, just add a few extra classes in your CSS file:
.main.no-left {
width:calc(100% - 200px);
}
.main.no-right {
width:calc(100% - 250px);
}
.main.no-left.no-right {
width:100%;
}
And apply the classes dynamically via JS as needed. Anything else requires a JS solution that actually sets the width as an inline style, or makes use of position:absolute;, which can get real hacky, real fast.
EDITED:
<style>
div {
margin: 0;
padding: 0
}
div.main-wrapper {
overflow: hidden;
width: 700px;
margin: 0 auto;
}
div.left-wrapper {
float: left;
width: 500px;
}
div.left-col {
float: left;
width: 200px; /*change to what value you desire*/
background-color: #5446EB;
height: 400px;
}
div.main-col {
background-color: #DDEB46;
height: 400px;
}
div.right-col {
float: right;
width: 200px; /*change to what value you desire*/
background-color: #EB838D;
height: 400px;
}
</style>
<div class="main-wrapper">
<div class="left-wrapper">
<div class="left-col">
insert content of the left col here
</div>
<div class="main-col">
insert content of the main col here.
</div>
</div>
<div class="right-col">
insert content of the right col here
</div>
</div>
I think this should solve your problem:
.main, .left, .right {
height: 250px;
}
.left {
float: left;
background-color: green;
width: 50px;
position: relative;
margin-left: -300px; // negative width of main
}
.right {
float: left;
background-color: blue;
width: 80px;
margin-left: 50px; // width of left
}
.main {
width: 300px;
background-color: gray;
float: left;
position: relative;
left: 50px; // width of left
}
.wrap:after {
content: "";
clear: both;
}
<div class="wrap">
<div class="main">Main</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>

How do I achieve this equidistant layout without calc?

Is there a "pure" way to achieve this layout where there is fixed content and equal fluid gutters, i.e. a way without using calc?
Fiddle
HTML:
<body>
<div class="content"></div>
<div class="content"></div>
<div class="content"></div>
</body>
CSS:
body {
min-width: 300px;
}
.content {
width: 100px;
height: 100px;
background: blue;
float: left;
margin-left: calc((100% - 300px) / 4);
}
Unfortunately not. You could use a way to "almost" make it like that by using wrapper divs for each .content and style the wrappers to be one third of the body width. Within each wrapper you center the blue boxes. The drawback of that is the distance between the blue boxes is twice as wide as the distance from the outer blue boxes to the body border.
* {
margin: 0;
padding: 0;
border: 0;
}
body {
min-width: 300px;
width: 100%;
}
.content-wrapper {
width: 33.3333%;
text-align: center;
float: left;
}
.content {
width: 100px;
height: 100px;
background: blue;
margin: 0 auto;
}
<body>
<div class="content-wrapper"><div class="content"></div></div>
<div class="content-wrapper"><div class="content"></div></div>
<div class="content-wrapper"><div class="content"></div></div>
</body>
I fiddled around a bit and almost achieved a solution:
Fiddle
HTML:
<body>
<div id="wrap">
<div class="content"></div>
<div class="content"></div>
<div class="content"></div>
<div class="content"></div>
</div>
</body>
CSS:
body {
margin: 0;
}
#wrap {
text-align: justify;
}
.content {
width: 100px;
height: 100px;
background: blue;
display: inline-block;
}
#wrap:before {
content:"";
display: inline-block;
}
#wrap:after {
content:"";
width:100%;
display: inline-block;
}
If multiple pseudo-elements were possible, we could generate an empty inline-block (the same "empty word" as the :before) as :after(1) and the element with width:100% as :after(2).
Well, I couldn't get it to work. But thanks to you Paul for your answer and thanks chipChocolate.py and myfunkyside for the edit!

Having the floating children elements determine parent width

Here is an example
http://jsfiddle.net/BringMeAnother/LwXhE/
// html
<div class="container clearfix">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
// css
.container {
background: red;
padding: 10px;
}
.child {
width: 100px;
height: 100px;
float: left;
}
.child:nth-child(even) {
background: green;
}
.child:nth-child(odd) {
background: blue;
}
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
The container with the red background seem to always stretch to 100%. What I'd like to do is to make its width depend on the floating children, so in this case, 3 times 100px.
The reason I'd like to have this is as follow. In a flexible layout, I have a container that contains several child elements of different sizes. The width and amount of those children can vary. The children always float. The goal is to have the floating children centered. So, if I always have one child element, I'd simply set its margin-right and margin-left to auto. However, there are several children which I wish to put next to each other, but after they have been ordered horizontally, I'd like that row to be centered on the page. I cannot give a fixed width to the container since the amount of children and each of their width are not determined in advance.
I think I might be able to do this with javascript, but I wonder if there is a pure css solution. Thanks
Besides Adsy suggestion (to set the container's position to fixed), you could:
1) Use position absolute on the container:
HTML:
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
CSS:
.container {
background: red;
padding: 10px;
position:absolute;
}
.child {
width: 100px;
height: 100px;
float: left;
}
.child:nth-child(even) {
background: green;
}
.child:nth-child(odd) {
background: blue;
}
http://jsfiddle.net/tKz8b/
2) Set a float on the container, which is good if you need it with relative / static positioning:
HTML:
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="clearfix"></div>
<div>Next</div>
CSS:
.container {
background: red;
padding: 10px;
float: left;
}
.child {
width: 100px;
height: 100px;
float: left;
}
.child:nth-child(even) {
background: green;
}
.child:nth-child(odd) {
background: blue;
}
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
http://jsfiddle.net/LYrWx/1/
By wrapping your container div in another wrapper div, you can centre your red container div, and the red div will only be as wide as its floating children.
HTML
<div class="centered">
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
CSS
.centered {
text-align: center;
}
.container {
background: red;
padding: 10px;
display: inline-block;
}
.child {
width: 100px;
height: 100px;
float: left;
}
.child:nth-child(even) {
background: green;
}
.child:nth-child(odd) {
background: blue;
}
Fiddle: http://jsfiddle.net/SbPRg/
Late to the party here, but all you really need is to add display: inline-block. And to center the .container div, just apply text-align: center to whatever contains it.
JSFiddle: http://jsfiddle.net/LwXhE/24/
Add position:fixed; to container
.container {
background: red;
padding: 10px;
position:fixed;
Fiddle