Displaying elements in multiple rows using CSS - html

I have a fixed width container <div> that displays one or more widget <div>s. I want it to look like this:
<- grey blocks are widgets, red border is the container
Simplified, my structure in HTML looks like this:
<div id="container">
<div id="widget1">1</div>
<div id="widget2">2</div>
<div id="widget3">3</div>
<div id="widget4">4</div>
<div id="widget5">5</div>
<div id="widget6">6</div>
<div id="widget7">7</div>
</div>
Considerations
Widgets will have a fixed height e.g. 100px
Widgets will have a fixed width e.g. 100px but they may also be a multiple of that width (plus any margins crossed - see widget 1)
Widgets should be spaced nicely with a margin (or similar) e.g. 10px
I don't know how many widgets there will be (the user can assign as many or few as they like to the container).
The container is a fixed width but doesn't have any "visual" styling (the red border is there for demonstration)
Solution has to work in modern browsers (and MSIE7) and would ideally be pure CSS.
Because of consideration 4. I can't assign additional markup e.g. row div, classes (.first-child, .last-child) and because of 2. :nth-child wouldn't work AFAIK.
Things I've tried
margin-left on widgets with :first-child setting margin-left: 0 won't display a new row properly.
margin-right on widgets with :last-child setting margin-right: 0 the first row forces the container div wider and last-child isn't supported until MSIE9.
equal left and right margins (e.g. margin: 0 5px 10px) forces the container wide again.
overflow - works great in my head! Not so much with either margins or padding.
Is there a way to do this in CSS?
http://jsfiddle.net/agtb/VHXGT/

I believe you are thinking too complicated :-)
If I understand you correctly you don't need any special handling of the separate widgets. Just give the widgets an all around margin of half the spacing, and the container the same margin but negative.
#container {
width: 440px;
margin: -5px;
}
#container div {
background-color: gray;
height: 100px;
width: 100px;
float: left;
margin: 5px;
}
See http://jsfiddle.net/SGdG3/1/

set container width 400 and the first div width 200 float left, rest width 100 float left

Related

Simple way of using the full browser available width (CSS Responsive Design)

3 div.
body margin of 10px.
Picture on the bottom
I want the divs to equally have the same width, the same margins on the sides while also covering/using the whole browser's width whichever size it is (desktop, tablet, mobile)
Here's what I did by using pourcentage and what I believe:
" The full browser width is 100%
If the div's margin are 10px and the body's margin are 10px then
The div's width would be around 30%.
Let's try 30%.
It fits - blank space too.
Let's try 30.5%.
Blank space, it's not equal on the sides.
Let's put 32%.
etc. "
but often I get extra blank space on the right or one div to go down because it's actually too wide.
Is there a more simple way to do this? Properties?
Thank you.
Design:
Media queries:
Your issue stems from the fact that you are mixing relative units with absolute ones - pixels are an absolute unit as 10px is always 10px, but a percentage is relative to the screen width, so no matter how close you can get it to fitting the full width of the screen, as soon as you change the width of the screen all of the values are going to change.
You have (at least) two options here:
First, switch all your units to percentages, so that every measurement is relative to the width of the screen. In other words, if you use percentage based margins, you will know exactly how much space you can allocate to each thing.
Alternatively, if you really need the margins to be an absolute pixel width, use CSS calc:
This feature of CSS allows you to mix unit types easily, and let the browser do the math to figure it out.
For example:
width: calc(33.333% - 20px);
will style the div to take up one third of the screen width, minus the width of a 10px margin on the left and a 10px margin on the right.
If all three divs have this width, the total space taken up will equal to 100% of the screen, with the space for all of the margins accounted for.
(if you want the first and last divs to have no margin on the left and right respectively, just change the calculation to match!)
More Information About 'Calc'
Extra tip! Remember that white-space in your code will add spaces in between your elements, so if you style everything to fill exactly 100% width, these extra spaces may still cause your items to break if you have not dealt with this
I would say the best way to approach this is have container elements for each div, so a structure like this:
<div class="container-full">
<div class="container-third">
<div class="content">
Hello world
</div>
</div>
</div>
.container-full{
width: 100%;
}
.container-third{
width: 33.33%;
padding: 10px;
}
.content{
width: 100%;
}
Utilize padding, instead of margin. Make sure to use box-sizing: border-box
display:flex is already widely suported, so you can rely on that instead of floats.
if you don't use box-sizing:border-box; for all the elements - you could at least for the divs in question along with a 10px padding.
Here goes sass:
.container {
display:flex;
& > div{
flex:0 0 33.33%;
padding: 10px;
box-sizing: border-box;
}
}
or you could use a percentage margin between the divs.
.container div{
width:30%;
float:left;
margin-right:5%;
}
.container div:last-child{
margin-right:0;
}

padding within in a div

