Lay out children with equal space between each other to fill container - css

I have a div with a variable width, and I have a variable amount of children inside this div. I want the children to fill up the space inside the div. I first tried to change the div to display:table and the children to display:table-cell but I ended up all the children filling up all the space and not obeying their width and max-width properties. Then I've tried the table approach: I've changed the div to a table (yes, I know, it's not recommended, that's why I'm probably here asking) and wrapped the children into a tr and each in tds, but I ended up all the children cells filling up the whole space, but aligned to left (I've set the children divs display:inline-block):
If I change the alignment to center, I get this:
They are centered, but I still get spaces on the left and right of the parent (with the yellow background that I've set for distinguishing). What I actually want is this:
I've achieved this by setting the first td to align text to left, the second to center, the third to right. But I may have more of these thumbnails, so I need a general solution.
How can I lay out a variable number of children inside a container to fill the width, with the first element starting at the exact left border of the container (unlike the second image) and the last element ending at the exact right border of the container (like shown in the third image)?

Something like this?
HTML:
<div>
<span id="s1"></span>
<span id="s2"></span>
<span id="s3"></span>
</div>
CSS:
div{
background: #ff6;
text-align: justify; /* Important */
font-size: 0; /* Used to remove spaces */
}
div:after{ /* Used to create a new last line */
content: '.';
display: inline-block;
width: 100%;
height: 0;
overflow: hidden;
}
span{
display: inline-block;
height: 150px;
}
/* Use your widths, min-widths and max-widths here: */
#s1{
background: red;
width: 15%;
min-width: 50px;
max-width: 150px;
}
#s2{
background: green;
width: 40%;
min-width: 50px;
max-width: 250px;
}
#s3{
background: blue;
width: 40%;
min-width: 50px;
max-width: 200px;
}
Demo
You can obtain equally spaced boxes using text-align: justify on the wrapper. The problem is that it doesn't work for the last line (which in this case is the first too), so you can either use text-align-last, or an :after pseudo element with width: 100% in order to create a new last line.

Related

How to set height of flex row but still allow row to expand vertically?

Consider this very simple header:
.box {
height: 100%;
width: 50px;
background-color: blue;
}
.row {
display: flex;
height: 60px;
background-color: yellow;
}
<div class="row">
<div class="box"></div>
<h1>This string needs to be able to wrap</h1>
</div>
The blue box needs to be defined by the height of the row and the text needs to be able to wrap. But as you can see, when the text wraps it extends beyond the flexbox. The flexbox can't grow at all because I have defined its height. If I remove the height specification then text wrap works correctly but the blue box disappears. This is a quite frustrating problem that I have spent hours trying to figure out. Is there no way to say to the row "your height is 60px but you can go bigger if you need to".
What I've tried so far:
Use min-height: 60px. For some reason the blue box still doesn't show up when I do this.
Use max-height: 100px. The row defaults to that size which is too big for when the text doesn't wrap.
I guess I could write media queries to manually change the height of the row, but it seems like there should be a more flexboxy way of doing this. Any ideas?
Here is the JS Fiddle if you want to play with it.
You don't need height: 100%; on child element of flex element.
And if you want minimum height of 60px on parent element, use min-height: 60px; instead of height: 60px;
.box {
width: 50px;
background-color: blue;
}
.row {
display: flex;
background-color: yellow;
min-height: 60px;
}
Here is the fiddle
https://jsfiddle.net/3bzeht52/

Header height to fit background image

