I run in to this problem quite often, and it usually results in me spending additional time to try and address the problem. Essentially it is a straightforward layout as follows:
HTML:
<div id="container">
<div id="items">
<div class="item">
(data here)
</div>
<div class="item">
(data here)
</div>
<div class="item">
(data here)
</div>
<div class="item">
(data here)
</div>
-- repeats --
</div>
</div> <-- end container -->
CSS
#container {
margin: 0 auto;
width: 980px;
overflow: hidden;
}
#items {
float: left;
width: 980px;
min-height: 1000px;
}
#items .item {
float: left;
width: 230px;
height: 230px;
margin-right: 20px;
margin-bottom: 20px;
}
My intended result is to have a 4 x 4 grid displaying items. As you can see from my CSS above, I am adding a right margin to each item in order to space them out. The only problem with this is that the fourth item in each row drops down to the next row (which is obviously being caused due to the right margin on the item):
(230 x 4) = 920 + (20 x 4) = 80 = 1000 (but the container width is 980). So instead of 4 items on each row I get three.
If the right margin on every fourth item isn't included then all four items fit perfectly within the constraints of the parent DIV. I know I can just add a separate class for the fourth item and set it's right margin to 0px but this means I have to add additional checks in my scripting when displaying products dynamically.
Ideally what I would like is a pure CSS solution that works well in all major browsers AND IE7. Does anybody know of any?
You could try using percentages rather than fixed widths for your items.
#items .item {
float: left;
width: 23%;
height: 230px;
margin-right: 2%;
margin-bottom: 20px;
}
Fiddle: http://jsfiddle.net/kboucher/Mv7sh/
To target every fourth child of an element you can use :nth-child(x), but that is not supported in IE8 and earlier. w3schools doc
:last-child won't really do it because you would have to wrap every group of four.
However, depending on your design, a width and height of 225 instead of 230 would even out at 980 with the margins.
And unless you have a specific reason to only have margin-right, you could split it into margin-right and margin-left with a value of 10.
Related
I guess I have the simplest problem ever and cannot find a ready solution.
I need to make a grid with fixed widths and fixed distance between them.
I need x columns a 400px (x = total width/400), and during browser resizing I would need this grid to shrink, column by column (columns must always keep their width size and distance between them).
The content flows over all columns and should spread out over all columns.
That's why I don't like any open source grid system (Boostrap, Skeleton, etc.) they all use %width, and columns always change width on resizing.
What would be the simplest way?
Edit/Clarification:
This is how it looks without columns: http://jsfiddle.net/xjrt8qrm/16/show/
<div>See the fiddle</div>
I want it to have x columns. x is the maximum possible amount of 400px columns, depending on the users resolution. I want only one row of columns, so the content spreads like on a newspaper from top to bottom.
So it will look somehow like this on a PC: http://i.imgur.com/kmd620p.png (You can ignore the text/comments there).
It's pretty simple. The container holds the contents together. Float left will cause them to line up left to right. When the container runs out of space to hold them, they'll drop from the right to a row below one at a time. The clear div clears out the float so that it doesn't propagate to other nearby classes. Obviously, you'll have to handle padding, margins, etc as your style dictates.
If you needed newspaper like vertical layout, you could try a solution like this one
You could use media queries in this manner or even overflow:none to hide columns that didn't fit if that was your desired behavior.
Here's a simple solution:
HTML:
<div class="container">
<div class="fourhundred">
Div 1
</div>
<div class="fourhundred">
Div 2
</div>
<div class="fourhundred">
Div 3
</div>
<div class="clear"></div>
</div>
CSS:
.fourhundred {
width: 400px;
margin: 10px;
float: left;
}
.clear { clear:left }
.container { width: 100% }
This is why flexbox have been designed. Add to your container:
.container {
display: flex;
justify-content: space-between;
align-content: space-between;
width:100%;
}
as in this Fiddle
Simply used width: calc(100% / 3); you can use any value instead of 3. Divided the whole width into 3.
here is the Fiddle Demo
<div id = "main">
<div id ="sub">One
</div>
<div id ="sub">Two
</div>
<div id ="sub">Three
</div>
</div>
CSS Part
#main{
border: 2px solid black;
height:100px;
width:100%;
position: relative;
display:flex;
}
#sub{
border:1px solid red;
width: calc(100% / 3);
height: calc(100% - 40px);
padding:10px;
margin : 5px;
display:inline-block;
}
The Bootstrap 3 docs say:
Rows must be placed within a .container for proper alignment and padding.
Does this mean that one of their ancestors should be a container or that their immediate parent should be a container?
Having looked at the examples, I think the former interpretation is correct as containers have fixed widths for specific display sizes:
#media (min-width: 1200px) {
.container {
width: 1170px;
}
...
}
And as such they cannot be placed inside other components (e.g. .panel-bodys).
In other words, is the following correct markup in Bootstrap 3?
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Title</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-6">
Col 1
</div>
<div class="col-xs-6">
Col 2
</div>
</div>
</div>
</div>
It means that one of their ancestors should be a .container.
And your code is correct, as the docs mention:
Note that, due to padding and fixed widths, containers are not
nestable by default.
Some info on why rows need to be inside .container.
Rows have margin-left: -15px; margin-right: -15px. That's because rows should only contain columns, e.g. col-md-12, and those columns have padding-left: 15px; padding-right: 15px. So that negative margin on the row will mean that effectively columns will line up 'flush' with the edges of the grid.
Because of that negative margin, you need to have the .container because it has padding-left: 15px; padding-right: 15px;. Without that, your rows would go off the page.
Full width designs
Of course, if you do wrap everything in .container then you'll have a fixed width which is not right for everyone. So, if you don't want that, you can go against Bootstrap's rules and place your rows inside a parent that has padding: 0 15px to offset the negative margin on rows (the would cause container to go off the screen and cause a scrollbar).
This demo shows both situations described above.
The .container class is responsible for the padding and margins of its children. Hence, whatever content you put inside the containers inherhits those properties unless overridden. There's nothing unusual going on here.
Take a look at the source for further information:
.container {
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
}
I know there are tons of CSS side-by-side positioning questions, but I have a unique scenario that I haven't seen any answer that works.
I am stuck with the following HTML block, that I cannot change:
<div class="outer">
<div class="inner">
<label>...</label>
<table>...</table>
</div>
</div>
The "outer" div has a fixed width that can change at runtime. The "inner" div can repeat any number of times, and has a width of 100%.
I need to have each <label> element take up a fixed width of 150px, with the <table> element taking up the rest (ie, 100% of the remaining space).
No matter how I try to float the elements, etc, I can't get it to work correctly. Also, this application will only be used on machines with latest versions of Chrome / Firefox, so IE backwards-compatibility is not an issue.
Thanks!
You could add a padding left to the .inner and then negatively margin the label back into that space.
Like this:
.inner {
padding-left: 150px;
}
label {
width: 150px;
margin-left: -150px;
float: left;
}
table {
width: 100%;
border: 1px solid #000;
}
http://jsbin.com/IdayeTOp/1/edit
I would consider myself to be an intermediate/advanced CSS/HTML coder but I'm stumped on how to do the following scenario.. I'm starting to think it is impossible but I really want to believe it is..
Let's say the wrapper width is 1000px.
Within it is three columns. The two outside columns are the same width, this width is decided by the center column. The center column is the only one with content, just one line of text with 30px of padding on either side. So if the line of content is 100px with padding, than the other two columns would be (1000-100)/2 each..
Is there a dynamic way to have the two outside columns adjust to the varying width of the center column that is defined by its varying contents, one line of text?
Graphic of what I am trying to accomplish:
The very closest I could come up with was to use display: table; and table-cell. This creates the dynamic effect you're looking for, but I don't think you can get your desired effect without setting an explicit width to the center element.
HTML:
<div id="wrap">
<div id="left">
Left
</div>
<div id="center">
center
</div>
<div id="right">
Right
</div>
</div>
CSS:
#wrap
{
width: 1000px;
display: table;
}
#wrap div
{
display: table-cell;
border: 1px solid #000;
width: auto;
}
#center
{
padding: 0 30px;
text-align: center;
}
You can check out my attempt here, it has some buttons for you to see the different states, width on/off and add text etc. (the jQuery has nothing to do with the solution)
I think this is as close as you're going to get with pure CSS.
Good 'ole tables to the rescue:
http://jsfiddle.net/hgwdT/
Actually I think tables are the devil, but this works as you described. And so here it is using display: table-cell on the child divs, so it is functionally the same using nicer markup:
http://jsfiddle.net/XXXdB/
The center element can indeed have a dynamic width; to prevent the content from being squished, I simply added a white-space: nowrap to the p containing the text.
I also confirmed that this solution works in IE8 and FF, in addition to Chrome.
This not the most elegant solution, but it works. I wanted to go the pure CSS route, but couldn't figure it out. Nice work, jblasco and Kyle Sevenoaks, on figuring that out!
Here is my jsFiddle demo. If you don't mind using a little JavaScript though (utilizing jQuery in my example):
HTML:
<div id="wrapper">
<div class="side"></div>
<div id="middle">One line of text.</div>
<div class="side"></div>
</div>
CSS:
#wrapper {
margin: 0 auto;
width: 1000px;
}
#wrapper div {
float: left;
height: 300px;
}
.side {
background: #ddd;
}
#middle {
background: #eee;
padding: 0 30px;
text-align: center;
}
JavaScript:
var adjustSize = function(){
// Declare vars
var wrapper = $('#wrapper'),
middle = $('#middle'),
totalWidth = wrapper.width(),
middleWidth = middle.width(),
middleOuterWidth = middle.outerWidth(),
remainingWidth = totalWidth - middleOuterWidth,
sideWidth;
if(remainingWidth % 2 === 0){
// Remaining width is even, divide by two
sideWidth = remainingWidth/2;
} else {
// Remaining width is odd, add 1 to middle to prevent a half pixel
middle.width(middleWidth+1);
sideWidth = (remainingWidth-1)/2;
}
// Adjust the side width
$('.side').width(sideWidth);
}
I'm making a website and want it to appear as a grid of boxes and rectangles.
I have a 6x6 grid of relatively-alined left-float divs. They work fine and fit neatly in a 900 width wrapper div. If i want a horizontal rectangle, i simply make one of these squares twice as wide (accounting for margins between, but that's irrelevant) and delete the one next to it. No problem.
The issue I have comes in when I want to make a rectangle twice as TALL. it ends up bumping everything left of it in the same row as it a line down. The same happens with a square twice as large (2x2 grid units).
Here's the code in jsfiddle:
http://jsfiddle.net/zucw9/
Essentially, how can I get either 8,9, and 10 to shift up one space, or for 6,7, and 8 to move into that gap, leaving 9 and 10 where 6 and 7 are right now?
http://jsfiddle.net/zucw9/10/
This solution isn't a very good solution but it works.
(I changed some of the names so i could read it better. (.grid_rect_tall became .grid_tall etc. margin-left:10px; margin-right: 0px etc.. became margin: 5px;)
basically you specify a -ve margin-bottom for the tall one and an extra margin so the other elements don't overlap.
.grid_square, .grid_long, .grid_tall
{
float: left;
margin: 5px;
background: #6CC;
}
#main{
position: relative;
width: 905px;
overflow: hidden;
border: 1px solid black;
padding: 5px;
}
.grid_square{
width: 140px;
height: 140px;
}
.grid_long{
width: 290px;
height: 140px;
}
.grid_tall{
width: 140px;
height: 290px;
margin-bottom: -150px;
}
.rbuffer
{
margin-right: 155px;
}
.lbuffer
{
margin-left: 155px;
}
I'd still go with my comment though and use either: http://960.gs or css3 grid layout: http://w3.org/TR/css3-grid-layout
EDIT:- I thought i better put a why to my comment earlier that this is not a good solution. Simply put: if you want to change the layout of the page you will have to change the classes on the items as well as having to change the css.
Also created one with even more elements to show the possibilities: http://jsfiddle.net/zucw9/11/ (or in em instead of px because i was bored. http://jsfiddle.net/zucw9/15/)
The layout is standard, how it should be displayed. I would recommend to use another div which wraps up the dives that appear before the taller div. This is not a very flexible solution though.
Edit: Move
<div class="grid_square">8</div>
<div class="grid_square">9</div>
<div class="grid_square">10</div>
higher in hierarchy after
<div class="grid_square">2</div>
should fix it.
i hope your thinking like below
code:
<div id="main">
<div class="grid_square">1</div>
<div class="grid_rect_long">2</div>
<div class="grid_rect_tall">3</div>
<div class="grid_square">4</div>
<div class="grid_square">5</div>
<div style="clear:both"></div>
<div>
<div class="grid_square">6</div>
<div class="grid_square">7</div>
<div class="grid_square">8</div>
<div class="grid_square">9</div>
<div class="grid_square">10</div>
</div>
</div>