CSS: height- fill out rest of div? - css

i wonder if this is possible with simple css or if i have to use javascript for this?
i have a sidebar on my website. a simple div#sidbar it's normally about 1024px high, but the height changes dynamically due to it's content.
so let's imaginge the following case:
<div id="sidebar">
<div class="widget"></div> //has a height of 100px
<div class="widget"></div> //has a height of 100px
<div id="rest"></div> //this div should have the rest height till to the bottom of the sidebar
</div>
i want the div#rest to fill out the rest of the sidebar till it reaches the bottom of the div#sidebar.
is this possible with pure css?

If you know the exact height of #widget (100px in your case), you can avoid using JavaScript by using absolute positioning:
#sidebar
{
height: 100%;
width: ...;
position: relative;
}
.widget
{
height: 100px;
}
#rest
{
position: absolute;
left: 0;
width: 100%;
top: 200px;
bottom: 0;
}

What you want is something like 100% - 200px but CSS doesn't support expressions such as these. IE has a non-standard "expressions" feature, but if you want your page to work on all browsers, I can't see a way to do this without JavaScript. Alternatively, you could make all the divs use percentage heights, so you could have something like 10%-10%-80%.
Update: Here's a simple solution using JavaScript. Whenever the content in your sidebar changes, just call this function:
function resize() {
// 200 is the total height of the other 2 divs
var height = document.getElementById('sidebar').offsetHeight - 200;
document.getElementById('rest').style.height = height + 'px';
};

I propose the table-element as an alternative:
+: clean CSS
+: avoiding javascript
-: table semantically misused
-: not the requested div-elements

I came across this question while looking for an answer to a similar question, and I thought I'd illustrate calc. As of this post, calc is not yet supported cross-browser; however, you can check this link here to see if your target browsers are supported. I've modified matt's hypothetical case to use calc in an example on jsFiddle. Essentially it is a pure CSS solution that does what casablanca proposes in his answer. For example, if a browser supports calc, then height: calc(100% - 200px); would be valid as well as for similar properties.

Sometimes a workaround might be:
#rest {
height: 100%;
padding-bottom: 200px;
}
The div itself will be too high, but because of the padding its content will have the right height.

you can do this with nested div tags. you have one specifying the width on the left, and then another left blank. To fill the rest of the other side you nest a 100% relative div inside the right side div. like so:
<div style="width:100%">
<div style="width:300px;background-color:#FFFF00;float:left">
</div>
<div style="margin-left:300px">
<div style="position:relative;left:0px;width:100%;background-color:#00FFFF">
</div>
</div>
</div>

Try
height: 100%;
or
height: auto;

Related

CSS Flexbox dynamic aspect-ratio code is influenced by content

For a webpage grid-layout I decided to use Flexbox. Now I wanted to implement some "auto-functionality", so that grid-boxes can later be inserted without the need to add classes or styles in the HTML. One of this features is to make a box allways be 75% as tall as it is wide - even if the box is resized by, for example, browserwindow resize. Off course, if the boxes content extends the 75%-height, it should (and only then should) increase its height to fit the content. I searched for hours to find a suitable solution, but I finally got it working. So I thought at least, until I added content to the box.
The auto aspect-ratio works fine, as long as the box is empty. If I add content, the 75% of the width is allways added to the height it has through extension by its content. I made a jsfiddle to clearly visualize the problem:
JSFiddle wd5s9vq0, visualizing the following Code:
HTML-Code:
<div class="container">
<div class="content-cell"></div>
<div class="content-cell"></div>
</div>
<div class="container">
<div class="content-cell">
This cell has an inreased height because of
it's content. The empty space below the
content is the 75% of the cells width.
</div>
<div class="content-cell"></div>
</div>
CSS:
.container {
display: flex;
width: 400px;
}
.content-cell {
flex: 1 1 0;
margin: 10px;
background-color: #ccc;
}
.content-cell::after {
content: "";
display: block;
padding-top: 75%;
}
If I didn't knew it better, it looks like a floating-problem - but I think the ::before / ::after selector should add the block-element before the element it is used on and not inside it.
Does anyone has an idea on how to fix this problem?
This seems to be a very widespread problem on the internet, and most solutions you find are either about wrapping the content, absolute-positioning the content or a mixture of both. This has numerous and case-dependent downsides. After hours of playing around with the code, I finally found a combination of CSS proporties that work without the need to add any DOM or make the content absolute-positioned. This looks quit basic, and I am wondering why it took me so long and why you can't find it out there on the web.
The HTML:
<div class="mybox aspect-full">
This is text, that would normally extend the box downwards.
It is long, but not so long that it extends the intended aspect-ratio.
</div>
The CSS:
.mybox {
width: 200px;
}
.aspect-full::before {
content: '';
display: block;
padding-top: 100%;
float: left;
}
The only downside I could find is that the content of your cell must float. If you use clear on one of your child objects, it is positioned below the expander-block and you are back to the original problem. If you need to clear the floating of divs inside of these aspect-ratio-cells, you might consider to wrap them and keep the wrapper floatable.

