side-by-side, flexible width divs without wrapping? - css

I'm not really sure how to best explain this. I'm trying to have three div elements positioned side-by-side; the first (left to right) is flexible-width, the second is also flexible width, the third is static width and it floated to the right. The first two are inside a div on the same level as the third; that is to keep to total width of the first two under a max-width.
Here is a jsfiddle of what I'm doing.
My problem is that when the text in the middle div is long, the middle div will drop below the first one, instead of having the text wrap. I can't give the middle one a max-width, because the first div is flexible and could get smaller. Any idea how I can go about fixing this?
I know it can be achieved by using a table, but I'd really prefer not doing so unless it's the only easy solution.
Edit: I decided to just do fixed width. The amount of work for required for this just wasn't worth it, especially considering that most of the time, the flexible width would never be used for me anyway.

if you wan a pure css based solution then it might be little difficult and also not much browser compatible. Though you can achieve this by using the css property called display:table ; and display:table-cell;. Again older browser, maybe IE-9 also won;t be able t render this.
Then you should go for the jQuery solution. You can use the following code-
$(document).ready(function(){
var w = 400 - $('.inner_container .left_box').width();
$('.inner_container .middle')css('width',w);
});
Thanks.

The display: table property and related properties, such as display: table-cell, have been supported in IE since version 8 -- as well as all versions of Firefox and Chrome/Safari.
Reference: http://caniuse.com/#feat=css-table
I believe it's the way to go in your case.
HTML
<div class="container">
<div class="inner_container">
<div class="left_box">
<p>Lorem ipsum dolor sit amet</p>
</div>
<div class="middle">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<div class="right_static">Hi!</div>
</div>
CSS
.container {
position: relative;
width: 500px;
border: 1px solid #000;
overflow: auto;
}
.right_static {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
background-color: green;
}
.inner_container {
display: table;
width: 400px;
overflow: auto;
}
.left_box {
display: table-cell;
background-color: red;
}
.middle {
display: table-cell;
background-color: #9999FF;
}​
DEMO
http://jsfiddle.net/nd7qj/
By the way, you mentioned in your question that the leftmost div should have flexible width, but in the CSS you provided it had fixed width. So I didn't apply a width to it in my code.

Related

Safari position:sticky not working in an overflow:auto element

According to CanIUse, there is a known issue with Safari and position:sticky inside an overflow:auto element:
A parent with overflow set to auto will prevent position: sticky from working in Safari
However, this is the exact use case that I need. I have a scrollable div, which is subdivided into two columns. The right column should be sticky and never move, even when the entire div is scrolled. The reason I'm using position:sticky on the right column is that I want the user to be able to still scroll the left column with the cursor on the right column. And this was the only solution that I found to have worked.
A working example for Firefox / Chrome is here:
http://cssdeck.com/labs/zfiuz4pc
The orange area remains fixed while scrolling, but in Safari it doesn't.
The example above has some unnecessary wrappers to my issue, but I wanted to replicate as closely as possible the environment where I want to have this code working in. The basic gist of it is I have this:
<div class="modal-content">
<div class="left-content">
</div>
<div class="sticky-element">
</div>
</div>
And the CSS:
.modal-content {
display: flex;
overflow: auto;
flex-flow: row nowrap;
}
.left-content {
flex: 0 0 300px;
}
.sticky-element {
position: sticky;
top: 0;
right: 0;
width: 200px;
}
Again, this works in FF/Chrome but not in Safari. Is there a workaround to get it to work in all browsers? Or is there a different approach I can use to maintain scrollability even with the mouse cursor over the sticky element?
simply add position: -webkit-sticky;
Adding display: block to the .sticky-element worked for me without having to add position: -webkit-sticky. Found this solution at this Codepen.
I got this solution from someone else:
http://cssdeck.com/labs/bu0nx69w
Basically, instead of position:sticky, use position:fixed for the right panel. The key is to also you will-change:transform in a parent div (in the above example, in .modal-content) so position:fixed becomes fixed relative to that parent, and not the viewport. It's a neat little trick
I had a similar case:
<div scroll>
<div sticky />
<list />
</div>
Just wrap the scroll content with a div worked like a charm:
<div scroll>
<div>
<div sticky />
<list />
</div>
</div>
I had to use below to make it work in both Chrome and Safari:
position: sticky;
position: -webkit-sticky;
display: block;
position: sticky will not work, if your parent element has overflow: hidden. having this sticky setting, it will have automatically transform your element from relative to actual fixed to the top border of the document.
Another solution for this specific case, so long as you don't need the scroll bar on the far right of the modal.
Since your sticky element is the same height as your .modal-content, you could remove sticky altogether from .sticky-element. First, remove overflow:auto from .modal-content, then add that style to .left-content since that's the part you want to scroll anyway.
i cant really test this for safari right now but this has always been an alternative for me when creating a sticky footer for example:
<!DOCTYPE html>
<html>
<head>
<title>sticky side div</title>
<style type="text/css">
.maindiv{
position: relative;
display: inline-block;
background-color: forestgreen;
width: calc(100vw - 150px);
height: 100%;
overflow: auto;
}
.sidediv{
position: fixed;
display: inline-block;
background-color: lightyellow;
float: right;
width: 100px;
height: 100%;
}
</style>
</head>
<body>
<div class="maindiv">
Lorem 45
</div>
<div class="sidediv">
Lorem 30
</div>
<div class="maindiv">
Lorem 100
</div>
<div class="maindiv">
Lorem 900
</div>
</body>
</html>
once you know the width of your right content add a little more px to it then use the css calc function to make sure the other div's don't flow in to it
also there is a known bug with vh and vw in Safari 7. You can fix it by setting height: inherit on the #child elements whose parents have vh heights or vw widths
but my best recommendation if you were not going for cross browser support will be to use CSS Grids

