Ok, so i thought this was easy as 123. I've research here and tried a couple of solutions. For some reason, i can't get it right.
Basically, i'm trying to do a layout where the left column is fluid and the right column is fixed.
HTML:
<div class="column-ab">
<div class="col-content">content section</div>
<div class="col-aside">side section</div>
</div>
CSS:
.column-ab {background-color: black; width: 100%;}
.column-ab .col-aside, .column-ab .col-content {float: left;}
.column-ab .col-content {background-color: cyan; margin-right: 300px;}
.column-ab .col-aside {background-color: yellow; width: 300px;}
.column-ab:after {display: table; content: ""; clear: both;} /* clear */
jsfiddle:
https://jsfiddle.net/ud1frxdp/
Why something so easy doesn't work?
Turn your classes into ids or they will both inherit a width of 100%; then set the width.
.column-ab {background-color: black; width: 100%;}
#col-aside, #col-content {float: left;}
#col-content {background-color: cyan; width: calc(100% - 300px);}
#col-aside {background-color: yellow; width: 300px;}
.column-ab:after {display: table; content: ""; clear: both;} /* clear */
<div class="column-ab">
<div id="col-content">content section</div>
<div id="col-aside">side section</div>
</div>
As an alternative solution your problem can also be solved using few lines of flexbox layout. Code explanation in comments.
.column-ab {
display: flex;
flex-wrap: wrap; /* Wrap the divs when width is too small i.e. <300px of viewport */
}
.col-content {
flex: 1; /* Expands and shrinks according to width, fluid content */
background: tomato;
}
.col-aside {
flex: 0 0 300px; /* flex-basis: 300px for fixed width */
background: lightblue;
}
<div class="column-ab">
<div class="col-content">content section</div>
<div class="col-aside">side section</div>
</div>
Updated JSfiddle
Using display: table; and display: table-cell; is a common use and also a wide cross-browser code, compatibility from IE8 http://caniuse.com/#search=table
https://jsfiddle.net/ud1frxdp/3/
.column-ab {
background-color: black;
width: 100%;
display: table;
}
.column-ab .col-aside, .column-ab .col-content {
display: table-cell;
}
.column-ab .col-content {
background-color: cyan;
}
.column-ab .col-aside {
background-color: yellow;
width: 300px;
}
I also exploded your CSS because of readability, you should avoid coding like this and use a post-processor to minify it, being able to read the code is very important.
Related
In a webpage i have following markup for my layout
<div class="parent">
<div class="left-content"></div>
<div class="right-content"></div>
</div>
and the styles for the given markup are:
.parent{
display:table;
width:100%;
}
.parent > .left-content{
width:auto;
}
.parent > .right-content{
width:320px;
}
How do I make the "right-content" occupy 320px of available width and the "left-content" div occupy all the remaining width?
Note that: i can not use the following technique to achieve this behaviour as my layout is responsive and i need to move the "right-content" to the bottom of "left-content" at specific resolution.
Markup:
<div class="parent">
<div class="right-content"></div>
<div class="left-content"></div>
</div>
Styles
.parent{
display:block;
width:100%;
}
.parent > .left-content{
width:auto;
}
.parent > .right-content{
width:320px;
float:right;
}
To make things easier I would first change the markup so you have the left content is below your right-content (as desired on smartphone-resolutions).
<div class="left-content"></div>
<div class="right-content"></div>
Next, because your first div is the one that takes up remaining width, the simple solution seems to be display:table-cell (and the parent as display:table). It looks doable with inline-blocks or floats as well, but you may have to resort to something like width: calc(100% - 320px); so I like the table solution a little bit more.
Next you add a simple media query to change back to blocks on lower resolutions.
.parent {
display: table;
width: 100%;
}
.parent > .left-content {
display: table-cell;
width: auto;
/* Added for visualisation */
background: blue;
height: 50px;
}
.parent > .right-content {
display: table-cell;
width: 320px;
/* Added for visualisation */
height: 50px;
background: red;
}
/* Media query */
#media(max-width: 550px) {
.parent > .left-content {
display: block;
}
.parent > .right-content {
display: block;
width: 100%;
}
}
<div class="parent">
<div class="left-content">Left</div>
<div class="right-content">Right</div>
</div>
I would strongly suggest using calc rather than forcing your markup to behave like a table.
http://sassmeister.com/gist/c87585fcff7fae356adb
.left-content,
.right-content {
width: 100%;
}
#media (min-width: 600px) {
.left-content {
float: left;
width: calc(100% - 320px);
}
.right-content {
float: right;
width: 320px;
}
}
The div elements inside the row are floated left, as described here:
http://www.w3schools.com/html/html_responsive.asp
and percentage sized.
I tried to apply what was suggested in this link below, in a similar question, but without success:
Responsive CSS / Inline divs
The divs keep an inline relation of 50% - 100% - 50% and their contents overlap.
Can anyone help me spot what I missed?
Thank you.
In my CSS and HTML I have:
footer[role="contentinfo"] div {
box-sizing: border-box;
}
.engage-row:after {
content: "";
display: table;
clear: both;
}
.col-1 {
float: left;
width: 25%;
}
.col-2 {
float: left;
width: 50%;
padding: 10px 20px 0px 20px;
}
.col-3 {
float: left;
width: 25%;
}
.footer-wfix {
clear: both;
}
/* for illustrative purposes */
.engage-row {
border: 1px solid red;
}
.engage-row > div {
border: 1px solid blue;
}
<footer id="colophon" role="contentinfo">
<div class="footer-wrap">
<div class="engage-row">
<div class="col-1">
Column 1
</div>
<div class="col-2">
Column 2
</div>
<div class="col-3">
Column 3
</div>
</div>
<div class="footer-wfix">
Footer Menu and Site-generator
</div>
</div>
</footer><!-- #colophon -->
Edited the code and am adding the below for clarity:
- I edited the footer by adding the "engage-row" and it's containing column divs.
- All divs have inherited box-sizing: border-box.
- Column 1, Column 2 and Column 3 don't readjust positioning when I decrease the screen size (width); instead of becoming on top of each others, they are changing their size (keeping percentages but becoming smaller), making the containing text and images overlap (text from column 2 goes in front of the image in column 1). I hope I am using the correct terms for clarity.
- How can I make them readjust the positioning as the screen size changes?
- PrintScreen: 3column divs in footer
(This is an awesome site. Thank you)
You need to take into account the padding in the .col-2 declaration. When you have three columns adding up to a total of "100 % width" and then add padding, the result so to speak is "more than 100 % width", causing the overlapping behavior you observe.
One way around it is to declare the paddings in percent as well. If you don't like the resulting "elastic margins", you need to figure out a equation that works. Or check out Bootstrap or something similar (I mean you can either use it as is, or decipher their responsive solutions).
You need to add the css3 property box-sizing: border-box; This will wrap your padding into your div, so the width will be 50% only.
Please share your feedback if its helpful for your problem.
.col-2{
float: left;
width: 50%;
padding:10px 20px 0px 20px;box-sizing: border-box;
}
you mention 25% 50% 25% and a border of div so overlapped,
in this case use box-sizing: border-box;
.engage-row:after {
content: "";
display: table;
clear: both;
}
.col-1 {
float: left;
width: 25%;
}
.col-2 {
float: left;
width: 50%;
padding: 10px 20px 0px 20px;
}
.col-3 {
float: left;
width: 25%;
}
.footer-wfix {
clear: both;
}
/* for illustrative purposes */
.engage-row {
border: 1px solid red;
}
.engage-row > div {
border: 1px solid blue;
box-sizing: border-box;/*added one*/
}
This is what I needed (I couldn't be clear until I researched enough):
The left and right divs include images and I didn't want those to change size as I decrease the screen resolution. I wanted to input that adjustment in the middle div which contains only text and a subscription form.
The question/answer that drove me there:
How to make element fill remaining width, when sibling has variable width?
My testing fiddle - http://jsfiddle.net/0gvxxpjj/
<!-- In html--->
<div class="row">
<div class="col-1">
<img src="">
</div>
<div class="col-3">
<img src="">
</div>
<div class="col-2">
<h3>Header</h3>
<p>This is a paragraph that, along with the header, needs to wrap as the screen is resized</p>
</div>
</div>
<!-- html ends here-->
/* CSS starts here */
.col-1 {
float: left;
width: 100px;
}
.col-3 {
float: right;
width: 100px;
}
.col-2{
padding: 10px 20px 0px 20px;
overflow: hidden;
}
.row {
border: 1px solid black;
display: inline-block;
}
.col-1, .col-3 {
border: 1px solid blue;
}
.col-2 {
border: 1px dashed red;
}
Hope it becomes useful to someone else.
As I understand it, you want to have the divs be in a 25% - 50% - 25% layout and after the browser shrinks beyond a certain size, they become 100% width and stack on top of each other.
This is done via media queries. What, essentially, happens is that you set some CSS rules inside a media query which adds to any previous CSS rules only when a certain condition has been met (in this case browser width). A rough example can be seen below.
These are the relevant parts:
This sets how the divs will look by default - full width.
.col-1,
.col-2,
.col-3 {
float: left;
width: 100%;
}
This sets the widths of the divs to 25-50-25 once the browser width is larger than 768px.
#media all and (min-width:768px) {
.col-1, .col-3 {
width: 25%;
}
.col-2 {
width: 50%;
}
}
You can extend this example to the layout you desire.
footer[role="contentinfo"] div {
box-sizing: border-box;
}
.engage-row:after {
content: "";
display: table;
clear: both;
}
.col-1,
.col-2,
.col-3 {
float: left;
width: 100%;
}
.col-2 {
padding: 10px 20px 0px 20px;
}
.footer-wfix {
clear: both;
}
/* for illustrative purposes */
.engage-row {
border: 1px solid red;
}
.engage-row > div {
border: 1px solid blue;
}
#media all and (min-width:768px) {
.col-1, .col-3 {
width: 25%;
}
.col-2 {
width: 50%;
}
}
<footer id="colophon" role="contentinfo">
<div class="footer-wrap">
<div class="engage-row">
<div class="col-1">
Column 1
</div>
<div class="col-2">
Column 2
</div>
<div class="col-3">
Column 3
</div>
</div>
<div class="footer-wfix">
Footer Menu and Site-generator
</div>
</div>
</footer><!-- #colophon -->
I am wondering if it's possible to display two div elements in inverted order using only css.
No html change or javascript code, just css.
I have the following html:
<div id="container" class="clearfix">
<div id="right-sidebar">Right</div>
<div id="left-sidebar">Left</div>
</div>
and this current css:
#container {
width: 200px;
border: 2px solid blue;
padding: 2px;
margin: 0;
}
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
#left-sidebar, #right-sidebar {
width: 150px;
padding: 2px;
}
#left-sidebar {
border: 2px solid red;
float: left;
}
#right-sidebar {
border: 2px solid green;
float: right;
}
The result shows the right div above the left one. I'd like to swap them, showing the left one above the right one, maintaining the container properties (auto calculated height).
To explain it in different words, I'd like to achive using just CSS the same result I would obtain by swapping the two divs in the html code.
Is it even possible with only css? [I'm dreaming about a float: bottom property :)]
http://jsfiddle.net/mT7JJ/1/
According to this and many others, i am afraid you can not swap only with css, but I've found something that will help you in this situation and that is this
So this will be your edit on fiddle
#container {
display: table; width: 200px;
border:1px red solid;
}
#left-sidebar {
display: table-header-group;
}
#right-sidebar {
display: table-footer-group;
}
The only think i can think about is relative/absolute position. But it will not be really efficient though
One modern solution, as has been comented, is flex layout.
Another tricky posibilitity is using transforms
webkit demo
I an just rotating the container upside down, and then rotaing the inner divs to make them look ok. It's done in the hover, to show the net effect.
The hover is a little bit inestable due to the clearfix, but this is not relevant here.
#container:hover {
-webkit-transform: rotateX(180deg);
}
#container:hover div {
-webkit-transform: rotateX(180deg);
}
I enjoy answering a question that has been declared imposible :-)
<div id="container" class="clearfix">
<div id="left-sidebar">Left</div>
<div id="right-sidebar">Right</div>
</div>
#container {
width: 200px;
border: 2px solid blue;
padding: 2px;
margin: 0;
}
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
#left-sidebar, #right-sidebar {
width: 150px;
padding: 2px;
}
#left-sidebar {
border: 2px solid red;
}
#right-sidebar {
border: 2px solid green;
}
check this left div above right div
Using CSS only:
#blockContainer {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}
#blockA {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
box-ordinal-group: 2;
}
#blockB {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
box-ordinal-group: 3;
}
<div id="blockContainer">
<div id="blockA">Block A</div>
<div id="blockB">Block B</div>
<div id="blockC">Block C</div>
</div>
http://jsfiddle.net/hLUHL/713/
no expert and old question but use case apply for me under specific conditions to anwser this question: "Swap div order using css only"
My answer is almost entirely based on Harry's answer here https://stackoverflow.com/a/31366853/3913379 (Original Answer v2) and tested nowadays (Chrome/FF) under the condition that the child divs are same size (use case is main Div contains TWO divs with link icons and text).
So to swap TWO divs left to right and vice versa using CSS only I used a css transform on X axis (transform: translateX ), like this:
<STYLE type="text/css">
#Child1Div {transform: translateX(100%);}
#Child2Div {transform: translateX(-100%);}
</STYLE>
<div id="MotherDiv" >
<div id="Child1Div">Context of child one</div>
<div id="Child2Div">Content of child two</div>
</div>
So, note usage of percentages and negative values in one case, to attain basically "the swap". HTML structure is unchanged (and JS/JQuery listeners were unaffected, for example link's onClick(...) )
This may fail under some inherited special styles but simple case worked nicely for me.
Style can be applied in HEAD tag or inline on divs or also dynamically via JS (for example to swap two Icons/Images via a button click or something like that)
There are two ways to do that with css. Flex and Grid.
Flex:
#container {
display: flex;
flex-wrap: wrap;
position: relative;
justify-content: flex-start;
flex-direction: row-reverse;
}
Grid:
#container {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr))
}
#left-sidebar {
order 2
}
#right-sidebar {
order 1
}
I have 2 divs side by side. I don't know the height of them upfront, it changed according to the content. Is there a way to make sure they will always be the same height, even when one of them stretches, only with CSS?
I made a fiddle to show. I want the red and blue divs to be the same height...
http://jsfiddle.net/7RVh4/
this is the css:
#wrapper {
width: 300px;
}
#left {
width:50px;
background: blue;
float:left;
height: 100%; /* sadly, this doesn't work... */
}
#right {
width:250px;
background: red;
float:left;
}
You could try instead of using float, use display: table-cell. You might find some older browsers don't understand this rule however. See below:
#wrapper {
display: table; // See FelipeAls comment below
width: 300px;
}
#left {
display: table-cell;
width: 50px;
background: blue;
}
#right {
display: table-cell;
width: 250px;
background: red;
}
Antony answer works ok, but you need all the divs to have the same parent and to have a wrapper, I have a solution that use javascript but works with any kind of element, they just need to have the same selector.
function setEqualHeight(selector, triggerContinusly) {
var elements = $(selector)
elements.css("height", "auto")
var max = Number.NEGATIVE_INFINITY;
$.each(elements, function(index, item) {
if ($(item).height() > max) {
max = $(item).height()
}
})
$(selector).css("height", max + "px")
if (!!triggerContinusly) {
$(document).on("input", selector, function() {
setEqualHeight(selector, false)
})
$(window).resize(function() {
setEqualHeight(selector, false)
})
}
}
setEqualHeight(".sameh", true)
http://jsfiddle.net/83WbS/2/
I would recommend reading this article that explains how to do what you are trying to do. I would put a fiddle up that shows, but its pretty extensive and pure css. http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks
There is a much simpler solution I want to point to. Using large padding-bottom: 500em and negative margin-bottom:-500em of the same amount on columns while the wrapper has simply overflow:hidden to cut the columns to the right size.
Found here:
HTML/CSS: Making two floating divs the same height
As indicated by Hexodus you can padding-bottom and margin-bottom, but a better solution would be to use flexbox or grid.
You can check this codepen if you want. I included a footer area because that is something I needed and it required a little bit more of hack.
.section {
width: 500px;
margin: auto;
overflow: hidden;
padding: 0;
}
div {
padding: 1rem;
}
.header {
background: lightblue;
}
.sidebar {
background: lightgreen;
width: calc(25% - 1rem);
}
.sidebar-left {
float: left;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.main {
background: pink;
width: calc(50% - 4rem);
float: left;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.sidebar-right {
float: right;
padding-bottom: 500rem;
margin-bottom: -500rem;
}
.footer {
background: black;
color: white;
float: left;
clear: both;
margin-top: 1rem;
width: calc(100% - 2rem);
}
<div class="section">
<div class="header">
This is the header
</div>
<div class="sidebar sidebar-left">
This sidebar could have a menu or something like that. It may not have the same length as the other
</div>
<div class="main">
This is the main area. It should have the same length as the sidebars
</div>
<div class="sidebar sidebar-right">
This is the other sidebar, it could have some ads
</div>
<div class="footer">
Footer area
</div>
</div>
You can do this without using tables, by using this CSS trick.
Example - http://jsfiddle.net/LMGsv/
HTML
<div id="wrapper">
<div id="columns">
<div id="left">text</div>
<div id="right">text<br/>another line<br /></div>
</div>
</div>
CSS
#wrapper {
float:left;
width: 300px;
}
#columns {
float:left;
width:300px;
background:blue;
}
#left {
float:left;
width:50px;
background: blue;
}
#right {
width:250px;
background: red;
float:left
}
I'm having a bit of a "moment" where I am stumped on an issue I thought should be pretty easy (and probably is, I'm just over complicating I'm sure).
I'm looking to have a div with multiple children div's; the children should automatically expand or contract based on the number there are (the site I'm working on is in a CMS that allows a user to add or remove items).
My issue is having the div's respect the min- and max-width declaration. I have a hunch that it could be something to do with them being float:left, but I've tried a few other variations with no luck.
My main objective is to get these columns to fill their space on one "row", up to 4 columns.
EDIT: I need to have these columns be a minimum width, as well as a maximum width. So if there are 3 child div's, they should all be wider than if there were 4 child div's.
Here is an example of my code: http://codepen.io/joe/full/IJvGp
HTML
<div class="sub cf">
<div class="row">
<div class="col">
Column 1
</div>
<div class="col">
Column 2
</div>
<div class="col">
Column 3
</div>
<div class="col">
Column 4
</div>
</div>
</div>
CSS
.sub {
width: 670px;
background: #fff;
border: 10px solid #414042;
}
.sub .row {
padding: 0;
float: left;
width: 100%;
}
.sub .row .col {
min-width: 166px;
max-width: 222px;
width: 100%;
float: left;
border-right: 1px solid #D0D2D3;
margin: 0;
padding: 0;
}
.cf::before, .cf::after {
content: "";
display: table;
}
.cf::after {
clear: both;
}
With jquery you could dynamically set the column widths as a % based on the number of columns within the row.
var colWidth = (1 / $('.sub.cf .row').children().length * 100) + '%';
$('.sub.cf .col').outerWidth(colWidth);
working fiddle. Insert or remove more columns and rerun it to see how it works.
Removing the width:100%; on the .sub .row .col item made them appear in 4 columns.
Regardless it looks like you should be using a table instead of this approach.
CSS3 Solution
Remove the min and max widths on .col but add the box-sizing: border-box property to that. Then add the following code below the .col definition which yields the result in this fiddle:
.sub .row .col:nth-last-of-type(2),
.sub .row .col:nth-last-of-type(2) ~ .col
{
width: 50%;
}
.sub .row .col:nth-last-of-type(3),
.sub .row .col:nth-last-of-type(3) ~ .col
{
width: 33.3%;
}
.sub .row .col:nth-last-of-type(4),
.sub .row .col:nth-last-of-type(4) ~ .col
{
width: 25%;
}
You could try something like this:
HTML:
<div class="sub">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
CSS:
.sub {
text-align: justify;
width: 670px;
background: #fff;
sborder: 10px solid #414042;
}
.sub div {
display: inline-block;
max-width: 166px;
min-height: 100px;
border-right: 1px solid #D0D2D3;
margin: 0;
padding: 0;
}
.sub:after {
content: '';
width: 100%;
display: inline-block;
}
The main problem here is width: 100% and max-width: 222px. With width: 100% you are making the children divs as big as you can. And because of max-width: 222px they all become 222px width. Your parent div is 670px width, so if you do the math: 222px * 4 = 888px. The children divs' total width is exceeding the parent's width, that's why it's pulling the last div down.
You can try:
Codepen
If you don't care much about supporting IE8- then ScottS solution is the best.
You have the following code.
max-width:222px;
Reduce it to some value so that it can be accomdated!
max-width:166px;
works for me!