Bootstrap grid formatting

I'm trying to format a slide in a bootstrap that has the format of the following fiddle: fiddle
The two divs with "hidden" in them are meant to disappear when on desktop so that when someone is using a tablet or phone they stack on top of each other. This works fine in the fiddle where the height is set to a fixed number
height: 100px;
But I don't want to set the height this way. If I remove this line you can see in the fiddle that "hidden2" drops down in a weird way instead of acting as a spacer for the text content on the bottom. I've also noticed if I remove the img tag the grid works fine.
I'm not sure why it does this and with real content it just looks like there's no spacer and all the text hugs the left side. Any ideas?
Edited: You can have a width of the content so there is space on both sides, and using the bootstrap grid system drop the text content down.
HTML
<div class="whole">
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4">
<img src="http://placehold.it/100x100"/>
</div>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8">text content</div>
</div>>
CSS
div {
height: 100px;
background: red;
border: 1px solid black;
text-align: center;
}
img {
border-radius: 50%;
}
.whole {
margin: 0 10%;
width: 80%;
}
As much as i understood from your question, you're trying to preserve the functionality found on the fiddle link you provided, but also preserving equal heights. I also understand that you do not want to assign the height manually (i.e in your case, hard-coded).
There are two ways of approaching the solution: Javascript or CSS3.
Javascript:
I usually wouldn't solve layout issues with Javascript, but since your scenario has more than one row invloved, the easy way is JavaScript. With the help of jQuery, you can iterate through the div elements, having an initialized variable (example: var bHeight = 0). Check for each element's height; if it's greater, assign it to bHeight.
Your code should something like this:
$(document).ready(function(){
var bHeight = 0;
$("div").each(function(){
if($(this).height() > bHeight)
bHeight = $(this).height();
}); //end of loop
//now, assign height to all
$("div").height(bHeight);
});
This method will allow you to assign the height of your columns dynamically.
CSS3:
A little research online cold introduce you to the CSS3 display: flex, yet it's totally up to you to decide regarding browser support (CSS flex Property), and more details on solving your issue here: (A Complete Guide to Flexbox)

how to make the height of all three sections same?

I've attached a screenshot with this question. There are three columns and I want to keep the height of all the three columns exactly same. I managed to keep the width same with width css property now i wanted to adjust to height. Can anyone help me out in this regard. Thanks in advance.
I would use the following CSS to achieve this:
.wrapper {
display: table;
table-layout: fixed;
width: 100%;
}
.column {
display: table-cell;
}
With table-layout: fixed you're telling every child elements with display: table-cell to have same width, equally distributed based on wrapper's width, as well equal height.
Demo
In pure CSS you can use CSS3 columns: for a 3-column layout just try with
<div style="columns:3">...</div>
(with both -moz- and -webkit- prefixes)
See https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multi-column_layouts for the reference, in particular about the height balancing:
Height Balancing
The CSS3 Column specification requires that the column heights must be balanced: that is, the browser automatically sets the maximum column height so that the heights of the content in each column are approximately equal.
There is actually no right, cross browser way to do this, but rather you have to resort to some hacks.
A method I have used previously is to wrap the three columns inside a container and set a custom background to the hole container. Basically you create an image, having the same width of the website, having the two vertical lines, and you set it as the background of the container.
<div class="wrapper">
<div class="column">....</div>
<div class="column">....</div>
<div class="column">....</div>
</div>
<style> .wrapper { background-image: url(wrapper-bg.png); } </style>
You could use a javascript library like http://www.cssnewbie.com/equalheights-jquery-plugin/#.UVwCaZAW200 to achive this. This method however does not work if, the hight of the columns is dinamically changing in height (e.g. you have a collapsable item in it). Of course you can handle this cases by handling those events and recalculating the hight.
Finally you could use height: 100%. It's not as simple as it seems however! This solution does only work for block elements and the size of the parent has to be known. So, if you know the size of the website in advance you can do something like the following:
<div class="wrapper">
<div class="column">....</div>
<div class="column">....</div>
<div class="column">....</div>
</div>
<style>
.wrapper { height: 1000px; width:900px; }
.column { width:300px; float:left; height: 100%; }
</style>
Hopefully this will become simpler in future....