Fixed width columns with fluid gutters

I know this can be done with columns, but I have to support IE.
I'm trying to get to a layout whose columns are all fixed width, with the gutters being fluid.
I couldn't get this to work with floats, so I settled on using justified inline-block items:
HTML
<div class="wrapper">
<div></div>
<div></div>
<div></div>
<!-- more divs... -->
</div>
CSS
.wrapper {
text-align: justify;
}
.wrapper div {
width: 100px;
display: inline-block;
}
This works wonderfully, but the last row of divs are all aligned to the left: http://jsfiddle.net/EsHh3/
The only solution I found is to add additional unnecessary divs: http://jsfiddle.net/EsHh3/1/
I feel uncomfortable about this, so I'd like to know if there are any other options.
Please don't tell me not to re-invent the wheel. I have not found any fluid grid system that supports fluid gutters.
For what you want to do, I'm afraid a CSS only solution is not available at the moment, much less if you want it to work in IE8.
Since you want to have (a) items that are in the HTML source as a list (b) a variable number of columns depending on available space (c) column spacing depending on width of container I think the solution you'll need would have to employ at least a bit of javascript.
Consider on of the frameworks proposed in the other answers. One I've worked with and could do what you want is Masonry (or the for-pay bigger brother Isotope). (There's also a non-jQuery version of Masonry). You'll have to come up with a function that when the page is resized, recalculates the desired gutter and reconfigures the framework. Something along the lines of calculating x = how many items would fit per line based on the container width and item width and then dividing the remaining space by x-1.
If you want to stick with the idea of adding extra DIV's to the markup, an alternative would be to listen to resize events, and add DIVs as needed based on the width and how many items would fit per line.
ORIGINAL ANSWER, which failed to fit all the criteria.
Since you're relying on text-align: justified the reason the last line doesn't expand to the full width is because there's no line break at the end of it. So to accomplish that we add an extra element with an wrapper:after {} rule, that is also an inline block with a width of 100% so it guaranties a line break.
See fiddle
The CSS ends up something like:
.wrapper {
text-align: justify;
width: 380px;
margin: 0 auto;
}
.wrapper div {
width: 100px;
display: inline-block;
}
.wrapper:after {content: ''; width: 100%; display: inline-block; background: pink; height: 2px; overflow: hidden}
Note that the pink background is there so that you can see where the element is. You might need to play with the border/margin/padding of that extra element or the wrapper so that content that comes after wrapper doesn't gain extra margin. In chrome unfortunately there's a slight missalignment of the last row items, possibly because of the extra space between the last DIV and the fake element.
Hey I don't know why you want a fluid gutter, but I have a simple grid sample which you might want to have a look and if you want to see the css then click the SCSS on the codepen site. Also, if you are learning then this sample is very good start point for how to make your own grid. Also, to avoid yourself reinventing the wheel you might want to try different grid frameworks out there. Just google css grid frameworks.
you can try this:
.wrapper {
text-align: justify;
width: 380px;
margin: 0 auto;
moz-column-count: 3;
-moz-column-gap: 20px;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
column-count: 3;
column-gap: 20px;
}
Updated URL
This is how I would go about it: http://codepen.io/jeremychurch/pen/wmtJz
.container {
display: table;
width: 100%; }
.cell {
display: table-cell; }
.content {
width: 15em;
margin: 0 auto; }
<div class="container">
<div class="cell">
<div class="content">
</div>
</div>
<div class="cell">
<div class="content">
</div>
</div>
<div class="cell">
<div class="content">
</div>
</div>
</div>