I have a question related to header height.
HTML:
<header>
<h1>
Hello World!
</h1>
</header>
CSS:
header {
background-image: url("../images/header.png");
background-size: cover;
height: 100%;
text-align: center;
color: white;
}
In this case header height fits text height. Is there a way to set header height the same as image height?
You could do the header image as a foreground img tag rather than background image and then do this in the CSS
header {
position: relative;
}
header img {
width: 100%;
height: auto;
}
header h1 {
position: absolute;
top: 0;
}
In the header's css, you can put:
background: url("../images/header.png") 50% 50% / 100% no-repeat fixed;
It will automatically place and size the image so it's not stretched.
Why don't you just use Flexbox? It's the defacto standard these days.
Here is a jsfiddle what I have in mind:
JSFiddle example
Essentially, what you want to do is your <h> element should actually be a child of another div within your <header>:
<header>
<div class="backimage">
<h1>
Hello World!
</h1>
</div>
</header>
Your <header> div, as the flex "container", display child elements as column, without wrap, aligned in the center with space around, and justified center:
header {
display: flex;
flex-flow: column nowrap;
justify-content: space-around;
align-items: center;
align-content: space-around;
}
Child elements within the flex "container" should be ordered for number of appearance either as a row or column, in this case the "container" displays items in a column layout, so you want your header to appear as the first item. flex is shorthand for flex-grow, flex-shrink, and flex-basis; this third one being what size the element should be, the first two controlling what priority or portion of the container element this child element will be treated as compared to other children. In this case, handle it auto. We want to reposition the header to be vertically centered in the containing div, so position: relative;, add 50% of the container's height to the origin point of the ` element's origin (which always starts from the top left of an object), and because the text default is set at 1em, it would logically follow that .5em would be the center, so subtract that from the 50%. Give it text-align center for horizontal centering:
header h1 {
position: relative;
top: 50%;
margin-top: -.5em;
text-align: center;
order: 1;
flex: 1 0 auto;
}
Then you just have to worry about your background. Background, no repeat, define the height of the image (which in this case will be applied to the div itself), border here for example just so you can see the boundary of the div, and don't forget that this should appear second compared to the header:
.backimage {
background-image: url('http://upload.wikimedia.org/wikipedia/ \
commons/4/47/PNG_transparency_demonstration_1.png');
background-repeat: no-repeat;
border: 1px solid blue;
width: 500px;
height: 300px;
order:2;
}
Here's what you end up with:
Here's a great guide on flexbox usage:
Flexbox guide

How to proportionally fill a space around a fixed size div?

Could someone please help me?
I have three divs.
enter code here
The one in the middle should always be 1040px.
The left and right one shall fill the whole left space.
How can I make them proportionally grow/shrink when I resize the window?
Here is the code:
http://codepen.io/christophz/pen/413d31df9d33e1205b73bed3ebee1f5d
Thank you very much in advance!
Here is a pure CSS option using CSS display properties of table and table-cell.
DEMO: http://jsfiddle.net/audetwebdesign/a9J7D/
The markup is the same as you proposed.
The CSS is:
.container {
width: 100%;
min-width: 540px; /* you may want this... */
margin: 0 auto;
outline: 1px dashed blue;
display: table;
}
.bar-light {
width: auto;
height: 52px;
background-color: blue;
display: table-cell;
}
.bar-dark {
width: 540px;
height: 52px;
background-color: red;
display: table-cell;
}
Set display: table to .container and for the child elements, display: table-cell.
For .bar-light, set the width to auto and they will be computed to fill in the remainder of the page width (equally).
In my example, I set the center width to 540px to make it easier to see in the fiddle.
Finally, add a min-width to .container, without any content, the table cells will collapse to zero width as you shrink the window size.
Note About Heights
This layout will create three columns of equal height, the height will be computed to enclose the tallest of the three child elements.
This is real quick so it might be slightly off but you should be able to get the idea
HTML
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
CSS
div { float: left;}
.b { width: 1040px;}
JQuery
$(document).onload(resize);
$(window).resize(resize);
function resize() {
var ww = $(window).width();
var width = (ww-1040)/2;
$('.a').width(width);
$('.b').width(width);
}
Add a table with 3 column. In the middle column add you div. specify the size you want for this for these column e.g. 10-80-10. or -80-.

Is there a way to make background color stretch alongwith the content on h2?