How to float divs left with shorter divs one below anoter

I have a list of dynamically generated divs that represent panels for selecting various options. There are two types of divs, regular ones and short ones. The height of the regular divs is set with javascript to te height of the tallest one. Additionally, if the height of te short div is less than half of the maximum it is set to half of that height, otherwise it is set to the full height.
What I would want to do now (preferably with CSS) is to list those items in such a way that if there is enough space, to put one short div below another sort div.
Here are some illustrations to hopefully make things clearer:
As far as I can see, this is not possible purely with CSS: If you provide the small boxes with clear: left, they will appear below all others. If you don't, they will appear next to each other.
The simplest workaround I can think of is to manually group two small boxes into a separate div. Here's a working example:
<html>
<head>
<style type="text/css">
div.large, div.small { width: 40px; margin: 5px; }
div.large { height: 95px; background-color: blue; }
div.small { height: 45px; background-color: red; }
div.large, div.smallblock { float: left; }
</style>
</head>
<body>
<div class="large">1</div>
<div class="large">2</div>
<div class="smallblock">
<div class="small">3</div>
<div class="small">4</div>
</div>
<div class="smallblock">
<div class="small">5</div>
<div class="small">6</div>
</div>
<div class="large">7</div>
</body>
</html>
There is no generic pure CSS solution.
See a previous answer of mine for a comparison of the candidate techniques:
CSS Floating Divs At Variable Heights
Unless you can use server-side code to manually calculate pixels and use position: relative / position: absolute; top: ?px; left: ?px, you will have to resort to JavaScript to handle the positioning.
This jQuery plugin is generally a good solution: jQuery Masonry
There's also a raw JavaScript version: Vanilla Masonry
I find myself recommending it somewhat regularly:
https://stackoverflow.com/search?q=user%3A405015+masonry
Some possibly relevant demos:
http://desandro.com/demo/masonry/docs/filtering.html
http://desandro.com/demo/masonry/docs/animating-jquery.html
http://desandro.com/demo/masonry/docs/appending.html

What's the preferred solution to fixing non-clickable content after applying an IE6 filter for pngs?

<div id="calendar">
<p>Text</p>
<div class="section">blah</div>
</div>
I'm applying the PNG to #calendar, in IE6 I use filter but it makes the content not clickable - I believe the way around this was to force everything inside to be positioned ( eg position:relative ) and have a z-index + hasLayout but sometimes it doesn't work.
Should I instead wrap all my stuff in another div and apply the png BG to a sibling node such like this, or what?
<div id="calendar">
<div id="calendar-bg"></div>
<div id="calendar-content">
<p>Text</p>
<div class="section">blah</div>
</div>
</div>
Then force the calendar-bg to be absolutely positioned and 100% width/height, and relatively position #calendar-content on top of it? Or is there some other hidden way that the mainstream png fixer scripts ( ala htc, jquery.pngFix ) work?
That is indeed the (only) correct solution to this problem I ever came across. You can't rely on your first solution (positioning the childs relatively), because the opacity filter in IE is thrown over all child elements, with the child elements not being clickable as a result.
So just make sure the png is not in the parent element of a clickable element.
So, create a parent with the property 'position: relative' (or absolute, depends on your layout) and insert two children for the background and the actual content.
Example:
<div id="calendar">
<div id="calendar-bg"></div>
<div id="calendar-content">
<p>Text</p>
</div>
</div>
#calendar { position: relative; }
#calendar #calendar-bg {
position: absolute;
left: 0;
top: 0;
height: 100%; /* Or the height and width in pixels if you know them */
width: 100%; }
#calendar #calendar-content {
position: relative;
z-index: 1; }
I believe the way around this was to force everything inside to be positioned ( eg position:relative ) and have a z-index + hasLayout but sometimes it doesn't work.
Position:relative doesn't trigger hasLayout. You should try something simple like zoom:1 with a z-index.
I'm pretty sure (going from my memory of dealing with a similar problem) that trying to relatively position stuff on top of a png in IE6 doesn't work, but specifying z-index does.

Resources