Add content within a nested div, and not change look of it's container

At the moment I have a container div
#container {
margin: 0 auto;
margin-top: 10px;
width:800px;
background-color:#eaeced;
}
within that div I'd like to add a content box which I've done like this
#contentbox {
background-color: #fff;
width: 400px;
margin: 5px;
}
As soon as I write some text into the #contentbox div.. this div covers the whole of the #container div... I have tried using padding but this increases the original size of the container..
I've just tried to add margin: 5px; but this will create the space only on the sides.. not on the top or the bottom.. :(
Sorry I'm quite new at this and would appreciate some help
Thank you :)
Not a lot of information, but I think what you're after is something like this:
#container {
margin: 0 auto;
margin-top: 10px;
width: 790px;
background-color:#eaeced;
padding: 5px;
}
#contentbox {
background-color: #fff;
width: 400px;
padding: 1px 0;
}
p {margin: 1em 0;}
presuming HTML like this:
<div id="container">
<div id="contentbox">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</div>
</div>
first of all move the required padding onto the #container, you can adjust the width of the #container to be your required width, less the total left/right padding - this will keep the width of the box as you want.
Then you have collapsing margins going on - though margin collapsing is correct behaviour you won't see it in IE unless you add specific margins - adding a specific margin to the <p> or any other content in the box will be required to get consistent behaviour even though it's the opposite of what you probably want.. the p should have default margins and they're what's collapsing outside the the #contentbox in some browsers (e.g. FF).. once you add specific margin all browser will then exhibit collapsing margin behaviour though some collapse the background internally and some externally so it looks weird.. however
adding 1px top/bottom padding (or a border would do it too) to the the inner #contentbox will fix that and make sure the actual content margins stay inside the content box
The result is I think what you're looking for.. but if not leave a comment or update your question with some code or a JSFiddle example

How do you set a floating div's width to take up remaining space without pushing other divs down?

