2 columns layout in css (ordering items) - css

Is there any way to show 2 columns layout with this html code using only css? (column1 class should be in first column, and column2 class in the second one)
<div class="container">
<div class="column1">1a</div>
<div class="column2">1b</div>
<div class="column2">2b<br>zz</div>
<div class="column1">2a</div>
<div class="column2">3b</div>
<div class="column2">4b</div>
<div class="column2">5b</div>
<div class="column1">3a</div>
<div class="column1">4a</div>
</div>
The result I expect:
1a 1b
2a 2b
3a zz
4a 3b
4b
5b

float seems the best option here if you manage the Block formatting context
example :
* {
box-sizing: border-box;
}
div div {
box-shadow: inset 0 0 0 1px;/* see me */
width: 50%;
line-height: 1.4em; /* because of that 2 lines element , to hide the gap */
background: lightblue;/* see me too */
}
.column1:first-child {
float: left; /* let another float stand aside */
}
.column2 {
float: right;
clear: right;/* pile us to the far right */
}
div div:nth-child(odd) {
background: lightgreen;/* see me different */
}
<div class="container">
<div class="column1">1a</div>
<div class="column2">1b</div>
<div class="column2">2b<br>zz</div>
<div class="column1">2a</div>
<div class="column2">3b</div>
<div class="column2">4b</div>
<div class="column2">5b</div>
<div class="column1">3a</div>
<div class="column1">4a</div>
</div>
It matches your expected layout here, but will it also with real content ?

One way you can do this would be to float the classes of .column1 and .column2 like this:
.container {
width: 100%;
}
.column1 {
float: left;
width: 50%;
}
.column2 {
float: right;
width: 50%;
}
<div class="container">
<div class="column1">1a</div>
<div class="column2">1a</div>
<div class="column1">2b</div>
<div class="column1">3a</div>
<div class="column2">2b</div>
<div class="column2">3b</div>
<div class="column2">4b</div>
<div class="column1">4a</div>
<div class="column1">5a</div>
</div>
You could also maybe simplify this by having only two inner divs representing each column like:
<div class="container">
<div class="column1">
...
</div>
<div class="column2">
...
</div>
</div>

You can also achieve the same thing using minimal code via using flex. Just add following code to your CSS.
.container {
display: flex;
flex-wrap: wrap;
}
.container div {
width: 50%;
}
Explanation :- You add display type flex to the container, so all the elements will be arranged next to each other inside this div.
Now when you give width of 50% to internal divs and give flex-wrap: wrap to the container, it ensures that only 2 divs are next to each other since there is no space left to accommodate more.
Alternatively if you want the items closer to each other you can reduce the width of the outer container.
.container {
display: flex;
flex-wrap: wrap;
width: 10%;
}
.container div {
width: 50%;
}
This would be closer to what you are expecting.

Related

Using calc() with a dynamic value?

I am wondering if this is possible: I have a header that can contain a variable amount of text. Below that I have another element which I want to take up the remaining height of the page.
<div class="header row">
<div class="title column large-5">Potentially very long text</div>
<div class="menu column large-7">Menu items</div>
</div>
<div class="content">
</div>
<div class="footer">
</div>
Normally I would do this using calc, eg:
.content {
height: calc(100vh - 75px);
}
Where 75px is the set height of .header.
But in this example, the .header element is dynamic and does not have a set height. Only a padding and font-size are set.
To complicate things, this also uses the Foundation Grid layout, which makes me nervous about using display: table (.title and .menu sit side by side on desktop, but stacked on mobile) .
Is there anyway to get the height of the dynamic header element (without resorting to JQuery)?
You can use flexbox and set .content to flex-grow: 1 so that it will fill to grow the available space.
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
.content {
flex-grow: 1;
background: #eee;
}
<div class="header row">
<div class="title column large-5">Potentially very long text</div>
<div class="menu column large-7">Menu items</div>
</div>
<div class="content">
</div>
<div class="footer">
</div>
I made a small pen to show the way to do this using flex box, it involved changing your markup a bit:
css:
.container {
display: flex;
flex-direction: column;
height: 250px; // whatever you want here
}
.header {
width: 100%;
background: red;
padding: 10px;
}
.content {
background: yellow;
width: 100%;
flex-grow: 1;
}
So the content will always take the available space inside the content div.
check the whole pen: http://codepen.io/anshul119/pen/yMYeLa
hope this helps.

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>

