I have a lot of blocks, and I want to order them in a table-like way. The problem is, that because of the margin-right of the last one, they don't really fit in the way I want them to. See this example. I want to have 4 blocks on one line, how can I achieve that?
CSS:
.box {
width: 500px;
height: 10000px;
}
.block {
float: left;
width: 100px;
height: 100px;
margin-right: 30px;
background-color: #0f0;
margin-bottom: 50px;
}
Use last-child, a CSS selector, like so: http://jsfiddle.net/QwGV5/1/
.block:last-child {margin-right: 0;}
For compatibility: http://caniuse.com/css-sel3
div:last-child {
margin-right: 0;
}
But this will only work in IE9+ (maybe 8, can't remember)
Otherwise, put a class on the last one.
Here's an update to your fiddle http://jsfiddle.net/QwGV5/2/
I think for what you want to do though, you'd actually want it on every 4th div. So you can use nth-child
.box div:nth-child(4n) {
margin-right: 0;
}
Eaxmple: http://jsfiddle.net/QwGV5/4/
You can make a new class for the last block in each row (e.g. .last) and make margin-right:0 for that class.
HTML:
<div class="box">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block last"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block last"></div>
</div>
CSS:
.last { margin-right: 0; }
JS Fiddle Example
Related
Ok, I've been taught that you only should use a wrapper <div></div> if it is absolutely necessary, since creating an unneeded element in the DOM wastes resources.
However, let's say you have 5 child elements which all need a left margin of 10%. would writing the css for each one be less intensive than making a new div?
So the code would look something like this:
scenario 1: Wrapper
<div class='wrapper'>
<div class='div1'></div>
<div class='div2'></div>
<div class='div3'></div>
<div class='div4'></div>
<div class='div5'></div>
</div>
.wrapper{
margin-left: 10px
}
scenario 2: No Wrapper and all elements styles with one css entry
<div class='div1'></div>
<div class='div2'></div>
<div class='div3'></div>
<div class='div4'></div>
<div class='div5'></div>
.div1,
.div2,
.div3,
.div4,
.div5{
margin-left: 10px
}
scenario 3: No Wrapper and the elements already have styling
<div class='div1'></div>
<div class='div2'></div>
<div class='div3'></div>
<div class='div4'></div>
<div class='div5'></div>
.div1{
margin-left: 10px
}
.div2{
margin-left: 10px
color: red
}
.div3{
margin-left: 10px
color: blue
}
.div4{
margin-left: 10px
color: white
}
.div5{
margin-left: 10px
color: green
}
Also, would the number of elements that need the same styling change your answer??
Thanks for your thoughts, I want to start forming good habits :)
The better solution is:
HTML
<div class="div div--one"></div>
<div class="div div--two"></div>
<div class="div div--three"></div>
CSS
.div {
margin-left: 10px;
}
.div--two {
color: red;
}
.div--three {
color: yellow;
}
This is obviously just an example. Please do not name your classes 'div'.
I thought this would be (relatively) easy, but from the answers it seems harder than I anticipated.
Perhaps even impossible!
GOAL
I'd like to have a large list of div elements that can arbitrarily be assigned a .left or .right class.
All the .left divs should stack up underneath each other on the left hand side, the .right divs should stack up underneath each other on the right hand side. The number of divs in each class is arbitrary.
THREE CONDITIONS
The height of each div will not be known in advance
I would like them to stack up underneath each other on the assigned
side, regardless of how many divs are present, what order they appear in, and how many are
assigned to either side.
I don't want to use a 'wrapper' div as some have suggested. This is
because the solution must cater for random quantity and ordering of
.left and .right divs (see example below).
Ideally I'd like it to be a pure html / css solution, as backwards compatible as possible - though I realise this may prove unrealistic.
SAMPLE HTML
<div class="left">left one</div>
<div class="left">left two</div>
<div class="right">right one</div>
<div class="left">left three</div>
<div class="right">right two</div>
<div class="right">right three</div>
<div class="left">left four</div>
<div class="right">right four</div>
<div class="right">right five</div>
<div class="left">left five</div>
<div class="right">right six</div>
<div class="right">right seven</div>
UPDATE
After so many answers I'm impressed by the range of answers/techniques, but none of them quite meet all of the conditions.
Hence I'm staking a quarter of my meagre reputation on trying to get a solid solution!
UPDATE 2
It seems that my original goal is undoable. Therefore I have not marked any as the answer, although having put up a bounty I awarded it to Josh who gave me the best way of (almost) achieving that, along with great explanations of the css he used.
Thanks everyone for your help and ideas.
Here's what I'd recommend:
Fiddle requiring no hacks
Here's the key CSS that we're including:
#media (min-width:400px){
.left {
width: 60%;
}
.right {
width: 30%;
float: none;
margin-left: 100%;
transform: translateX(-100%);
}
}
Explanation of this CSS
What that's doing is pushing your .right elements completely out of the container to the left, and then dragging them back their entire width.
The position: relative; and left: 100%; tell the element that it needs to display off the right edge of the container.
The transform: translateX(-100%); then tells the element that it needs to display to the left (hence the negative) 100% of its width - which drags it to be flush with your right edge.
With this solution, items can be reordered arbitrarily and no additional calculations need to be made.
I hope this helps!
Update:
Fiddle requiring one hack not dependent on DOM order
Here's what we changed:
CSS
.right {
width: 30%;
float: none;
margin-left: 100%;
transform: translateX(-100%);
margin-bottom: -1.2rem; /* New */
margin-top: calc(1.2rem + 5px); /* New */
}
.right:first-of-type {
margin-top: 0; /*optional - if there's a preceding element on the page this will prevent it from being shifted downward*/
}
What this is doing is making the DOM think these elements have negligible space they're taking up in the document flow, when in reality we're just screwing with its margins to make it display where it was before. This shouldn't fail with an arbitrarily ordered set of elements in an arbitrarily long list. Essentially we're doing something very similar to what float does in removing the element from document flow - but we're only making it reserve space as if it had no height. Plus, it doesn't get dragged to one side of the screen or the other.
The calc(1.2rem + 5px) for margin-top is basically saying: add this margin-bottom we took away back, plus the original 5px margin we had before.
I use rem units here because you don't have any defined font-sizes. Generally, you would want to use em, and we could have here. I chose 1.2 as that's the default line-height for these items. This fix, then, would only work for one line of text in an element. You'll need to have some awareness of the height of the element being rendered in order for this to work.
Hope that helps!
Update, the second
Fiddling with minimal JavaScript
First, add this:
CSS
.right.last {
margin-top: 0;
}
Then add this:
JavaScript
var rights = document.querySelectorAll(".right");
rights[rights.length-1].className += " last";
And you won't see that gap on the last element any longer.
I am adding one more answer here. I don't want to spoil the previous answer. However, with this answer the necessity to wrap the divs is eliminated.
JSFiddle here
<div class="left">left one</div>
<div class="right">right one</div>
<div class="left">left two</div>
<div class="right">right two</div>
<div class="left">left three</div>
<div class="right">right three</div>
<div class="right">right four</div>
<div class="right">right five</div>
Added float:left;clear : left and float:right;clear:right css properties
.left {float:left; background: coral; margin-bottom: 5px;}
.right {float:right; background: mediumaquamarine; margin-bottom: 5px;}
#media (max-width:400px){
.left, .right {
width:100%;
}
}
#media (min-width:400px){
.left {
float: left;
clear : left;
}
.right {
float: right;
display: inline-block;
margin-left: 10%;
clear : right;
}
}
Put all the left side elements inside a separate div. Also the right elements inside a separate div.
Then make the css styling as i did in below code snippet.
It works! Hope this is what you need!
.left {float:left; background: coral; margin-bottom: 5px;}
.right {float:right; background: mediumaquamarine; margin-bottom: 5px;}
.left-wrapper{ float:left; width:60%;}
.right-wrapper{ float:right; width:30%;}
#media (max-width:400px){
.left, .right, .left-wrapper, .right-wrapper {
width:100%;
}
}
#media (min-width:400px){
.left {
width: 100%;
}
.right {
width: 100%;
float: none;
display: inline-block;
margin-left: 10%;
}
}
<div class="left-wrapper">
<div class="left">left one</div>
<div class="left">left two</div>
<div class="left">left three</div>
</div>
<div class="right-wrapper">
<div class="right">right one</div>
<div class="right">right two</div>
<div class="right">right three</div>
<div class="right">right four</div>
<div class="right">right five</div>
</div>
If you can figure out the height of the first few elements on the left side (assuming it starts with the left side) before the right side then this would be possible: http://jsfiddle.net/n467un0c/29/
.left {
float:none;
background: coral;
margin-bottom: 5px;
}
.right {
float:right;
background: mediumaquamarine;
margin-bottom: 5px;
position: relative;
top: -46px; /** this value should be the height of the elements added together (including the margins) on the left side BEFORE the first element on the right side... in this case it would be 'left one' and 'left two' before 'right one' **/
}
#media (max-width:400px){
.left, .right {
width:100%;
}
}
#media (min-width:400px){
.left {
width: 60%;
margin-right: 10%;
}
.right {
width: 30%;
clear: right;
}
I have updated the JSFiddle here. It is working now. I have added extra wrappers to the left divs and right divs.
<div class="left">
<div class="left">left one</div>
<div class="left">left two</div>
</div>
<div class="right">right one</div>
<div class="left">left three</div>
<div class="right">
<div class="right">right two</div>
<div class="right">right three</div>
<div class="right">right four</div>
<div class="right">right five</div>
</div>
I have structure like:
<style>
#main{
max-width: 500px;
margin: 0 auto;
overflow: hidden;
border: 1px solid red;
}
#container{
margin-right: -50px;
}
.block{
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid grey;
margin-right: 30px;
}
</style>
<div id="main">
<div id="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
</div>
If I have wide width it looks like
http://i.stack.imgur.com/3I1yM.png
It's ok.
But if I use narrow it sucks
I need that internal bloks is aligned to center like this
http://i.stack.imgur.com/5GXMJ.png
Hi what you need here is the property text-align:center:
#container{
margin-right: -50px;
text-align:center;
}
The demo http://jsfiddle.net/u5HHc/
What about this?
http://jsfiddle.net/ALR8P/3/
Remove margin from blocks, user text-align justify and add word spacing if you want some fixed space for your blocks on the last row.
#container {
letter-spacing: 10px; //word-spacing: 10px; //to space blocks on last row
text-align: justify; //to align everything to the borders on the first lines
padding: 0px 10px; //to separate the blocks from the borders a little
}
.block {
margin-right: 0px;
}
It looks wrong when width is too small and only one block fits on each row but maybe there you need some media query to make your css responsive to fix that on that special case.
EDIT: letter-spacing works better crossbrowser http://jsfiddle.net/ALR8P/5/, you may want letter-spacing: 30px; since your margin was 30px
This is my HTML
<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
How can I get this image by using only CSS? I guess with float, but how can I get the fifth div next to the first one?
Changing the HTML is NOT (!) an option.
My first comment would be that class names can't start with a number, so I really hope that you can edit the HTML for that. To answer your question ignoring this fact, if each element has a class, this is pretty simple. Just do this:
div {
float: left;
width: 200px;
height: 100px;
border: 1px solid #000;
display: block;
clear: left; }
div.5 {
float: none;
clear: none;
display: inline-block; }
Preview: http://jsfiddle.net/Wexcode/mvwSL/
You have a few options:
Float and negative margins:
.five{float:right; margin-top:-500px;}
Demo
Or margins only
.five{margin:-500px 0 0 200px;}
Demo
Or relative positioning:
.five{position:relative; top:-500px; left:200px;}
Demo
Or absolute positioning:
.five{position:absolute; top:0; right:0;}
(Make sure the container is set to position:relative;)
Demo
First, classes with numeric values are not valid. You're quite screwed if you can't change them... With proper classes, a solution might be:
CSS :
div {float:left;clear:left}
div.c5 {float:right}
jQuery
$("div.c5").insertBefore("div.c1")
See this fiddle
#Wex
div:last-child{
float: none;
clear: none;
display: inline-block;
}
Try below: It works as you required but horizontally, you want vertically. But am sure it might help you.
#outer {
width: 500px;
margin: 300px 0 0 10px;
}
.inner {
background-color: red;
width: 100px;
height: 100px;
float: left;
margin: 10px;
}
<html>
<body>
<div id="outer">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
<div class="inner">4</div>
<div class="inner">5</div>
<div class="inner">6</div>
<div class="inner">7</div>
</div>
</body>
</html>
Let's say I want to have two columns. The right one is 200px wide, and the left one just takes up the remaining width. Is this possible? What do I set the width of the left column to be?
Update: Solved Using Flexbox
Now that we have Flexbox (with over 95% support globally) this layout (and others) can be easily achieved without styles being dependent on source order.
Flexbox Example:
HTML
<div class="flex-container">
<div class="flex-column"> Big </div>
<div class="fixed-column"> Small </div>
</div>
CSS
.flex-container {
display: flex;
}
.flex-column {
flex: 1;
}
.fixed-column {
width: 200px;
}
Live Demo using Flexbox
Solved Using Floats
The trick is matching the remainder column’s margin to the floated sidebar’s width. Remember, source order matters when using floats, so we make sure the floated element comes first.
Example right-aligned small column:
HTML
<div id="Container">
<div id="RightColumn">Right column</div>
<div id="LeftColumn">Left column</div>
</div>
CSS
#RightColumn {
float : right;
width : 200px;
}
#LeftColumn {
margin-right : 200px;
}
Live Demo
Right-aligned small column
Left-aligned small column
You float the left column and set margin to minimum of the width of the left column.
<div id="Container">
<div id="LeftColumn" style="float: left; margin-right: 200px;"></div>
<div id="RightColumn" style="float: right; width: 200px;"></div>
</div>
OR
<div id="Container">
<div id="RightColumn" style="float: right; width: 200px;"></div>
<div id="LeftColumn" style="margin-right: 200px;"></div>
</div>
If you don't want to float divs, you can do the following:
.rightDiv {
position: absolute;
right: 0;
width: 200px;
}
.mainDiv {
position: absolute;
left: 0;
right: 200px;
}
Yes, it is possible. Set the right column's style to float: right and width: 200px, and the left column will be the content and take up the rest of the width.