For part of a layout I want to make, I want to use three divs, all floating next to each other. The Left and Right have a max-width set, which works fine, but I want the middle div to expand its width to fill the remaining space. To clarify, the left and right divs may have a width of anywhere from 0px to the max-width, depending on what is in each, and I want the middle div to expand its width so that it takes up the rest of the space not used by the divs on either side.
The problem it's having now is that if there is a lot of content in the middle div, it's expanding and pushing the right div off to the next line instead of keeping it up with the other two.
Here's the css I have so far:
#left-column {
width: auto;
max-width: 200px;
height: auto;
float: left;
}
#middle-column {
float: left;
width: auto;
}
#right-column {
width: auto;
max-width: 200px;
height: auto;
float: right;
}
...and the HTML:
<div id="left-column">...</div>
<div id="middle-column">...</div>
<div id="right-column">...</div>
I think that this can be accomplished using a three-column, single-row table, but I absolutely do NOT want to use tables - I want to accomplish as much as possible by using pure css.
Thanks!
Classic Floats
If you order it:
<div id="left-column"></div>
<div id="right-column"></div>
<div id="middle-column"></div>
and you float the left column left, and the right column right, the middle column should fill in the remaining space. You will have some issues with margins, borders and paddings though.
Flexbox
If you don't need to support older browsers, you can use flexbox. With flexbox, this sort of structure becomes much simpler, and the markup doesn't need to change.
You will need to be able to select the parent element, so for the purposes of this demo, the code will be wrapped by <div class="wrapper">.
.wrapper {
display: flex;
flex-direction: row;
height: 200px;
}
.left {
background-color: red;
width: 100px;
}
.middle {
background-color: green;
flex: 1;
}
.right {
background-color: blue;
width: 100px;
}
<div class="wrapper">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
The height and widths are added explicitly so that the <div>s are visible. With actual content, the columns would automatically adjust.
I don't want to dredge up an old thread here but I was looking for a solution to my own problem and came across this and I thought I'd better share with Francisco...
Tables are a terrible idea for positioning layout, the main problem is that before a table will show/render in the browser it has to render it's </table> tag.
Could you imagine if Facebook's column content used a table for it's layout, it would take ages for it to render anything to the screen when checking your timeline for instance!
Another issue is that tables behave extremely differently in each browser.
Basically: <table> for layout = NO!, <table> for listing out rows of data or information = YES!

2 column CSS div with stretchable height

Related (possibly duplicate) questions:
How do I achieve equal height divs with HTML / CSS ?
Make Two Floated CSS Elements the Same Height
Hello, every one,
I tried for hours to create a stretchable 2 columns div but without any luck. here is my html code and my css code below it
<div class="two_cols_container">
<div class="two_cols">
<div class="left-col">
test
</div>
<div class="right-col">
test
</div>
</div>
</div>
my css code is
.two_cols_container {
width: 100%;
height: 100%;
}
.two_cols {
position: relative;
margin: 0 auto;
border: 1px solid black;
height: 100%;
height: auto !important;
min-height: 100%;
}
.two_cols .left-col {
/*position: absolute;
left: 0;*/
float: left;
}
.two_cols .right-col {
/*position: absolute;
right: 0;*/
float: right;
}
any idea?
A: either use float OR absolute positioning to make your columns. not both. You can just float both the columns to the left and it should be ok with no absolute positioning.
B: you're big problem is the columns can't be next to each other if both of their' widths are 100%. There's no way they can sit side by side in their containing element when they both take up the whole width. Set the width to at most 50%, but I'd go with a little lower to account for some browser bugs.
EDIT: I agree with Sneakiness, wet the width to something lower than 50%, because the margins and padding have to fit too.
There's
Tables ( you probably wouldn't want to rely on this )
Faux Columns ( the most practical way, faking columns going down using images - see http://www.alistapart.com/articles/fauxcolumns/ )
Border Trick ( a little complex but this only works for solid colors )
Padding / Margin / Clipping ( another complex one I wouldn't recommend )
I'd go with #2. If you need colors that are backgrounds of those columns to go all the way down, set a background on the container of those columns and make sure it repeats vertically, e.g,
div#wrapper { background:url(/images/faux.gif) repeat-y; }
If the columns are floated make sure to have overflow:hidden and a hasLayout trigger for IE like a width.
By the way since you have floats, apply overflow:hidden to .two_cols selector and add this rule:
html, body { height:100%; }
I found this method to be the simplest and most effective of all equal-height two-column layouts. You don't have to fake anything, and it Just Works.
If you mean that you want a fluid two-column layout, you need to set margins for both columns separately to position them both on the page.
You can use div style property to create as many columns you need, with what ever CSS effect you need :
<div style=”width: 100%;”>
<div id=”left” style=”float: left;">
<--! your text here -->
</div>
<div id=”right” style=”float: right;">
<--! your text here -->
</div>
</div>
Source and example : WordPress Tutorial Series - Basics about HTML and CSS

Resources