Reputation: 28865
I have a page which is supposed to look thus:
It's the header here that's the cause of my problems. It contains:
An icon, in the far left end, which has a fixed size
A title, just to the right of the icon, which takes up just as much space as needed to fit the title text on one line
Sometimes, a subtitle arranged below the title
Sometimes, a box with some auxiliary stuff arranged to the right of the titles, using up any left-over space
I don't want to nest these elements, for various reasons (including but not limited to perfectionism), and I'm almost there... except that I can't get the last box, "auxiliary stuff", to fill the remaining space.
I've built this as columns, with the icon being 100% height, title and subtitle being <50% height, and the aux box being having 100% height. Giving the aux box a fixed width works fine, but when I try to make it grow horizontally with width: 100%
, the 100% seems to mean "100% of the surrounding box" (in my case, <heading>
) rather than "100% of the remaining space", which makes it overflow.
html, body { padding: 0; margin: 0; height: 100%; width: 100%; font: 10px sans-serif }
/* Colors to please the eyes */
article { border: 5em solid limegreen; }
header { border: 1px solid tomato; }
.icon { background-color: cyan; }
h1 { background-color: magenta; }
h2 { background-color: yellow; }
.aux { background-color: lavender; }
/* Arrange them boxes */
article {
display: flex;
flex-flow: column nowrap;
}
header {
display: flex;
flex-flow: column wrap;
align-content: flex-start;
height: 5em;
}
.icon { width: 5em; height: 100% }
h1 { font-size: 200%; margin: 0 }
h2 { font-size: 150%; margin: 0 }
.aux { height: 100%; width: 100%; }
<article>
<header>
<div class=icon>ICON</div>
<h1>Main header</h1>
<h2>Subheading here</h2>
<div class=aux>MOAR STUFF</div>
</header>
<section>
Lorem ipsum dolor sit amet...
</section>
</article>
Can I make the last box grow horizontally, without changing the markup?
Upvotes: 3
Views: 2155
Reputation: 371203
UPDATED SOLUTION (now that CSS Grid is available)
With the advent of CSS Grid, the layout is relatively simple. There is no need to alter the mark-up.
One key rule is this one:
grid-template-columns: 5em auto 1fr;
It establishes a grid with three columns. The widths of each column are specified, and inline with the requirements of the question.
The fr
unit is similar in concept to the flex-grow
property. It is designed to consume free space.
header {
display: grid;
grid-template-columns: 5em auto 1fr; /* set 3 columns at specified widths */
grid-template-rows: 50% 50%; /* set 2 rows at specified heights */
height: 5em;
}
.icon {
grid-row: span 2; /* span two rows (full height) */
}
h1 {} /* placed automatically based on source order */
h2 {
grid-column: 2; /* placed in column 2 */
}
.aux {
grid-column: 3;
grid-row: 1 / span 2;
}
/* non-essential decorative styles */
body { margin: 0; font: 10px sans-serif }
article { border: 5em solid limegreen; }
header { border: 1px solid tomato; }
.icon { background-color: cyan; }
h1 { background-color: magenta; font-size: 200%; margin: 0; }
h2 { background-color: yellow;; font-size: 150%; margin: 0; }
.aux { background-color: lavender; }
<article>
<header>
<div class=icon>ICON</div>
<h1>Main header</h1>
<h2>Subheading here</h2>
<div class=aux>MOAR STUFF</div>
</header>
<section>
Lorem ipsum dolor sit amet...
</section>
</article>
OLD (PRE-GRID) SOLUTION
If you define a width for the column containing the h1
and h2
, then getting the auxiliary box ("moar stuff") to stretch the remaining width of its parent is not a problem.
Try this:
HTML (no changes)
CSS
h1 {
font-size: 200%;
margin: 0;
width: 10em; /* new */
}
.aux {
height: 100%;
width: calc(100% - 10em - 5em - 10em); /* width less header column less icon
less green border */
}
Upvotes: 2
Reputation: 1579
My answer
html,
body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font: 10px sans-serif
}
/* Colors to please the eyes */
article {
border: 5em solid limegreen;
}
header {
border: 1px solid tomato;
}
.icon {
background-color: cyan;
}
h1 {
background-color: magenta;
}
h2 {
background-color: yellow;
}
.aux {
background-color: lavender;
}
header {
height: 5em;
position: relative;
}
.icon {
width: 5em;
height: 100%;
position: absolute;
}
h1 {
font-size: 200%;
margin: 0 0 0 calc(5em / 2); /* adjust for the font size */
float: left;
height: 1px;
}
h2 {
font-size: 150%;
margin: calc(1em * 200 / 150) 0 0 calc(5em / 1.5); /* adjust for the font size */
float: left;
clear: left;
}
.aux {
overflow: hidden;
height: 100%;
text-align: center;
}
<article>
<header>
<div class=icon>ICON</div>
<h1>Main header</h1>
<h2>Subheader here</h2>
<div class=aux>
MOAR STUFF MOAR STUFF
</div>
</header>
<section>
Lorem ipsum dolor sit amet...
</section>
</article>
The advantage is that .aux
takes on the correct size, so you can for example center stuff in it. The disadvantage is that you lose the background for the main header so you have to fake it on another element. But that can be done.
Upvotes: 1
Reputation: 5281
What essentially needs to be changed (given your rule to leave the HTML as-is), is:
header
fill its parentaux
fill of 100% (aux
will
grow as needed)aux
so it stays inside parenth1
and h2
a height of 50% so they wrap.h1
and h2
need to fill their boxes, so flex grow.small update
html,
body {
box-sizing: border-box;
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit
}
/* Colors to please the eyes */
article {
border: 5em solid limegreen;
}
header {
border: 1px solid tomato;
}
.icon {
background-color: cyan;
}
h1 {
background-color: magenta;
}
h2 {
background-color: yellow;
}
.aux {
background-color: lavender;
}
/* Arrange them boxes */
article {
display: flex;
flex-flow: column nowrap;
}
header {
background-color: lavender;
display: flex;
overflow: hidden;
width: 100%;
flex-flow: column wrap;
align-content: flex-start;
height: 5em;
}
.icon {
width: 5em;
height: 100%
}
h1 {
font-size: 200%;
margin: 0;
height: 50%;
}
h2 {
font-size: 150%;
margin: 0;
height: 50%;
}
.aux {
min-height: 100%;
max-width: 100%
}
<article>
<header>
<div class=icon>ICON</div>
<h1>Main header</h1>
<h2>Subheading here</h2>
<div class=aux>MOAR STUFF</div>
</header>
<section>
Lorem ipsum dolor sit amet...
</section>
</article>
Upvotes: 0
Reputation: 197
I don't know of any simple way to fix this without changing the markup. The trouble is that you have wrapping and stretching at the same time. If you removed the part that wraps, you could change the flex direction and stretch the final element.
Below is a solution with very little change to the markup. I placed the heading and subheading in a container.
html, body { padding: 0; margin: 0; height: 100%; width: 100%; font: 10px sans-serif }
/* Colors to please the eyes */
article { border: 5em solid limegreen; }
header { border: 1px solid tomato; }
.icon { background-color: cyan; }
h1 { background-color: magenta; }
h2 { background-color: yellow; }
.aux { background-color: lavender; }
/* Arrange them boxes */
article {
display: flex;
flex-flow: column nowrap;
}
header {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
height: 5em;
}
.icon, h1, h2 {
flex-shrink: noshrink;
}
.icon { width: 5em; height: 100% }
h1 { font-size: 200%; margin: 0 }
h2 { font-size: 150%; margin: 0 }
.aux { height: 100%; flex-grow: 1; }
<!DOCTYPE html>
<html>
<head>
<title>Flexicols</title>
</head>
<body>
<article>
<header>
<div class=icon>ICON</div>
<div class='subtitled-heading'>
<h1>Main header</h1>
<h2>Subheading here</h2>
</div>
<div class=aux>MOAR STUFF</div>
</header>
<section>
Lorem ipsum dolor sit amet...
</section>
</article>
</body>
</html>
Upvotes: 0