Is there a way of writing CSS that lets you re-organize the order of how HTML components appear?

I am working on a responsive site in which the mobile/tablet view differs from the desktop view in the way it re-orders the DIVs.
Is there a way to write maintainable CSS that let's you re-organize the order of how HTML DIVs appear?
For example, the code below controls the order of how DIVs would appear on a desktop device:
<div class="container">
<div class="row1">
<div class="col1A">Sample content</div>
<div class="col2A">Sample content</div>
<div class="col3A">Sample content</div>
</div>
<div class="row2">
<div class="col1B">Sample content</div>
<div class="col2B">Sample content</div>
<div class="col3B">Sample content</div>
</div>
</div>
However, for mobile/tablet view, I want to display the DIVs in different order using CSS, like the example below:
Show row2, col2B
Then row1, col1A
Then row1, col3A
Then row2, col1B
Is this possible using CSS ?
As a proof-of-concept, you can use the flex CSS property to reorder how elements are visually rendered.
In your example, I had to keep the child elements within a single container
and then I could control the order using the order property.
If you want to hide some items on the small screen view, use display: none on the specific items.
Note: For a wide screen, you would need some CSS rules to get the items to look like two rows. (Please specify what you need.)
If you combine this with media queries, you can get a workable solution.
.container {
display: flex;
flex: center;
flex-direction: column;
align-items: center;
border: 1px dotted blue;
}
.container div {
text-align: center;
padding: 10px;
border: 1px dotted gray;
width: auto;
}
.col1A {
order: 2;
}
.col2A {
display: none;
}
.col3A {
order: 3;
}
.col1B {
order: 4;
}
.col2B {
order: 1;
}
.col3B {
display: none;
}
<div class="container">
<div class="row1 col1A">Sample content 1A</div>
<div class="row1 col2A">Sample content 2A</div>
<div class="row1 col3A">Sample content 3A</div>
<div class="row2 col1B">Sample content 1B</div>
<div class="row2 col2B">Sample content 2B</div>
<div class="row2 col3B">Sample content 3B</div>
</div>
If you want to simulate two rows of three elements, you can still use flex with some adjustments. The following may be helpful.
.container {
display: flex;
flex: center;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
border: 1px dotted blue;
padding: 20px 0;
}
.container .row1 {
margin-bottom: 20px;
}
.container div {
text-align: center;
padding: 10px;
border: 1px dotted gray;
flex-basis: calc(33% - 20px);
}
.col1B {
background-color: yellow;
}
<div class="container">
<div class="row1 col1A">Sample content 1A</div>
<div class="row1 col2A">Sample content 2A</div>
<div class="row1 col3A">Sample content 3A</div>
<div class="row2 col1B">Sample content 1B</div>
<div class="row2 col2B">Sample content 2B</div>
<div class="row2 col3B">Sample content 3B</div>
</div>
Set a screen size for mobile device detection in the css and add the following
#media screen and (max-width: SIZE) {
.row2{
display: flex; flex-flow: column;
}
.col1B{
order: 1;
}
.col2B{
order: 2;
}
.col3B{
order: 3;
}
}
And then add the classes to the DIVs
<div class="row2">
<div class="col1B">Sample content</div>
<div class="col2B">Sample content</div>
<div class="col3B">Sample content</div>
</div>
Change order: 1/2/3; to your needs.

CSS- Getting 100% width div to wrap under another [jsfiddle]

