Let say I have a layout with 3 columns:
| left sidebar | content | right sidebar |
Each column is a div with float: left.
I'd like to have the content div always centered, but also set a max-width to it:
| left sidebar | centered + max width | right sidebar |
The total width of the 3 columns should always be 100%, so the two sidebars would have adapt and fill the remaining space.
So in a very big screen it would look like this:
| left sidebar | content | right sidebar |
As if the content div had margin: 0 auto (but with the two divs at the sides instead of empty space).
Is it possible to do such a thing with CSS?
Using flexbox is quite a simple
*{margin:0; box-sizing:border-box;} html,body{height:100%;font:14px/1.4 sans-serif;}
div{ border: 1px solid #000;}
/* here you go */
.flex{ display: flex; }
.grow-1{ flex: 1; }
<div class="flex">
<div>left sidebar</div>
<div class="grow-1">content</div>
<div>right sidebar</div>
</div>
adding the class grow-1 to other elements:
*{margin:0; box-sizing:border-box;} html,body{height:100%;font:14px/1.4 sans-serif;}
div{ border: 1px solid #000;}
/* here you go */
.flex{ display: flex; }
.grow-1{ flex: 1; }
<div class="flex">
<div class="grow-1">left sidebar</div>
<div class="grow-1">content</div>
<div class="grow-1">right sidebar</div>
</div>
Things have changed since float: left was the only solution.
A simpler alternative is to use display properties. An example would be something like this:
div#wrapper {
display: table;
width: 100%;
table-layout: fixed;
}
div#left-sidebar,
div#content,
div#right-sidebar {
display: table-cell;
}
The table-cell property allows the divs to behave like cells in a table without actually using a table — the best of both worlds.
The properties in the wrapper div allow you to specify the width and affect how the cells are distributed.
A better solution would be to use flex-box. However, that only works in modern browsers, so you might have to hold off till you can be sure that there’s no IE lurking about. It’s also a bit harder to learn, but much more flexible.
If you wanted to avoid the use flex-box due to some older browsers not supporting it...
You could use display table properties in the css. A #media query can then be utilized to effectively set the max-width of your content div (i.e. the middle column).
Example media query:
#media (min-width: 300px) {
.middle {
width: 100px !important;
}
}
Note regarding the media query: The width value for the .middle class should equal the #media queries min-width value divided by three. The width value within this context then behaves similar to max-width.
For example; if you want the max-width of the middle column to be 300px, then you set the min-width value for the #media query to 900px. Given this configuration the width of the middle column would remain flexible until the browser width exceeds 900px wide, at which point the middle column width is fixed at 300px wide.
Code snippet:
Here is the full code snippet, including both html and css:
body, html {
padding: 0;
margin: 0;
}
.wrapper {
width: 100%;
height: 100px;
display: table;
background: #BADA55;
table-layout: fixed;
}
.wrapper > div {
display: table-cell;
width: 100%;
text-align: center;
vertical-align: middle;
}
.middle {
background: #C0FFEE;
}
#media (min-width: 750px) {
/*
* The 'width' value below should be the #media
* queries 'min-width' value (above) divided by three.
*
* The 'width' value below is then behaves similar
* to 'max-width'.
*/
.middle {
width: 250px !important;
}
}
<body>
<div class="wrapper">
<div>left sidebar</div>
<div class="middle">content</div>
<div>right sidebar</div>
</div>
</body>
Related
I have two divs inside a third div. Div A is on the left, occupying 30% of the space. Div B is on the right, occupying 70% of the space.
When the width of the screen becomes too small to fit them side by side, I would like to position div B on top and div A on the bottom.
I have considered replicating div A before and after B. For normal width I would show A1 and hide A2. For smaller width I would show A2 and hide A1.
However this seems like a dirty trick. Is there any other way to achieve this?
I think you need order property of flexbox module, you can check this codepen example, you only need to add some breakpoints when you need to change the order, the order is applied to each child element of flexbox container
Flexbox is a good choice for this case.
By defining a media query for widths less than 575px and using flex-direction:column and set order for both divs you can arrange them as desired.
Below is an example I hope will help you:
.Main{
display: flex;
height: 150px;
color: white;
font-size: 2rem;
text-align: center;
line-height: 150px;
}
.A{
flex-basis: 30%;
background-color: red;
}
.B{
flex-basis: 70%;
background-color: blue;
}
#media screen and (max-width: 575px) {
.Main{
flex-direction: column;
}
.B{
order: 0;
}
.A{
order: 1;
}
}
<div class="Main">
<div class="A">A</div>
<div class="B">B</div>
</div>
I'm sure this is simple but I'm struggling to get my head around it.
I have two divs. A heading div max-width 500px. A main div max-width 400px. The main div should be centered horizontally in the browser window. The left hand edge of the heading div needs to align to the left hand edge of the main div. See below. The red line is the center of the browser window:
I've acheived this by adding a wrapper div with max-width 500px (the pink colour) and using extra padding on the left hand side. This works to a point. But at smaller screen sizes the extra padding on the left knocks the layout off center.
So how do I create this layout? I'm presuming I can not add the heading div as a child of the main div, because a child can't be wider than its parent. I'm guess flexbox might be the answer, but I've never used Flexbox.
This is the code I have so far:
https://jsfiddle.net/aqpyzogc/
<div class="wrapper">
<div class="heading"></div>
<main></main>
</div>
.wrapper {
max-width:500px;
margin:0 auto;
padding:0 0 0 100px;
background-color:lightpink;
}
.heading {
max-width:500px;
background-color:cyan;
height:100px;
}
main {
max-width:400px;
background-color:grey;
height:500px;
}
But at smaller screen sizes the extra padding on the left knocks the layout off center.
You can calculate the correct amount of padding for those viewport sizes, using the calc() function.
Below 600px viewport width, the remaining space is 100% minus 400px, and we need half of that for the padding-left, so:
body {
margin: 0;
}
.wrapper {
max-width: 500px;
margin: 0 auto;
padding: 0 0 0 100px;
background-color: lightpink;
}
#media (max-width: 600px) {
.wrapper {
padding-left: calc((100% - 400px) / 2);
}
}
.heading {
max-width: 500px;
background-color: cyan;
height: 100px;
}
main {
max-width: 400px;
background-color: grey;
height: 500px;
}
<div class="wrapper">
<div class="heading"></div>
<main></main>
</div>
I set the body margins to 0 here as well, so that the whole thing fits with the 600px breakpoint. If you need those additional margins, you have to figure them in in the breakpoint value calculation.
Fiddle: https://jsfiddle.net/aqpyzogc/1/
I have two div's, wrapped inside one container div. The bottom div contains a dynamically filled table (with variable width), which determines the overall width of all div's.
In the top div, I want to list several small red blocks (div's or span's or whatever). These red blocks need to take the available horizontal space, but wrap to a new line if they reach the max allowed width.
So this is what I want to achieve:
Unfortunately, I can't make it work. No matter how I CSS the red blocks (small floating div's, or inline-block's), they keep on taking more width than allowed. As a result, all div's become a lot wider than allowed, wider than my table:
How can I force these red blocks to only use the allowed with, and pick a new line if they run out of space?
Thanks!
UPDATE:
Here's a working example that shows the red blocks (which have variable length) next to each other, taking up more width than they are allowed. They need to start on a new line as soon as the table's width is reached.
http://codepen.io/anon/pen/bqobGp?editors=1100#0
table td{
border:thin solid gray;
line-height:25px;
padding:0 5px;
}
.div1, .div2 {
margin-top:15px;
padding:20px;
background:white;
box-shadow:2px 0 3px rgba(0,0,0,.12)
}
.container {
display:inline-block;
background:#f1f1f1;
padding:30px;
}
.badge {
line-height:30px;
background:red;
min-width:150px;
color:white;
margin:5px 10px;
text-align:center;
font-family:sans-serif;
border-radius:5px;
display: inline-block;
}
Based on my historical experience, you can achieve such behavior using basic HTML tables if you set small width on a parent table element...
So: for your code, we can use display: table and a small width on .container and white-space: nowrap; for .div2 (to prevent line breaks on table) as following:
.container {
display: table;
width: 50px; /* use a small value */
...
}
.div2 {
white-space: nowrap;
}
here is the updated code pen
/* shrink 2nd div to fit the table */
.div2 {width: fit-content;}
/* shrink first div to minimum size
* but constrain it to shrink no further than width established by its siblings
*/
.div1 {min-width: available; width: min-content;}
alternative approach
.container {width: min-content;}
These width values are fairly new and the spec are still in flux, so different browsers may support them under different names or prefixes may be needed.
I'm not sure what you call your "red" blocks in your css file, but something that is short and simple would be to calculate the width.
For example:
.parent {
width: 100%;
padding: 0;
margin: 0;
background: green;
float: left;
}
.red_block {
width: calc(100% / 5 - 20px); /* Calculate width here - where it takes the full 100% of the parent and divides it by 5 "red blocks" and subtracts 20px for each */
height: 40px;
padding: 0;
margin: 10px;
background: red;
float: left;
}
<div class="parent">
<div class="red_block"></div>
<div class="red_block"></div>
<div class="red_block"></div>
<div class="red_block"></div>
<div class="red_block"></div>
<!-- Will wrap to second line -->
<div class="red_block"></div>
<div class="red_block"></div>
<div class="red_block"></div>
</div>
DEMO
Does this answer your question?
UPDATE:
With your "red blocks" being calculated via width, you can even specify that class in some media queries to change the width to your liking for mobile devices! Example:
#media screen and (max-width: 48em) {
.red_block {
width: calc(100% / 3); /* or to whatever you want...IE: width: 100%; */
}
}
I am developing Facebook application (I am not CSS pro.). The iframe canvas is liquid eg. width 100%.
The main div that hold the application is 500 px wide. There are two divs of left and right from main dic (see picture below). Left and right divs must have the same width.
When user resize browser window I want keep main div centered with fixed width while both left and right divs must resize appropriately to take only available space.
In case there is no space for left and right divs they must disappear. Main div must be centered.
Thank you very much for you help.
</style>
body{
margin: 0px;
padding: 0px;
}
#main{
width: 300px;
display: inline-block;
background: red;
}
#left, #right{
width: calc(50% - 150px);
display: inline-block;
background: green;
}
#media (max-width: 400px) {
#left, #right{
display: none;
}
}
</style>
<body>
<div style="text-align: center;">
<div id="left">1</div><div id="main">2</div><div id="right">3</div>
</div>
</body>
This is what I have so far: http://jsfiddle.net/clicker314/L77jh8ak/4/
If you are willing to use the calc() CSS function, this problem is relatively easy to solve:
#main{
width: 500px;
display: inline-block;
}
#left, #right{
width: calc(50% - 250px);
display: inline-block;
}
Thus, the left and right divs adjust their height based on the width of half of the screen, minus half of the main element. If you want a fallback, add another 'width:' rule on the line prior to the calc() width rule.
This works on all modern browsers, including IE 10+. If you want IE 8/9 support, add the second width rule I mentioned above.
For IE 8/9 support, you have two options:
1. Give a defined width for those two options. I.e. #left, #right{width: 200px;}.
2. Add some JS/jQuery to imitate the CSS calc() function.
To hide the divs on a certain size, add a media query (the 600px I added is hypothetical, pick any minimum screen size you like):
#media (max-width: 600px) {
#left, #right{
display: none;
}
#main{
width: 100%;
}
}
The #main rule there is optional. It assumes that you want the #main div to take up all of the space available in the container.
I actually don't know how to name my question. But I will explain what I need to do.
HTML is simple as this:
<div id="left_div"></div>
<div id="right_div"></div>
I need left_div to be on the left, to have 100% width, but with fixed right margin 320px. right_div has fixed width 300px and must be alongside left_div.
I know I can do this very easily, when I would do this:
<div id="right_div" style="float:right;width:300px"></div>
<div id="left_div" style="margin-right:320px;"></div>
But the problem is that I need HTML to be as I mentioned before. The order of DIVs matter. If someone wonders why, it's because I am working on responsive website, where I need, when the viewport is too narrow, the right_div to be below left_div. And that I can't do with simple solution I have put above.
I hope my question makes sense and I am thankful for any answers or helpful hints.
Oh, and I forgot to mention I need this to be pure HTML+CSS, no JS. And I don't need to support IE7 and below.
UPDATE:
left_div must be width:auto and right margin must be fixed (e.g. 300px).
If you want your layout to be responsive you should use a CSS framework like Columnal, 1140, or more in this list.
Most of these frameworks supports the grid system, which is the best way to structure your layout and you don't have to worry about floats and pixels anymore.
I think that what do you want is almost impossible with just pure HTML + CSS.
What may work for you is something like this one I did: http://jsfiddle.net/fmZAm/
HTML:
<div class="main">
<div class="left"></div>
<div class="right">
<div class="fixed_content"></div>
</div>
</div>
CSS:
div.main
{
min-height: 500px; /* force some height */
min-width: 300px; /* min width to show content */
text-align: center; /* center content when in vertical responsive mode */
font-size: 0px; /* remove blank space from 'inline-block' display */
}
div.main > div /* left and right divs */
{
width: 100%; /* force both to have as max width as possible */
min-height: inherit; /* same min height as parent */
min-width: inherit; /* same min width as parent to show content */
display: inline-block;
}
div.left
{
max-width: 58%; /* 100% width from max of 58% parent width */
background-color: lightgreen;
}
div.right
{
max-width: 42%; /* 100% width from max of 42% parent width */
text-align: right; /* put child 'inline-block' divs to the right */
background-color: dodgerblue;
}
div.right > div.fixed_content
{
width: 300px; /* set the 300px right div you want */
min-height: inherit; /* same min height as parent */
background: orange;
display: inline-block;
}
As both divs (left and right) will have % widths, both will resize based on the current max width, but you'll have your fixed width div inside of the right div. So, when your right div resize to 300px width (the fixed with of its child div) it will go below the left div.
Hope it helps!
I had the same issue, I solved it using position:absolute.
HTML
<div class="container">
<div id="left_div"></div>
<div id="right_div"></div>
</div>
CSS
.container {
position:relative;
}
#left_div {
float: left;
width: auto;
margin-right: 320px;
}
#right_div {
position:absolute;
top:0;
right:0;
width: 300px;
}