I have following set in the css for the h2 element:
...
width: 10%;
display: block;
background-color: #eee;
overflow-x: visible;
white-space: nowrap;
...
If I have an h2 header with text that cannot fit on one line (on the right-most column) this helps me push the text over to the side. I want the full width of the text to have the background color, and hence the "display: block;" rule. But this does not work. Only the width (10%) is colored.
Any suggestions?
Thx,
Tabrez
Here is an example with sample code: http://jsfiddle.net/VZccE/18
The chosen solution: Got rid of the width from h2 per suggestion from ptriek. I had it sitting there by mistake. It needed to be a couple of levels higher.
Just remove the width? I don't really understand why you set width to 10%?
I understand your question as "I want the header to wrap at width 10%, but still have a background for the entire width (100%)."
If that's what you mean, you can wrap the header in a div. If you apply the background to the div, you can set the header width do whatever you like.
demo
You can force the header to break out of the enclosing div by using absolute positioning. Here's an example:
HTML
<div>
<h2 id="hello">Hello World! I like cookies!</p>
</div>
CSS
div {
width: 50px; height: 100px;
background: #f00;
position: relative;
}
h2 {
white-space: nowrap;
background: #00f;
position: absolute;
left: 0; top: 0;
}
These background colors are just so you can see how the elements are positioned. You still need to specify white-space: nowrap to force the header into one line, but the special sauce that makes this work is the positioning. Notice how the enclosing element has position: relative - this ensures that the absolutely positioned h2 has its position based on the div, not the window.
See this in action: http://jsbin.com/aganam/3

Pixel and percentage width divs side-by-side

I've found a lot of similar questions, and tried out several solutions (including some of the so-called "holy grail" CSS layouts), but they don't quite do what I need.
I have a containing div (a CSS containing block) with id right. Inside it on the left side, I want a fixed-width div (a splitter bar, but it doesn't matter what it's being used for; id splitpane); on the right, filling the rest of the space, another div (id right-box below).
I've tried making the two inner divs display: inline-block (with vertical-align: top), setting the left one to width: 3px, but then there's no way to set the right to have width 100% - 3px. I've also tried using the float: left/margin-left: -100%/margin-left: 3px trick, but it has the same problem: the 100% plus the 3px overflows the parent containing block and causes a scroll bar to pop up. (Of course, it's not the scroll bar per se that's the problem; I could use overflow: hidden to remove it, but then content on the right would be truncated.)
Currently I'm using width: 99.5% for the right div, but that's a terrible hack (and is subject to overflow depending on screen width). It looks a bit like this:
<div id="right"><div id="splitpane"></div><div id="right-box">
...
</div></div>
With CSS as follows (float version, but the inline-block version is similar):
#right {
display: inline-block;
vertical-align: top;
height: 100%;
width: 85%; /* this is part of a larger div */
}
#right-box {
width: 99.5%; /* stupid hack; actually want 100% - 3px for splitter */
height: 100%;
}
#splitpane {
float: left;
width: 3px;
height: 100%;
background: white;
border-left: solid gray 1px;
border-right: solid gray 1px;
cursor: e-resize;
}
Is it even possible to do this? This is for an internal app., so solutions only need to work in Firefox 3 (if they are specific to FF3, though, preferably it's because the solution is standards-compliant but other browsers aren't, not because it's using Firefox-only code).
DIVs are the wrong element type for this since they don't "talk" to each other. You can achieve this easily with a table:
<table style="width:200px">
<tr>
<td id="splitpane" style="width: 3px">...</td>
<td id="rightBox" style="width: 100%">...</td>
<tr>
</table>
The 100% will make the rightBox as wide as possible but within the limits of the table.
This is possible. Because block level elements automatically expand to take up any remaining horizontal space, you can utilise a block level element next to an uncleared floated element with your desired width.
<style type="text/css">
div {
height: 100px;
}
#container {
width: 100%;
}
#left {
background: #FF0;
}
#splitpane {
position: relative;
float: right;
background: #000;
width: 3px;
}
</style>
<div id="container">
<div id="splitpane"></div>
<div id="left"></div>
</div>
See http://jsfiddle.net/georeith/W4YMD/1/
why you didn't use margin-left (since it was float layout) on right box?
so no need to create a splitter div...
#right{
width:200px; /*specify some width*/
}
#rightbox{
float:left;
margin-left: 3px; /*replace the splitter*/
/*margin: 0 3px; /*use this to give left & right splitter*/ */
}
yeah something like that, i hate empty div, it's not semantic and it's like putting a splitter on the "old" table way
If the div #right-box is only going to contain non-floated content it might be an idea to just put the content inside #right instead and let it wrap around the floated #splitpane.

Resources