I have been building websites for way too long not to know how to do this. I'm embarrassed to ask. But I must.
I want a way to make any number of child divs within a parent div automatically span to the full width of the parent div.
My criteria for this fix are:
All of the child divs must be the exact same width
The width of the children divs must be responsive/dynamic
I would prefer a fix that doesn't involve sitting there and testing different percentages to find the exact percent width to prevent one of the children being wrapped or hidden (IE "display: if-there-was-an-easy-fix" instead of "width: 29.468749%")
I would love it if the fix would work with fixed margins and dynamic margins (margin: 10px and margin: 5%)
I'm 99% sure I knew the answer to this like a year ago but my current job requires that I work almost exclusively in tables, so I've forgotten how to do anything that isn't clunky and semantically disgusting.
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: 29.468749%;
height: 200px;
display: inline-block;
margin: 0;
padding: 0;
border: none;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="three">
</div>
</div>
use display: flex on parent and flex: 1 on child elements to get flexbox
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
/*display:block;*/
display: flex;
}
.box {
/*width: 29.468749%;*/
/*display:inline-block;
/*margin:0;
padding:0;*/
flex: 1;
height: 200px;
border: none;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="three">
</div>
</div>
The first thing that you'll want to do is remove display: inline-block from the elements, and instead give them a float: left. From here you can get a 'default' full-width alignment by giving your elements a width of about 33.33% each. This would total 99.99%, which is 'close enough' to the full-width (unless you're on a screen of 10000px width). To ensure it's perfect though, you can use the CSS calc() property to ensure that it's exactly one third with width: calc(100% / 3).
This will work for regular elements, but your second box also has margin on it, which also factors into the width calculation in accordance with the box model. Because you're adding a 5% margin on both sides, , you'll want to subtract a total of 10% from the width calculation for this element. This can be done with width: calc((100% / 3) - (5% * 2)).
This gives you three equally wide elements, with one element having additional margins, as can be seen in the following:
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: calc(100% / 3);
height: 200px;
margin: 0;
padding: 0;
border: none;
float: left;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
width: calc((100% / 3) - (5% * 2));
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="one">
</div>
</div>
If you want to change the number of elements, you simply need to update the 3 in each of the width calculations to reflect the number of siblings. This can be made even easier with a CSS variable, meaning you only have to update the CSS in one place:
:root {
--columns: 3;
}
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: calc(100% / var(--columns));
height: 200px;
margin: 0;
padding: 0;
border: none;
float: left;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
width: calc((100% / var(--columns)) - (5% * 2));
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="one">
</div>
</div>
Related
I'm really struggling to create css layout like this:
Top row: fixed size: Ex: 50px;
Content: the biggest square the current width can fit. So width = height for this one. It should respect the bottom row min-height.
Bottom row: take all remaining space available, and with min-height. Ex: 50px.
No scrollbar. The idea is to use the current screen the best way possible for any resolution. No javascript unless it's only possible with js.
Any ideas?
That's the best I've got so far:
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>
css
body {
margin: 0px;
}
.shell {
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.header {
background-color: #0000ff;
height: 50px;
}
.square {
width: 100%;
background-color: #dc143c;
}
.footer {
background-color: #00008b;
height: 100vh;
}
You can use padding to get the aspect ratio:
body {
margin: 0px;
}
.shell {
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.header {
background-color: blue;
height: 50px;
}
.square {
width: 100%;
padding-top: 100%;
background-color: green;
}
.footer {
background-color: red;
height: 100%;
}
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>
Reference here
I think your question was already solved here:
Make a div fill the height of the remaining screen space
Mixed with your try:
body {
margin: 0;
}
.box {
display: flex;
flex-flow: column;
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.box .row.header {
flex: 0 1 50px;
background-color: #0000ff;
}
.box .row.content {
flex: 1 1 auto;
width: 100%;
background-color: #dc143c;
}
.box .row.footer {
flex: 0 1 40px;
background-color: #00008b;
}
<div class="box">
<div class="row header">
</div>
<div class="row content">
</div>
<div class="row footer">
</div>
</div>
Fiddle: https://jsfiddle.net/901s2kdL/
Content: the biggest square the current width can fit. So width =
height for this one. It should respect the bottom row min-height.
If you want the biggest square, the footer height will be fixed and it will be equal to min-height always (and it should be), so it doesn't matter if you will set it's height to 100% or 50px. max-width of square determining really sizes. If you look at this max-width: calc(100vh - 100px), the - 100px part is the real remaining space including header and footer, so if the header height is set to 50px, the footer height is also 50px.
body {
margin: 0px;
}
.shell {
background-color: black;
}
.header {
height: 50px;
background-color: red;
}
.square {
max-width: calc(100vh - 100px);
margin: 0 auto;
background-color: green;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.footer {
height: 50px;
background-color: blue;
}
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>
I want to have a side nav of width: 150px; and then the content floating next to it. I want the content to be 100% minus the 150px side nav width. Is this possible?
I know I can do it in Javascript, but I would much rather know a simple CSS solution, something that would be:
width:100%-150px;
Is there such a solution?
I want the content to be 100% width, minus the 150px side nav width.
Is this possible?
Yes:
width: calc(100% - 150px);
N.B. Be sure to leave a space either side of the minus sign. The CSS parser needs to be clear it is parsing a minus sign, followed by a positive integer.
There are many different ways to achieve that, here are a few of them.
1. using float + overflow:
Note, the content box shouldn't set any float on it, and overflow:auto can prevent wrapped text going under the sidebar box.
.container:after {
content: "";
display: table;
clear: both;
}
.sidebar {
background: pink;
width: 150px;
float: left;
}
.content {
background: gold;
overflow: auto;
}
<div class="container">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
</div>
2: using float + calc:
See the browser support tables - IE9+ basically.
.container:after {
content: "";
display: table;
clear: both;
}
.sidebar {
background: pink;
width: 150px;
float: left;
}
.content {
background: gold;
width: calc(100% - 150px);
float: left;
}
<div class="container">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
</div>
3. using display:inline-block + calc:
.container {
font-size: 0; /*remove white space*/
}
.sidebar, .content {
font-size: 16px; /*reset font size*/
display: inline-block;
}
.sidebar {
background: pink;
width: 150px;
}
.content {
background: gold;
width: calc(100% - 150px);
}
<div class="container">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
</div>
4. using CSS table:
.container {
display: table;
width: 100%;
}
.sidebar, .content {
display: table-cell;
}
.sidebar {
background: pink;
width: 150px;
}
.content {
background: gold;
}
<div class="container">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
</div>
5. using flexbox:
See the browser support tables - IE10+ with prefixes.
.container {
display: flex;
}
.sidebar {
background: pink;
flex: 0 0 150px;
}
.content {
background: gold;
flex: 1;
}
<div class="container">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
</div>
Another ways is to make the side nav float and then have the main content be width 100% and include a padding of 150px on the same side as the nav
An option would be to specify
.content {
left: 0;
position: absolute;
right: 150px;
}
.sidenav {
float: right;
margin-right: -150px;
}
instead of width: 100% for the content. Note: I assumed relative positioning on the parent element (which would contain both the content and side nav).
Good luck!
I am attempting to position two elements in the center of their given space regardless of the size of the page.
Example
https://jsfiddle.net/57q9dn78/
<div id="parent">
<div class="child right">
I am a child.
</div>
<div class="child left">
I am a child.
</div>
</div>
.child {
background-color: #ff0000;
height: 20px;
width: 100px;
max-width: 50%;
}
.right {
float: right;
margin-right: 75px;
}
.left {
float: left;
margin-left: 75px;
}
#parent {
background-color: #00FF00;
height: 20px;
padding: 20px 0;
width: 500px;
}
In the example the #parent div is set to 500px and the others have margins based on that. Normally parent would be 100% width. This is just an example of what I wanted. Is there a way to use calc or something else in CSS so as the page changes in size the margin changes or goes away entirely based on the face that each child is 100px.
You could use flexbox:
.child {
background-color: #ff0000;
height: 20px;
width: 100px;
max-width: 50%;
}
#parent {
background-color: #00FF00;
height: 20px;
padding: 20px 0;
display: flex;
justify-content: space-around;
width: 500px;
}
<div id="parent">
<div class="child right">
I am a child.
</div>
<div class="child left">
I am a child.
</div>
</div>
Just make the children's container 50%
.child {
height: 20px;
width: 50%;
float:left;
text-align:center;
}
.child span {
background-color: #ff0000;
}
https://jsfiddle.net/foreyez/xqvffyqj/
Just change the margin to 15% instead of 75px, which is 75px/500px:
.right {
float: right;
margin-right: 15%;
}
.left {
float: left;
margin-left: 15%;
}
Here is a working example
.child-holder {
width: 50%;
float: left;
}
.child {
background-color: #ff0000;
height: 20px;
width: 100px;
margin: auto;
max-width: 100%;
}
#parent {
background-color: #00FF00;
height: 20px;
padding: 20px 0;
width: 100%;
}
<div id="parent">
<div class="child-holder">
<div class="child">
I am a child.
</div>
</div>
<div class="child-holder">
<div class="child">
I am a child.
</div>
</div>
</div>
Before posting this I attempted to delete the question because none of the given answers handled the responsive design requirement. So, giving that parent needs to be 100%, you can make 2 boxes of 50% width and the auto margin on the child will allow the children to be centered within their respective spaces regardless of the size of parent or page.
Here is 2 simple variants, the first having fixed width and margin left/right (using your sample fixed width's), the second with fluid and translate left/right.
The middle for 2 element is 33% and then you reduce with 66% of their width.
If one want them centered at 25%, just change to 25% and reduce with 50%.
Snippet fixed width
.child {
background-color: #ff0000;
height: 20px;
width: 100px;
max-width: 50%;
}
.left {
float: left;
margin-left: calc(33.3% - 66.6px);
}
.right {
float: right;
margin-right: calc(33.3% - 66.6px);
}
#parent {
background-color: #00FF00;
height: 20px;
padding: 20px 0;
width: 500px;
}
<div id="parent">
<div class="child right">
I am a child.
</div>
<div class="child left">
I am a child.
</div>
</div>
Snippet fluid width
.child {
background-color: #ff0000;
height: 20px;
width: 100px;
max-width: 50%;
}
.left {
float: left;
position: relative;
left: 33.3%;
transform: translateX(-66.6666%);
}
.right {
float: right;
position: relative;
right: 33.3%;
transform: translateX(66.6666%);
}
#parent {
background-color: #00FF00;
height: 20px;
padding: 20px 0;
width: 100%;
min-width: 200px;
}
<div id="parent">
<div class="child right">
I am a child.
</div>
<div class="child left">
I am a child.
</div>
</div>
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>
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!