Pure CSS box collapse in specific way - html

I need to collapse divs (left: logo, banner, right: buttons group A, buttons group B)
I want these to collapse in specific way depending on screen size:
Button group B collapse
Banner collapse
If screen resolution is super high I want to have banner+logo on left (red+green), blank space in middle, and two button groups on right (blue+purple)
See image below:
This is what I have tried so far:
https://jsfiddle.net/ey74wud6/
To be honest it was trial and error, and boxes are collapsing in way not good for me.
<style>
/* just example - color, fixed size of box */
.green { background: green; width: 80px; height: 70px; }
.red { background: red; width: 270px; height: 70px; }
.purple { background: purple; width: 70px; height: 70px; }
.blue { background: blue; width: 70px; height: 70px; }
.box { margin: 2px; }
/* proper css experiments */
.left {
float: left;
}
.left .box {
float: left;
}
.right {
float: right;
}
.right .box {
float: left;
}
</style>
<div class="left">
<div class="box green"></div>
</div>
<div class="left">
<div class="box red"></div>
</div>
<div class="right">
<div class="box purple"></div>
</div>
<div class="right">
<div class="box blue"></div>
</div>
I know I can do it with little help of javascript but my question is it possible to solve my problem using pure CSS?
Any help will be appreciated

You can use css media queries for this. Check out the modified example: https://jsfiddle.net/ey74wud6/1/
I've modified your css code a bit, but the most important part is :
#media (max-width: 454px) {
.left {
width : 280px;
}
.right {
width: 80px;
}
}
#media (min-width: 455px) and (max-width: 522px) {
.left {
width : 360px;
}
.right {
width: 80px;
}
}
You can replace the values to fit your needs

What you need is display:flex
You can define flex-shrink/grow and combine it with max- and min-width on flexible Elements.
And you can combine that with mediaqueries

Related

CSS - Make multiple divs in columns wrap back around

Say I have three divs - Red Green and Blue with the following basic markup and styles: https://jsfiddle.net/ar8sn1o6/
<div class="red">Red</div>
<div class="green">Green</div>
<div class="blue">Blue</div>
.red, .green, .blue {
display: inline-block;
float: left;
margin: 1%;
width: 48%;
}
.red {
background: red;
height: 50px;
}
.green {
background: green;
height: 100px;
}
.blue {
background: blue;
height: 50px;
}
But I want to be displayed in two column on desktop and one column on mobile like this. Whilst it is reasonably straight forward to have a Red -> Blue -> Green mobile layout, I need to instead have a Red -> Green -> Blue layout
Is this possible without duplicating any HTML?
It is possible using media queries
Check out this article to find out more: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
Syntax
Media queries consist of an optional media type and can, as of the
CSS3 specification, contain zero or more expressions, expressed as
media features, which resolve to either true or false. The result of
the query is true if the media type specified in the media query
matches the type of device the document is being displayed on and all
expressions in the media query are true.
See snippet below. Resize it to see it working!
.red, .green, .blue {
display: inline-block;
float: left;
margin: 1%;
width: 48%;
}
.red {
background: red;
height: 50px;
}
.green {
background: green;
height: 100px;
}
.blue {
background: blue;
height: 50px;
}
#media (max-width: 400px) {
.red, .green, .blue {
display: block;
width: 100%;
}
}
<div class="red">Red</div>
<div class="green">Green</div>
<div class="blue">Blue</div>
UPDATE
What you're trying to achieve is not possible with CSS only.
Ill try to explain why not.
When you style elements with float: left or display: inline-block. They have an parent element which has the height of the highest child. So every new block thats inserted on a new row will allign at the bottom of the highest previous child.
So aligning them as you want is not possible. However, you can wrap an div around it. And then just add float: left; or display: inline-block. See this example: https://jsfiddle.net/ar8sn1o6/2/
NOTE:
When using float, the parent element will lose its height. You can fix this by adding overflow: hidden to the parent element.
Or use clearfix. See: https://css-tricks.com/snippets/css/clear-fix/
You could use Media queries to specify certain CSS when the viewport of the device is smaller than a certain/specified size.
For example:
#media screen and (max-width: 480px) {
container {
width: 100%;
}
.blue {
background-color: blue;
width: 90%;
height: 50px;
}
}
This would mean that if the width of the device was smaller than 480px, these styles would take effect. I think if you put them all in a container and they all had a width of say 90%, they would align one by one below each other in the mobile view.
Hope that helps
Put a container and add media-query
.red, .green, .blue {
display: inline-block;
margin: 1%;
}
.red {
background: red;
height: 50px;
width:100%;
}
.green {
background: green;
height: 100px;
}
.blue {
background: blue;
height: 50px;
width:100%;
}
.container, .green{
float:left;
width: 48%;
}
#media only screen
and (max-width: 480px) {
.container, .green{
width: 100%;
}
}
<div class="container">
<div class="red">Red</div>
<div class="blue">Blue</div>
</div>
<div class="green">Green</div>

