Float layout with reordering in modern CSS - css

I used to be good at CSS at one point, but the ship has sailed on while I was away.
I need some guidance on how to solve the following case:
I have X number of divs where X may change over time
The divs "float left" inside a container div, wrapping into rows
All the divs have their own rigid width and height
The divs have an order that can change and that is important
It is desirable that the rows formed by the float layout dont create uneccessary "gaps" (see the marked areas in example below)
So my html is like this:
<div class="container">
<div id="item-1" class="item"></div>
<div id="item-2" class="item"></div>
<div id="item-3" class="item big"></div>
<div id="item-4" class="item"></div>
<div id="item-5" class="item"></div>
<div id="item-6" class="item"></div>
<div id="item-7" class="item big"></div>
<div id="item-8" class="item"></div>
<div id="item-9" class="item"></div>
<div id="item-a" class="item"></div>
<div id="item-b" class="item"></div>
<div id="item-c" class="item"></div>
<div id="item-d" class="item"></div>
</div>
And my naïve pseudo-CSS is like this:
.container {
display: block;
width: 600px;
height: 600px;
border: 2px solid black;
}
.item {
width: 100px;
height: 100px;
border: 2px solid blue;
float: left;
}
.item.big {
width: 150px;
height: 110px;
border: 2px solid red;
}
So my question is, are there any modern CSS primitives that would solve this case? Especially, can the order be handeled in pure CSS?

You can achieve this with Flexbox . Flexbox is a pure CSS solution for that kind of problems.
All modern browsers supports it, so you can get rid of the float in your CSS files.
For better understanding, you can read about it here.
Hope it helps.

Related

Incorrect transform position in Chrome when using percent

When using transform with percent value on container that has float width (for ex. 800.63px) Chrome always rounds position in pixels incorrectly.
This typically happens with em/rem width in combination with percent (see example below):
HTML:
<div class="container">
<div class="wrap">
<div class="slider">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
</div>
SCSS:
.container {
width: 38rem;
}
.wrap {
width: 33%;
overflow: hidden;
}
.slider {
white-space: nowrap;
font-size: 0;
transform: translate3d(-1000%,0,0);
}
.item {
display: inline-block;
height: 8rem;
width: 100%;
background: limegreen;
&:nth-child(even) {
background: orangered;
}
}
The result is some part of next slide is always visible. Looks like Chrome first rounds the item width and then multiplies it by percent value.
Is there any known workaround for this? If I do the math in JS and use px values in transform then everything is (almost) perfect, but shouldn't it "just work" with percents too?
Please, see fiddle for working example: https://jsfiddle.net/Lumh07te/37/
Change the way you set your sizes.
Instead of the slider having width 100%, and needing a maximum transform of 1000%, set it to a width of 1000%, and a needed maximum transform of 100%.
And the items width is now 10% instead of 100%
in your original code, wrap has a width that is not integer, but than in the layout is forced to render as an integer value in pixels. Then , translating a 1000% of this value multiplies the rounding errors by 10. If you instead set the width to 1000%, the rounding to pixels is done on this size, and then it is mutiplyed by values less than 1 (0.5, 0.6, 0.7.. ) or 1 at a maximum
.container {
width: 38rem;
}
.wrap {
width: 33%;
overflow: hidden;
}
.slider {
width: 1300%;
white-space: nowrap;
font-size: 0;
transform: translateX(calc(-500% / 13));
transition: transform 0.4s;
}
.test {
height: 50px;
}
.test:hover ~ .wrap .slider {
transform: translateX(calc(-800% / 13));
}
.item {
display: inline-block;
height: 8rem;
width: calc(100% / 13);
background: limegreen;
font-size: 30px;
}
.item:nth-child(even) {
background: orangered;
}
<div class="container">
<div class="test">test</div>
<div class="wrap">
<div class="slider">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
</div>
</div>
</div>

Show a list of items as grid or column depending on the device