I simply can't figure this out: I have a div that is centered on screen with a width of 60%. Inside this div I have 3 more divs that float left with the width of 33% and have a gray bg color. The divs are filled with text and one image per div. Each div should now take 1/3 space inside the "maindiv". This works fine but as soon as I give my 3 "contentdivs" a padding so the text gets seperated a bit the third div wanders below the others. I also want a margin around my 3 divs so there is a gap between all the divs. But this only works if I give the divs a width of like 31%. As soon as I shrink my browser though, the third one pops up below the others again.
How it looks now:
How it looks with a width of 33.33%
How can fix this? I mean I set the divs to a relative width by setting the size in %. So the divs should just shrink as soon as I shrink my browser window. I tried to surround all the divs by other divs and messed around with margins and paddings but it just won't work.
Most likely it’s box model’s fault. Paddings, margins and borders can be added together in different ways. Add box-sizing:border-box to the container and its elements. Most certainly this brings about what you intended to do, and width:33.3333% wil work out as expected.
Adding margin still breaks the item? There’s another great thing called calc(). Assumed you have a margin of 8px, that’s just a few pixels too much. With calc(), you can subtract the additional margin like this:
.item{ width:calc(33.3333vw - 8px); }
Note that there must be whitespace around the minus. Try it and include your margin.
Apply box-sizing: border-box to all related elements (or the entire document, as Bootstrap does). http://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
Then, rather than margin, use padding for the outer spacing. This eliminates the need to do mental math altogether.
div {
box-sizing: border-box;
}
.one-third, .inner, .full-width {
padding: 8px;
}
.one-third {
float: left;
width: 33.333%;
}
.inner {
background-color: pink;
}
<div class="full-width">
<div class="inner">Full-width div</div>
</div>
<div class="one-third">
<div class="inner">Content</div>
</div>
<div class="one-third">
<div class="inner">Content</div>
</div>
<div class="one-third">
<div class="inner">Content</div>
</div>
Fiddle demo
Your best bet would be to get the three columns and margins to equal 100%. This is fairly easy if you know you are only having three columns:
.item {
width:32%;
margin-left:2%;
}
.item:first-child {
margin-left:0;
}
As long as there is only three it will always add up to 100% as you are overriding the first .item. If you don't override the first item then you will have a space before your columns and the last column won't fit. Mixing pixels and percentages will give you issues in a grid (unless they're paddings and you are using box-sizing). Margin is not included in the box-sizing as it is not part of the main box model.

How to detect (and style) if two floating DIVs are stacking vertically due to lack of container width?

I'm implementing kind of a toolbar in a responsive design. The toolbar sections are implemented as floating DIVs which go side by side with a nice gap between them. However, on lower width devices the DIVs are getting stacked vertically as there is less and less space. That's of course a good thing, but there is one little problem: they are stacking on each other without a vertical gap, or with twice as big vertical gap then it should be (wether I use padding on the container bar or margin on each toolbar section DIV). Neither of this two look too great.
The DIVs can have dynamic width, I don't know exactly on which container width they will get stacked, so I can't use some kind of width breakpoints and media queryies.
How could I style the DIVs taking the possible vertical stacking into account, so that in case of vertical stacking, there would be correct gap between them?
I only need to support modern browsers (newer Chrome, newer Firefox, IE9+).
If you can't target them with a media query (because you are uncertain when they will stack) then you have no choice but to add a top margin (or padding, depending on your needs) to them both. This will keep them in line with each other when they aren't stacked (as they will both have the same top margin/padding) and it will give a vertical space between them when they collapse.
You can even add a negative top margin to the containing element so that your top margin on your floating divs won't have any visible effect until they collapse.
.container {
margin-top: -20px;
}
.box {
border: 1px solid #000;
width: 250px;
margin-top: 20px;
float: left;
height: 100px;
}
<div class="container">
<div class="box">
</div>
<div class="box">
</div>
</div>

How to make a div fill up remaining horizontal space

I have two divs. One that is floated left and one floated right. The one of the left has a width set to 18% and a min-width of 217px. I want to have the div on the right take up the remaining space, while also being able to resize to fit the window.
The problem I am having is that I can set the right div's width to 82% and to float right, which works until I make the window side too small, in which case the min-width of the left div kicks in and it stops shrinking. The right div doesn't have enough space to fit, so it is pushed down.
Here's some sample code.
HTML
<div id="div1">
stuff inside of it
</div>
<div id="div2">
stuff inside of it
</div>
CSS
#div1
{
float: left;
width: 18%;
height: 100vh;
min-width: 130px;
box-shadow: 0px .3em .2em #000;
z-index: 2;
}
#div2
{
width: 82%;
float: right;
z-index: 1;
}
So this is where I'm stuck, how should I approach fixing div2? I've tried using a table instead of divs, but a border appeared around the cells that I couldn't change and it removed my box-shadow, so I would prefer a solution without it.
Your thinking of using tables is somewhat on the right track, as table elements do actually have many properties that make them capable of such a thing, but as people are pointing out in the comments, it's no longer a valid approach to use table elements for the purposes of layout for non-tabular data.
This is why CSS implemented a set of style rules built to reflect those unique properties. You can set a container around two elements with the style display: table;, and then give it's children the style display: table-cell;
Setting the width for the right side div to 100% will ensure it always fills as much space as is available to it.
But, since table cells can't break to a new row when the content exceeds the width of the table, it will automatically adjust to fit. So when another div (the left one) has a specific min-width, the div on the right is given less space in order to keep the cells contained.
Here's an example using your code:
http://jsfiddle.net/Q5rjL/
CSS table display properties give you all the benefits of these unique elements, but without the semantic issues. They are great for complex layouts where other style display types fall short.
You can also contain floats with overflow:hidden:
#div2{
overflow:hidden;
z-index: 1;
}
The DIV will fill up the remaining space (http://jsfiddle.net/MAjwt/)

Making a button element fill available width

There are a lot of "fill available space" questions on this site, but my issue is a bit particular in that I've already gotten a solution, but it doesn't work for buttons. I'd like to understand why this doesn't work for buttons, and how I can make it work. I imagine it's just some browser-style for the button element that I need to override.
I have two floating elements within a (fixed-width, if that matters) wrapping div. The right element has fixed width, and the left element should take up whatever width remains.
I can accomplish that by setting the right element to have fixed width and float: right, and leaving the left element without any special styling. This works perfectly for divs. It also works for spans, but only if I set display: block on them. For buttons, I can't get it to work at all. I tried block, inline-block, and every obscure width value I could find on the MDN.
http://jsfiddle.net/wjFbD/2/
I don't know why I didn't think of just wrapping the buttons in divs earlier. Here's what I've come up with:
http://jsfiddle.net/SkczB/2/
This involves the overflow: hidden box formatting context trick (which I suspected was going to make an appearance here, but couldn't quite see where to fit it in). Highlights:
The two buttons are wrapped in divs with class buttonWrapper.
Those divs are formatted according to the trick I outlined in the third paragraph, above. The right div has float: right and a fixed width, the left div has no special styling.
We now apply the box formatting context trick. The left div is given overflow: hidden, which causes it to make space for the right-floated div.
We can now apply a left margin to the right div, and change its width, and the left div will always be the right size.
The divs create the desired "fill available width" effect for us, now we just have to put the buttons inside the divs and give them a height and width of 100%.
If it's the left button you wanted to have a fixed width, then basically repeat the above steps with left and right swapped.
This may not be exactly what you're looking for here, but here's an option that seems to have worked out for me with your fiddle.
If you've got a fixed width div that the elements are contained in, you could split get the remaining width of the div after button A has been set to fill up, say, 100 pixels and then set button 2 to be the remaining size.
Alternatively, another option would be to run it as percentages 20%/80%, 30%/70%, that kind of thing. Here's a fiddle that achieves what you're looking for on just the button wrapper at the bottom. I've applied specific classes for it and added divs around each button for a bit more control. The button wrapper divs are set to 20% and 80% respectively, while the button is set to fill 100% of the containing space.
Here's the modified fiddle and the modfied HTML/CSS. Hope it helps for what you're looking for...
http://jsfiddle.net/wjFbD/7/
HTML
<div class="btnWrapper">
<div class="buttonWrapperB">
<button class="left">
button Left
</button>
</div>
<div class="buttonWrapperA">
<button class="right">
button Right
</button>
</div>
</div>​
CSS
.btnWrapper
{
width: 100%;
background-color: #FEE;
border: 2px solid black;
margin-bottom: 10px;
height: 50px;
}
.buttonWrapperB{
float: left;
width: 20%;
}
.buttonWrapperB button{
width: 100%;
height: 50px;
}
.buttonWrapperA{
float:left;
width: 80%;
}
.buttonWrapperA button{
width: 100%;
height: 50px;
}
​
I adjusted the background opacity of your .right elements to see what was going on below them. It looks like the .left elements are not only taking up the remaining space-- they're also taking up the entire row. Weirdly, the text inside these elements is centered as if it were only taking up the remaining space.
If you want the same to work for the buttons, it seems like the only solution involves a little hack. Buttons are quite complex indeed.
button.left {
margin: 0;
position: absolute; /*this seems to be the only way to get the button to stay on the same row - floating it left won't even work*/
z-index: -1; /*hides the "overflowing" part below the right button*/
width: 100%; /*make the button stretch to the full width of the row*/
padding-right: 400px; /*add a padding-right hack so that text will be centered correctly - should be same size as fixed width .right element*/
padding-left: 0;
display: block;
}
See updated fiddle: http://jsfiddle.net/wjFbD/6/
starting with
One element has fixed width, and the other element should take up
whatever width remains.
here is my general solution:
<div class="container">
<div class="two">125 €</div>
<div class="one">my favorite provider</div>
</div>
(stylus syntax, in your mind just add {,},;)
.one // red
border none
height auto
overflow hidden
white-space nowrap
text-overflow ellipsis
.two // green
float left
white-space nowrap
text-overflow ellipsis
You can set the one green thing to a fixed width, but indeed, you do not even have to! Things full up nicely. And String get's truncated with an ellipsis, if it gets too long.
Things get a bit more complicated, when one of them is a <button> rather than a <div> (and I can't figure out, which style property differenciates them, so I would need to style away), but anyway, with a wrapper, that also works:
→ See full codepen here. (Feedback appreciated.)