Sum of percent widths not rounded to 100%

I want to make a multi-segment progress bar.
It has to be horizontally centered, with a maximum width, but not a static one, so it can shrink if there is not enough space.
The problem is that sometimes the total progress is at 100%, but the segments could be at 33.33% and 66.66%.
The percentages are being calculated based on the width of the document, which may be an odd number, so the bar segments' widths are rounded in a way that leaves one pixel empty on the bar.
HTML
<div class="CENTER">
<div class="BAR">
<div class="SEGMENT ONE" style="width: 33.33%;"></div>
<div class="SEGMENT TWO" style="width: 66.66%;"></div>
</div>
</div>
CSS
.CENTER {
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.BAR {
height: 10px;
}
.SEGMENT {
float: left;
height: 100%;
}
.BAR { background-color: #F00; border: 1px solid #000; }
.SEGMENT.ONE { background-color: #FDA; }
.SEGMENT.TWO { background-color: #ADF; }
Play around with the width of the window after it's big enough for the bar to reach its maximum width.
There will be a red one pixel wide section on the right side of the bar.
How can I avoid it?
Example: http://jsfiddle.net/CV6fp
Can you do it using that same HTML and without JavaScript, CSS?
Maybe with table display?
http://jsfiddle.net/CV6fp/6/
.CENTER {
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.BAR {
height: 10px;
display: table;
width: 100%;
}
.SEGMENT {
display: table-cell;
height: 100%;
}
.BAR { background-color: #F00; border: 1px solid #000; }
.SEGMENT.ONE { background-color: #FDA; }
.SEGMENT.TWO { background-color: #ADF; }
Here is how I would do it:
http://jsfiddle.net/CV6fp/3/
Basically, drop the width property off the div with class TWO. Then make the same div NOT float left:
<div class="CENTER">
<div class="BAR">
<div class="SEGMENT ONE" style="width: 33.33%;"></div>
<div class="SEGMENT TWO"> </div>
</div>
</div>
And the style change:
.SEGMENT.TWO { background-color: #ADF; float:none; }
This means that second segment no longer floats:left, but I do think this may be what you are looking for.
Update: And finally after much soul searching, a CSS only solution to solve all the issues mentioned on this page:
http://jsfiddle.net/CV6fp/7/
Two changes to CSS: (1) segments set to float:right, and (2) .SEGEMENT.ONE to override that and always float:left
.SEGMENT {
float: right;
height: 100%;
}
.SEGMENT.ONE { background-color: #FDA; float:left; }
In this case you may need to reduce accuracy to the tenth's place and use a ceiling rounding function on the final segment. This way you would get 33.3% and 66.7%.
Try: .SEGMENT:last-child { float: none; width: auto !important; }. This should make the last segment to fill the remaining space.

Make container div clear when its content can't fit in one line?

I have a liquid layout. When the layout is wide enough some divs (.one and .two) can all line up horizontally on one line.
When the layout is squeezed eventually the right floated divs (.two) end up on multiple lines. Is there a way (without width based media queries) to make the left floated divs clear onto their own line when they cant all fit in a line. I assume I would need to be clear .cont2.
Below is my code an images of what im trying to achieve.
http://codepen.io/anon/pen/JcDlh
<div class="cont">
<div class="one">
</div>
<div class="cont2">
<div class="two"></div>
<div class="two"></div>
<div class="two"></div>
</div>
</div>
.cont {
background: blue;
width: 40%;
margin: auto;
overflow: auto;
}
.one {
background: red;
height: 100px;
width: 300px;
float: left;
}
.two {
float: right;
border: 1px solid black;
height: 100px;
width: 100px;
background: white
}
You could try:
.cont2 {
float: left;
overflow: auto;
}
See example at: http://codepen.io/anon/pen/kczux
to make them all together go to the next line (instead of one by one) you could use a float on the cont2 element. But for making it float to the left instead to the right, I think you need media queries.
http://codepen.io/anon/pen/Jbjmp
Just add to your CSS: .cont2 { float: right; }
It will make your cont2 div stick to the right with all of his child divs, and when you resize screen it will go to new line. For lower resolutions you will need media queries
You can use media queries for this, this is my take:
http://jsfiddle.net/S4R6h/
You can read a little here about how to target various devices based on size: http://css-tricks.com/snippets/css/media-queries-for-standard-devices/
Make the fiddle window very wide and you'll see what you've got when your code sits nicely in a line. Then shrink the window and the media query kicks in and for the purposes of showing you, the body will go black.
HTML:
<div class="cont">
<div class="one">
</div>
<div class="cont2">
<div class="two"></div>
<div class="two"></div>
<div class="two"></div>
</div>
</div>
CSS:
.cont {
background: blue;
width: 40%;
margin: auto;
overflow: auto;
}
.one {
background: red;
height: 100px;
width: 300px;
float: left;
}
.two {
float: right;
border: 1px solid black;
height: 100px;
width: 100px;
background: white
}
#media only screen
and (max-width : 1530px) {
/* Styles */
/* when the query kicks in we decend into night */
body{
background: #000;
}
.one {
background: red;
width: 100%;
}
.two{
width: 33.333%;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
}
}
With media queries this would be quite easy, I recommend checking those out. But if you're not willing to use them you could do the following:
Add display:inline-block to .cont2
.cont2 {
display: inline-block;
}
And remove the float:left from .one and instead of it add there display: inline-block; too. So .one would look like
.one {
background: red;
height: 100px;
width: 300px;
display:inline-block;
}
That way the .cont2 div will align to the left when there's not enought space for it to be on the same line with .one .
Here's a codepen: http://codepen.io/anon/pen/qLljt

Make floating divs the same height

I have 2 divs side by side. I don't know the height of them upfront, it changed according to the content. Is there a way to make sure they will always be the same height, even when one of them stretches, only with CSS?
I made a fiddle to show. I want the red and blue divs to be the same height...
http://jsfiddle.net/7RVh4/
this is the css:
#wrapper {
width: 300px;
}
#left {
width:50px;
background: blue;
float:left;
height: 100%; /* sadly, this doesn't work... */
}
#right {
width:250px;
background: red;
float:left;
}
You could try instead of using float, use display: table-cell. You might find some older browsers don't understand this rule however. See below:
#wrapper {
display: table; // See FelipeAls comment below
width: 300px;
}
#left {
display: table-cell;
width: 50px;
background: blue;
}
#right {
display: table-cell;
width: 250px;
background: red;
}
Antony answer works ok, but you need all the divs to have the same parent and to have a wrapper, I have a solution that use javascript but works with any kind of element, they just need to have the same selector.
function setEqualHeight(selector, triggerContinusly) {
var elements = $(selector)
elements.css("height", "auto")
var max = Number.NEGATIVE_INFINITY;
$.each(elements, function(index, item) {
if ($(item).height() > max) {
max = $(item).height()
}
})
$(selector).css("height", max + "px")
if (!!triggerContinusly) {
$(document).on("input", selector, function() {
setEqualHeight(selector, false)
})
$(window).resize(function() {
setEqualHeight(selector, false)
})
}
}
setEqualHeight(".sameh", true)
http://jsfiddle.net/83WbS/2/
I would recommend reading this article that explains how to do what you are trying to do. I would put a fiddle up that shows, but its pretty extensive and pure css. http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks
There is a much simpler solution I want to point to. Using large padding-bottom: 500em and negative margin-bottom:-500em of the same amount on columns while the wrapper has simply overflow:hidden to cut the columns to the right size.
Found here:
HTML/CSS: Making two floating divs the same height
As indicated by Hexodus you can padding-bottom and margin-bottom, but a better solution would be to use flexbox or grid.
You can check this codepen if you want. I included a footer area because that is something I needed and it required a little bit more of hack.
.section {
width: 500px;
margin: auto;
overflow: hidden;
padding: 0;
}
div {
padding: 1rem;
}
.header {
background: lightblue;
}
.sidebar {
background: lightgreen;
width: calc(25% - 1rem);
}
.sidebar-left {
float: left;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.main {
background: pink;
width: calc(50% - 4rem);
float: left;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.sidebar-right {
float: right;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.footer {
background: black;
color: white;
float: left;
clear: both;
margin-top: 1rem;
width: calc(100% - 2rem);
}
<div class="section">
<div class="header">
This is the header
</div>
<div class="sidebar sidebar-left">
This sidebar could have a menu or something like that. It may not have the same length as the other
</div>
<div class="main">
This is the main area. It should have the same length as the sidebars
</div>
<div class="sidebar sidebar-right">
This is the other sidebar, it could have some ads
</div>
<div class="footer">
Footer area
</div>
</div>
You can do this without using tables, by using this CSS trick.
Example - http://jsfiddle.net/LMGsv/
HTML
<div id="wrapper">
<div id="columns">
<div id="left">text</div>
<div id="right">text<br/>another line<br /></div>
</div>
</div>
CSS
#wrapper {
float:left;
width: 300px;
}
#columns {
float:left;
width:300px;
background:blue;
}
#left {
float:left;
width:50px;
background: blue;
}
#right {
width:250px;
background: red;
float:left
}

Div positioning on same line

I have a problem with some divs. In short here is what I need: 2 divs with a certain width (same width) - one with float left and one with right, and a third div that takes all the remaining space. The divs are using display : inline-block to have them on same line.
I have tried this :
<div class="wrapper">
<div class="control leftControl"></div>
<div class="display"></div>
<div class="control rightControl"></div>
</div>
And here is my css:
.wrapper {
width: 100%;
height: 100%;
min-width: 960px;
background-color: #E8E8E8;
}
.control {
width: 10%;
height: 100%;
display: inline-block;
background-color: #ADADAD;
}
.leftControl {
float: left;
}
.rightControl {
float: right;
}
.display {
width: 80%;
height: 100%;
display: inline-block;
}
The problem is that using % on some resolution causes the last div (controlRight) to be moved on a new line.I can understand why and found that if i use 79% on display the divs display almost correctly (1% left unsued.)
It is clear to me that this is not a correct solution.
Any help is appreciated.
You can put all your elements float:left and your 100% will always fit: fiddle
HTML
<div class="control"></div>
<div class="display"></div>
<div class="control"></div>
CSS
.control {
width: 10%;
height: 200px;
background-color: green;
float:left;
}
.display {
width: 80%;
height: 200px;
background-color:blue;
float:left;
}​
Putting everything on float left will simply push divs one by one on the right.