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>
Related
I can not understand how css works, and it's annoying me. I was trying to do some basic side by side two divs and one div below them.
At first I've learned that I had to give float:left for both side by side divs. For curiosity I did'nt gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Then I gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Question: I didn't gave float:left for third div but it didn't act like the first screen shot. Why?
css code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
float: left;
}
.other-posts {
width: 25%;
background-color: #00ff00;
float: left;
}
.author-text {
background-color: #ffff00;
}
html code:
<div class="container">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
<div class="author-text">author text</div>
</div>
When you use a float, you break the natural box-model behavior of the markup.
Your first floated element has a width of 50%, relative to the parent (1000px) it will take the half of the .container. The second (floated) element will take the next 250px. And here comes the good thing.
The third element, which isn't floated, is also a div, thus a block-level element (so implicitly it will take 100% of the width of its parent). If you set the background-color of your first and second element to a transparent one #0000ff00 and #00ff0000 respectively. You will see your third element is growing behind them.
This is, what I mean with "breaking the box-model". Now, to understand this beter, you could start giving a explicit width to the third element. Let's say: 90%, you will see how the yellow background will reduce itself from the right side.
If you set the width to 50% it will "jump" down, to the second line. It will be even broad as the first element, but two times height. With other words, it will try to fit in the first available space.
To avoid this, in the past, we used the clearfix hack... but since flexbox and css grids are broadly supported, we don't have to rely in floats anymore for this side-by-side layouts.
Float has their own use cases, is not that float sucked, it's just not meant for layout.
For more information on this topic you can check this great article about floats on CSS-Tricks.
Wrap the items you want side by side in another wrapper, then apply flexbox to that wrapper:
.my-flex-wrap {
display: flex;
}
Then remove all the floats. Done.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.my-flex-wrap {
display: flex;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
}
.other-posts {
width: 25%;
background-color: #00ff00;
}
.author-text {
background-color: #ffff00;
}
<div class="container">
<div class="my-flex-wrap">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
</div>
<div class="author-text">author text</div>
</div>
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>
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 trying to craft a flexbox in CSS with the following characteristics:
Three items stacked and centered within the middle of the flexbox
One item locked to bottom of the flexbox
Flexbox is set to a size of 100vh and 100vw, taking up visible screen area
Items within flexbox must not occupy the top 150px of the flexbox. This may push some items below the viewable area (see "Desired Result 3" in image below)
Ideally, a pure CSS solution is feasible with the HTML elements provided
The Problem
The vertically centered boxes won't honor the 150px space I would like to put at the top of the flexbox, and I haven't been able to create an elegant way to make sure the items don't float up past the top of the screen if I make the window too short. That is, the example in "Desired Result 3" in the image above remains elusive.
Example Code
HTML:
body {margin:0; font-family: sans-serif; font-weight:bold;}
.parentFlexBox {
background-color:grey;
display: flex;
flex-direction: column;
margin-top:0;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
height:100vh;
width:100vw;
}
.itemA, .itemB, .itemC, .itemD { padding:5px; text-align:center; margin-bottom:5px; color:#fff;}
.itemA { background-color:red; width:50px; margin-top:auto;}
.itemB { background-color:hotpink; width:150px; height:50px}
.itemC { background-color:purple; width:40px; height: 35px}
.itemD { background-color:blue; margin-top:auto; width: 80px;}
<div class="parentFlexBox">
<div class="itemA">A</div>
<div class="itemB">B</div>
<div class="itemC">C</div>
<div class="itemD">D</div>
</div>
Please run above code in full screen to see the issue
This might work for you:
HTML (add two invisible flex items)
<div class="parentFlexBox">
<div class="itemA">A</div>
<div class="itemB">B</div>
<div class="itemC">C</div>
<div class="itemD">D</div>
<div class="itemE">E</div><!-- invisible spacer item with 150px height -->
<div class="itemF">F</div><!-- invisible spacer item with 120px height -->
</div>
CSS
.parentFlexBox { justify-content: space-between; } /* changed from `center` */
.itemA { order: 1; } /* removed `margin-top: auto` */
.itemB { order: 2; }
.itemC { order: 3; }
.itemD { order: 5; height: 30px; } /* added `height` for centering calculation;
removed `margin-top:auto` */
.itemE {
order: -1;
flex: 0 0 150px; /* don't grow, don't shrink, remain at 150px height */
visibility: hidden;
margin-bottom: auto; /* stick to top of container */
}
.itemF {
order: 4;
flex: 0 1 120px; /* don't grow, shrink proportionally, start at 120px height */
visibility: hidden;
margin-top: auto; /* go south as much as possible (sticks to Item D) */
}
/* NOTE: Item D has height 30px. Item F has height 120px. Together they equal height of
Item E. Equally balanced on both ends, Items A, B & C are centered in the container. */
DEMO 1
I placed the spacer divs last in the mark-up to keep with the alphabetical ordering. If you prefer to list all divs (including spacers) in order, that would eliminate the need for the order property.
Also, in the demo, the code includes borders, in case you want to see the spacers at work. Just disable the visibility property.
Update (based on comment)
Nice, a couple of questions though: 1) Possible to make it so that BCD don't change height when resizing the window? 2) Possible to make the gray background extend to contain D when window is short? 3) Possible to do items E and F as pseudocode elements?
Question #1: Yes. Add flex: 0 0 <<absolute height>> to BCD. For instance, add flex: 0 0 50px to each item, which tells them to stay fixed at 50px height. (Also, remove the height property from each rule, to avoid any potential conflict with flex.)
Question #2: Yes. Instead of limiting the container to height: 100vh, use min-height: 100vh.
Question #3: Yes. Remove the E and F code from the HTML and CSS, and add this to the CSS:
.parentFlexBox::before {
content: '';
flex: 0 0 150px;
visibility: hidden;
margin-bottom: auto;
}
.parentFlexBox::after {
content: '';
flex: 0 1 100px;
visibility: hidden;
margin-top: auto;
order: 4;
}
DEMO 2
I tried to get two divs next to eachother. The right one has a fixed width, but the left one has to be able to resize. I tried multiple ways, but none fit all my requirements:
Right one has fixed width
Parent div has height of largest child (wraps its childs)
Left one has to resize
Html structure has to in this order (reason at bottom):
html:
<div class="container">
<div class="variable_width"></div>
<div class="fixed_width"></div>
</div>
I tried absolute positioning the right div and adding a margin on the left one and it achieved all requirements, except that the parent div doesn't wrap the largest child (as expected)
http://jsfiddle.net/0fxL71xL/3/
.container{max-width:400px;position:relative;}
.variable_width{margin-right:100px;}
.fixed_width{width:100px; position:absolute;right:0;top:0;}
I also tried using inline-block and max-width but then the divs don't align at the top, and I don't know how to handle the whitespace issue. Most important, it does not make the left div resize: http://jsfiddle.net/0fxL71xL/4/
.container{max-width:400px;}
.variable_width{max-width:290px; display:inline-block;}
.fixed_width{width:100px; display:inline-block;}
I also tried a float right on the right div, but it didn't come near what I wanted.
The closest I got was changing the order in html and using float:right on the div that has to go right, but in this case I can't use an #media query to have it display below the left div at a certain moment.
EDIT:While paulie_d's answer fixes it, I would prefer something that has a large browser support
flexbox can do that.
JSfiddle Demo
.container {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.fixed_width {
width: 200px;
background: #bada55;
}
.variable_width {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
background: plum;
height: 100px;
}
<div class="container">
<div class="variable_width"></div>
<div class="fixed_width"></div>
</div>
.container {
width:100%;
}
.variable_width {
max-width: 70%;
display: inline-block;
background-color:blue;
margin-right: -3px;
}
.fixed_width {
width:100px;
width: 28%;
display: inline-block;
background-color:red;
vertical-align: top;
}
now you can use this code. i think it will work fine.you can add some content in variable width div class and check whether it is working or not.i have checked it and it really works :) .
http://jsfiddle.net/souraj/vaqbsdzk/
After more searching I came across this interesting page which sums some techniques to achieve exactly what I wanted. It gives the most complete answer.
http://clubmate.fi/100-percent-height-columns-fixed-width-sidebar-pure-css-solutions-to-commons-fluid-layout-problems/