I have a basic need.
I have n images I want to display. I want to display them in rows, each row containing 3 images, if I am on a browser on a computer. I want to show them in a column, i.e. one below the other, if I am on a mobile device.
I do not want to use bootstrap.
Currently I am thinking to manage this with angular/flex-layout, but is seems that there is a bit of work (e.g. find the number of rows dividing by 3 and so on).
I am wondering if there is a simpler way.
This is very easily done with css media queries and flexbox.
.item {
width: 50px;
height: 50px;
background-color: tomato;
width: 100%;
margin: 8px;
}
#media (min-width: 720px) {
.list {
display: flex;
flex-wrap: wrap;
}
.item {
width: calc(33% - 16px);
}
}
<div class="list">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<!-- however many items you want -->
</div>
Live demo

How do I split a 1170 pixels grid into 8 boxes?

I need to split a 1170 grid into 8 boxes of X each with each box having the same amount of padding on the left and right. I can't seem to get it right :(
I managed to do 134 x 8 pixels and then a gutter of 14 each but that doesn't work because then the first and last box wouldn't have the same padding.
You could try calc
padding: 7px;
width: calc(12.5% - 14px);
More on Calc at W3Schools.com
If you are able to use flexbox, you can get even spacing in only a few lines instead of calculating by hand. The best resource I've found for flexbox is https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.container {
width: 1170px;
display: flex;
justify-content: space-between;
}
.item {
border: 2px solid red;
width: 50px;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
As commented, flex makes it easy.
+ selector will help to manage visually even padding
.flex {
display:flex;/* block level */
width:1170px;/* any values here or none */
height:100px;/* whatever: demo purpse*/
margin:auto;
background:lightgray;/* whatever: demo purpse*/
}
.flex div {
flex:1;/* sprays child evenly to fill whole space*/
padding:1em;
background:gray;
background-clip:content-box;/*show box minus padding area */
}
.flex div + div {/* make padding visually even */
padding-left:0;
}
div div {
display:flex;
align-items:center;
justify-content/* it's not text-align*/:center;
}
/* not just sure if that would be fine ? */
.flex:hover div {
padding:21px;
box-shadow:0 0 0 1px white
}
<div class=flex>
<div>average 128px each</div>
<div>width for content</div>
<div>is less or more</div>
<div>according to font-size</div>
<div>padding is 1em</div>
<div>but could be</div>
<div>static units</div>
<div>such as pixels</div>
</div
you do not want to use flex because you (unfortunate you) run IE8 ? display:table + table-layout:fixed will do the job for you
.flex {
display: table;
/* block level */
table-layout: fixed;
/* sprays child evenly if no width is specified*/
width: 1170px;
/* any values here or none */
height: 100px;
/* whatever: demo purpse*/
margin: auto;
background: lightgray;
/* whatever: demo purpse*/
}
.flex div {
display: table-cell;
padding: 1em;
background: gray;
background-clip: content-box;
/*show box minus padding area */
}
.flex div + div {
/* make padding visually even */
padding-left: 0;
}
div div {
vertical-align:middle;
text-align : center;
}
/* not just sure if that would be fine ? */
.flex:hover div {
padding: 21px;
box-shadow: 0 0 0 1px white
}
<div class=flex>
<div>average 128px each</div>
<div>width for content</div>
<div>is less or more</div>
<div>according to font-size</div>
<div>padding is 1em</div>
<div>but could be</div>
<div>static units</div>
<div>such as pixels</div>
</div
For some reason my jsFiddle here wouldn't work but I got eight columns working here: http://codepen.io/anon/pen/zoyEme
Make two half columns then put four columns in each of those for a total of eight.
Code:
.container,
.row,
.col-lg-6 {
padding-left: 0;
padding-right: 0;
}
div {border: 1px dotted red;}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-lg-6">
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
</div>
<div class="col-lg-6">
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
<div class="col-lg-3">
ONE
</div>
</div>
</div>
</div>

segmenting parent div height to use for child divs

I have a div with an specific height. i want this: i put some nested div's inside this div an tell them use specific percentage of height of the parent div. for example: div1=10%, div2=50% and div3=40%. Im talking about height.
Im using bootstrap and i can control location of parts of a row via col-*, But i want this for height of a parent div. How i can achieve this via Bootstrap?
<div id="parent" stele="height:500px;">
<div class="child">text 1</div>
<div class="child">text 2</div>
<div class="child">text 3</div>
</div>
Bootstrap grid system will make it easy for you to make responsive columns, because that is a cumbersome part to handle yourself for differing screen-sizes without horizontal scrolling. For height, you can rely on plain CSS styles, because vertical scrolling is not a problem.
Whatever your use-case be, just remember that percent dimensions are always relative to an element's parent. So if you want to give an element a height of 10% you need to consider the question: 10% of what?.
Following snippet will hopefully make it clear to you.
Snippet:
.parent { height: 120px; border: 1px solid gray; }
.parent div:nth-child(1) { height: 20%; background-color: #f00; }
.parent div:nth-child(2) { height: 50%; background-color: #00f; }
.parent div:nth-child(3) { height: 30%; background-color: #0f0; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row">
<div class="parent col-xs-10 col-xs-offset-1">
<div class="child">text 1</div>
<div class="child">text 2</div>
<div class="child">text 3</div>
</div>
</div>
</div>

Best Practice for CSS Clear or Overflow [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Having a discussion with a co-worker on what is best practice with CSS clear / overflow. Please shut one of us up and explain why one is better than the other.
JOEL'S CODE (using overflow):
<style>
.container { overflow: hidden; }
.one, .two { float: left; width: 50px; height: 50px; background-color: red; }
</style>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
CHRIS' CODE (using clear):
<style>
.clear { clear: both; }
.one, .two { float: left; width: 50px; height: 50px; background-color: red; }
</style>
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="clear"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="clear"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="clear"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="clear"></div>
</div>
Both make this image:
Who is right? :)
If you are in a situation where you always know what the succeeding element is going to be, you can apply the clear: both; value to that element and go about your business. This is ideal as it requires no fancy hacks and no additional elements making it perfectly semantic. Of course things don't typically work out that way and we need to have more float-clearing tools in our toolbox.
http://css-tricks.com/all-about-floats/
overflow:hidden is best used when you have a container which is smaller than the content inside; whereas clear:both is best used when you want a floating container to NOT position itself alongside the nearest container.
looking at your red squres example, you would want to use clear rather than overflow, but not as its done here. perhaps something more like:
.container { width:110px; clear:both; }
.one, .two { float: left; width: 50px; height: 50px; margin-right:10px; background-color: red; }
basically you are both wrong and right. Joel uses the better html approach, but Chris is using the right bit of CSS code, just in the wrong way.
Here is a compromise:
DEMO jsBin
CSS:
.container { display:table; }
.one, .two { float: left; width: 50px; height: 50px; background-color: red; margin:1px;}
HTML:
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
<div class="container">
<div class="one"></div>
<div class="two"></div>
</div>
I'd write it this way. CHRIS's code is something i'd not write but just cause of the redundant empty DIVs.
Since the CSS in both cases is about the same in terms of complexity and maintainability, the solution with simpler (and hence, smaller) HTML and overall payload wins. It isn't a big difference, and with compression, the repeated code will likely disappear, but simpler and smaller is always better if all else is equal.
What about the micro clearfix? No added markup, no overflow: hidden; clipping, cross browser support for IE 6+.
My personal preference is the overflow:hidden technique. I think this is because floating something is a style decision. To place a class of clear in the markup seems to me like adding style information into the data layer. It's similar (but nowhere near as bad) as adding inline css. (Infact, if you think about it, you might as well add style="clear:both" to the div you wish to add class="clear" to).
This is of course my personal opinion. I don't claim one is better than the other. But I have very rarely encountered a problem with overflow:hidden.

Resources