In a responsive layout, I have two columns. The left column is the sidebar and the right column is the content.
Using a media query, when the screen width is tiny, the columns turn to 100% width and stack on top of each other.
In this case, I want the sidebar (the first div) to appear beneath the content (the second div).
I tried using float: right on a small screen once it's at 100%, but at 100% width, the float apparently doesn't matter.
.left, .right {
width: 100%;
float: left;
background: green;
}
.left {
float: right;
background: red;
}
.half {
width: 50%;
}
.space {
width: 100%;
display: block;
height: 40px;
}
And on the page:
<div class="left half"> <!-- To mimic full screen size -->
Left
</div>
<div class="right half">
Right
</div>
<div class="space"></div>
<div class="left"> <!-- To mimic small screen size -->
Left
</div>
<div class="right"><!-- This should appear first -->
Right
</div>
Here is the fiddle: https://jsfiddle.net/ph09frvw/
I'm sure this is not the first time someone wanted to wrap the sidebar under the content, I just haven't been able to find a solution.
You can use display: flex and use the order property to change the order of the <div> elements. While floating can be helpful for horizontal alignment, it will be of little help for vertical alignment, Here is an example:
.flex {
display: flex;
flex-flow: row wrap;
}
.left {
order: 2;
flex: 1 0 50%;
background: red;
}
.right {
order: 1;
flex: 1 0 50%;
background: green;
}
.full {
margin-top: 20px;
}
.full > .left,
.full > .right {
flex: 1 0 100%;
}
<div class="flex">
<div class="left">
Left
</div>
<div class="right">
Right
</div>
</div>
<div class="flex full">
<div class="left">
Left
</div>
<div class="right">
Right
</div>
</div>
You could use the display:flex; property combined with flex-direction to reorder your divs. Ref: https://css-tricks.com/almanac/properties/f/flex-direction/
Remember to reference your related class-names in your HTML elements' class attribute.
Your CSS display:block should do the trick, else try something like:
float: left
When you use: display:block on a div element, you do not need to specify width:100% as it should automatically span across the width if it is not hindered by anything else.
Make sure the position of these elements are "relative", else it may not work as expected; it may be stated globally that some specific tags should be displayed "absolute" and that may break what you're trying to achieve.

using css to center an element

I am trying to align the elements in the head portion of a webpage properly.
There are three elements placed inside a header div:
The site logo (as an image) wrapped in an anchor tag should be left justified.
A div that contains a bunch of vertically aligned menu elements right justified.
A form containing a search box and a go button. This must be centered horizontally in the page and show between to logo on the left and the menu items on the right.
All three elements should be justified to the bottom of the header div.
I have been wrestling with this but nothing seems to work. Can you please help? Thanks!
<div style="float: right;">
<ul>
<li>Menu item</li>
</ul>
</div>
<div style="float: left;">
<img style="border: 0;" src="something.png" />
</div>
<div style="width: 300px; margin: 0 auto;">
Search box
</div>
Just a quick mockup.
UPDATE: using table/table-cell trick to allow vertical-align: bottom;
You need to wrap your manu, logo and searchbox into <div> with display: table-cell; css rule.
The markup:
<div class="table header">
<div class="table-cell">
<div class="logo"> </div>
</div>
<div class="table-cell">
<div class="searchbox"> </div>
</div>
<div class="table-cell">
<div class="menu"> <br/><br/><br/><br/><br/><br/><br/><br/></div>
</div>
</div>
and css:
.table {
display: table; /* our outer contaner should behave like table; */
width: 100%; /* set width to 100% */
}
.table-cell {
display: table-cell; /* our internal wrapper should behave like table cell to allow vertical-align */
vertical-align: bottom; /* align all elements vertical */
background: yellow; /* for debug purposes */
}
.logo {
float: left;
width: 100px;
background: green;
}
.menu {
float: right;
width: 100px;
background: red;
}
.searchbox {
margin: 0 auto;
width: 100px;
background: blue;
}
Complete example: http://jsfiddle.net/EREmH/4/

Resources