Oh, the golden days of table-based layouts. Shouldn't we all go back there and screw semantics? (I know, I know, ...)
But I have a tricky website layout that is done in seconds and very few lines of code if I use a table. I have been pulling my hair over achieving the same with divs for two days now. Maybe someone can help.
This is the layout I want to achieve:
http://jsfiddle.net/reltek/13c6yfmh/
This is the code using tables, nice and easy:
<table border="1" width="100%">
<tr>
<th rowspan="2" width="30%" valign="top">
<h2>Main Navigation</h2>
<p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
</th>
<td valign="top">
<h1>Main Content</h1>
<p>Flexible, might get really long.</p>
</td>
</tr>
<tr>
<td height="3em">
<h2>Footer</h2>
<p>flexible height, should stay at the bottom of the page.</h2>
</td>
</tr>
</table>
My div-based HTML can be found here: http://jsfiddle.net/reltek/48rmshen/
The problem is: the footer on the right doesn't stay at the bottom, if the left column is longer than the right one.
Any help appreciated, thanks everyone!
This is a job for flexbox (prefixing and workarounds for older browsers left as an exercise for the reader)
body {
display: flex;
}
nav {
background: red;
}
.non-nav {
display: flex;
flex-direction: column;
}
main {
background: green;
flex-grow: 1;
}
footer {
background: blue;
flex-shrink: 1;
}
<nav>
<h2>Main Navigation</h2>
<p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
</nav>
<div class="non-nav">
<main>
<h1>Main Content</h1>
<p>Flexible, might get really long.</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>end of text</p>
</main>
<footer>
<h2>Footer</h2>
<p>flexible height, should stay at the bottom of the page.</p>
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
</footer>
</div>
In keeping with your display:table in your example the following works.
Here is the jsfiddle http://jsfiddle.net/r4pg8p25/2/
You can add and subtract your empty paragraphs and see it expand and contract in sync with the left hand panel.
Hope this helps,
Tim
<html>
<header>
<style>
html, body { text-align: justify; height: 100%; }
.layout { display: table; height: 100%;}
.layout .columns-container { display: table-row; height: 100%;}
.layout .columns-container .column { display: table-cell; height: 100%;}
.layout .top { display: table-row; height: 100%;}
.layout .bottom { display: table-row; height: 100%;}
.layout .top .main{ display: table-cell; height: 100%;}
.layout .top .footer{ display: table-cell; height: 100%;}
.one-third { width:33%; float: left; height: 100%;}
.two-thirds { width:66%; height:100%; float: right; }
.main-footer { height: 100%; }
.nav { background: red; padding: 20px; }
.main { background: green; padding: 20px; height: 100%; }
.footer { background: brown; padding: 20px; height: 150px; }
</style>
</header>
<body>
<div class="layout">
<div class="columns-container">
<div class="column one-third">
<div class='nav'>
<h2>Main Navigation</h2>
<p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
padding-bottom:100%; margin-bottom:-100%;
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>end</p>
</div>
</div>
<div class="column two-thirds">
<div class="layout main-footer">
<div class='top'>
<div class="main" role="main">
<h1>Main Content</h1>
<p>Flexible, might get really long.</p>
<p>end of text</p>
</div>
</div>
<div class='bottom'>
<div class="footer">
<section id="colophon" class="site-info" role="contentinfo">
<h2>Footer</h2>
<p>flexible height, should stay at the bottom of the page.</p>
</section>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
You can make use of display:table but unfortunately you can't do rowspan so you need to get a bit creative with the div structure:
html, body {
min-height:100%;
padding:0;
margin:0;
}
#wrapper {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
}
.table {
display:table;
width:100%;
height:100%;
}
.row {
display:table-row;
}
.cell {
display:table-cell;
}
#left-column {
width:30%;
background:red;
}
#right-column {
width:70%;
height:100%;
}
#content, #header {
height:100%;
}
#header {
background-color:green;
}
#footer {
background-color:blue;
}
<div id="wrapper">
<div class="table">
<div class="row">
<div id="left-column" class="cell">
<h2>Main Navigation</h2>
<p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
</div>
<div id="right-column" class="cell">
<div id="content" class="table">
<div id="header" class="row">
<div class="cell">
<h1>Main Content</h1>
<p>Flexible, might get really long.</p>
</div>
</div>
<div id="footer" class="row">
<div class="cell">
<h2>Footer</h2>
<p>flexible height, should stay at the bottom of the page.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Example Fiddle
Related
I am trying to place my social and email links found with a ul additional-menu, to be displayed under my site's logo and tagline. I seem to be struggling getting it underneath. At the moment it looks like this:
The code below is like so:
.additional-menu {
list-style-type:none;;
margin: 0;
position:relative;
clear:both
}
.additional-menu li{
display:inline-block;
}
.ast-header-html-1{
position:relative;
clear:both;
}
<div class="ast-site-title-wrap">
<h1 class="site-title" itemprop="name">
<a href="https://puffpastrydelights.com/" rel="home" itemprop="url">
Pastry Delights
</a>
</h1>
<p class="site-description" itemprop="description">
Made with love, served with pride
</p>
</div>
<div class="ast-builder-layout-element ast-flex site-header-focus-item ast-header-html-1" data-section="section-hb-html-1">
<div class="ast-header-html inner-link-style-">
<div class="ast-builder-html-element">
<ul class="additional-menu">
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</div>
Wrap the whole thing with div that has display:flex and flex-direction: column
.wholeThing {
display: flex;
flex-direction: column;
border: 1px solid red;
}
.firstBit {
display: flex;
border: 1px solid blue;
}
<div class="wholeThing">
<div class="firstBit">
<div class="logo"><img src="http://placekeanu.com/250" /></div>
<div class="tagline">Keanu is breath taking</div>
</div>
<div class="social">
social one two three
</div>
</div>
`
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I want to select #com19 ?
.comment {
width:470px;
border-bottom:1px dotted #f0f0f0;
margin-bottom:10px;
}
.comment:last-child {
border-bottom:none;
margin-bottom:0;
}
That does not work as long as I do have another div.something as actual last child in the commentList. Is it possible to use the last-child selector in this case to select the last appearance of article.comment?
jsFiddle
:last-child only works when the element in question is the last child of the container, not the last of a specific type of element. For that, you want :last-of-type
http://jsfiddle.net/C23g6/3/
As per #BoltClock's comment, this is only checking for the last article element, not the last element with the class of .comment.
body {
background: black;
}
.comment {
width: 470px;
border-bottom: 1px dotted #f0f0f0;
margin-bottom: 10px;
}
.comment:last-of-type {
border-bottom: none;
margin-bottom: 0;
}
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I guess that the most correct answer is: Use :nth-child (or, in this specific case, its counterpart :nth-last-child). Most only know this selector by its first argument to grab a range of items based on a calculation with n, but it can also take a second argument "of [any CSS selector]".
Your scenario could be solved with this selector: .commentList .comment:nth-last-child(1 of .comment)
But being technically correct doesn't mean you can use it, though, because this selector is as of now only implemented in Safari.
For further reading:
https://drafts.csswg.org/selectors-4/#the-nth-child-pseudo
http://caniuse.com/#search=nth-child
If you are floating the elements you can reverse the order
i.e. float: right; instead of float: left;
And then use this method to select the first-child of a class.
/* 1: Apply style to ALL instances */
#header .some-class {
padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
padding-right: 20px;
}
This is actually applying the class to the LAST instance only because it's now in reversed order.
Here is a working example for you:
<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
border: 1px solid red;
padding-right: 0;
}
#header .some-class~.some-class {
border: 0;
padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
<img src="some_image" title="Logo" class="lfloat no-border"/>
<ul class="some-class rfloat">
<li>List 1-1</li>
<li>List 1-2</li>
<li>List 1-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 2-1</li>
<li>List 2-2</li>
<li>List 2-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 3-1</li>
<li>List 3-2</li>
<li>List 3-3</li>
</ul>
<img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>
Something that I think should be commented here that worked for me:
Use :last-child multiple times in the places needed so that it always gets the last of the last.
Take this for example:
.page.one .page-container .comment:last-child {
color: red;
}
.page.two .page-container:last-child .comment:last-child {
color: blue;
}
<p> When you use .comment:last-child </p>
<p> you only get the last comment in both parents </p>
<div class="page one">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
<p> When you use .page-container:last-child .comment:last-child </p>
<p> you get the last page-container's, last comment </p>
<div class="page two">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
The new :has() pseudo class (not yet supported by all browsers) lets you get pretty close to a solution:
.class:has(+ :not(.class))
The limitation is that this will find any element with .class which is followed by an element that doesn't have this class. But this would match the use case of the question.
What about this solution?
div.commentList > article.comment:not(:last-child):last-of-type
{
color:red; /*or whatever...*/
}
This can now be solved with careful use of :has(), specifically:
/* switch out the {class} below */
.{class}:not(:has(~ .{class}))
A similar technique also allows you to select anything but the last occurrence of a class in a container, or the last occurrence within a group of elements. See the snippet below for examples.
Note: has() is currently supported in Chrome, Edge and Safari, but not Firefox (Jan 2022)
/* last in group */
.class:has(+ :not(.class)) {
background: pink;
}
/* anything but last in container */
.class:has(~ .class) {
box-shadow: 0 0 0 1px #F00A;
}
/* last in container */
.class:not(:has(~ .class)) {
background: #0F0A;
}
<div>
<div class="class">not-last</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">last-class</div>
<div>---</div>
</div>
There are two ways to select the last element of a class.
Wrap your elements in a container element.
html:
<div class="container">
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
<div>
css:
.container:last-child {
color: red;
}
If you don't want to wrap your elements within another element then you can leverage last-of-type.
html:
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
css:
.member:last-of-type{
color: red;
}
I'm looking to change the background color of a footer. I tried making another div around it which worked but no matter what the background-color didn't budge. I must be overlooking something obvious!
This is what I have right now: http://jsfiddle.net/x5yvm50r/
And the code:
<div class="floatleft">
<h3>Heading</h3>
<ul>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
</div>
<div class="floatleft">
<h3>Heading</h3>
<img src="http://i.imgur.com/N23RQo5.png">
</div>
<div class="floatleft">
<h3>Heading</h3>
social icons
</div>
<div class="clear"></div>
.floatleft {float: left; margin: 0 20px 0 0; width: 400px;}
.clear {clear:both}
If anyone has any idea, I'd really appreciate pointing me in the right direction! This is more or less what I'm hoping for it to look like eventually
Thanks! :)
Simple, you should wrap the content in a seperate block level element (i.e. div or footer). Here is the updated fiddle, using a block level element with id="wrapper": http://jsfiddle.net/df1zjwmb/1/
<footer id="wrapper">
<div class="floatleft">
<h3>Heading</h3>
<ul>
<li>Link 1
</li>
<li>Link 1
</li>
<li>Link 1
</li>
<li>Link 1
</li>
</div>
<div class="floatleft">
<h3>Heading</h3>
<img src="http://i.imgur.com/N23RQo5.png">
</div>
<div class="floatleft">
<h3>Heading</h3>
social icons
</div>
<div class="clear"></div>
</footer>
And the CSS:
#wrapper {
background-color: green;
}
Clearing floated elements means that elements below the clear will be reset, but does not turn the floated elements into a block itself. To solve the problem requires adding a wrapper div, which creates a block level element that you can apply a background color to. Or you could use something other than floats, like inline blocks.
Here is more information: Advantages of using display:inline-block vs float:left in CSS
Check this fiddle
HTML
<div class="floatleft footcontainer">
<div class="floatleft">
<h3>Heading</h3>
<ul>
<li>Link 1
</li>
<li>Link 1
</li>
<li>Link 1
</li>
<li>Link 1
</li>
</div>
<div class="floatleft">
<h3>Heading</h3>
<img src="http://i.imgur.com/N23RQo5.png">
</div>
<div class="floatleft">
<h3>Heading</h3>
social icons</div>
<div class="clear"></div>
</div>
CSS
.floatleft {
float: left;
margin: 0 20px 0 0;
width: 400px;
}
.clear {
clear:both
}
.footcontainer {
background-color:lightblue;
float:left;
}
I've added a div which holds the 3 divs and gave it the background color and the float property.
Here you go: http://jsfiddle.net/5s4w19zy/
I wrapped the three floated divs in a container div (footer) and then floated them inside of that.
<footer>
<div>
<h3>Heading</h3>
<ul>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
</ul>
</div>
<div>
<h3>Heading</h3>
<img src="http://i.imgur.com/N23RQo5.png">
</div>
<div>
<h3>Heading</h3>
social icons
</div>
<div class="clear"></div>
</footer>
footer
{
width: 100%;
height: 150px;
background: #f5f5f5;
overflow: hidden;
}
footer div
{
float: left;
display: block;
margin: 0 0 0 0;
width: 33.333333%;
height: 150px;
}
.clear {clear:both}
HTML5 offers semantic markup tags, and since you need a wrapper for your footer (allowing a parent element to have a the background-color property of your choosing), <footer> tag sounds like the way to go:
<footer id="footer">
<div class="floatleft">
<h3>Heading</h3>
<ul>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
</div>
<div class="floatleft">
<h3>Heading</h3>
<img src="http://i.imgur.com/N23RQo5.png">
</div>
<div class="floatleft">
<h3>Heading</h3>
social icons
</div>
<div class="clear"></div>
</footer>
#footer { background-color:#asYouLikeIt; }
I have used flex box:
check this : http://jsfiddle.net/x5yvm50r/9/
HTML:
<footer>
<section class="left">l</section>
<section class="center">c</section>
<section class="right">r</section>
</footer>
CSS:
footer{
width:100%;
display:flex;
}
footer section{
flex:1;
}
I am trying to make my list items all the same width. I've tried setting the widths in the css and nothing changes. Can anyone figure this out?
Here is an image to show what I am talking about:
HTML:
<body>
<div class="content-wrapper" id="container">
<header>logo
<nav>navigation</nav>
</header>
<div class="clear-fix"></div>
<div id="body">
<section class="main-content">
<section class="leftPane">
<h2>Categories</h2>
</section>
<section class="rightPane">
<div class="checkout">
<h1>Checkout</h1>
<ul class="steps">
<li><a href="http://localhost:59213/Cart">
<div id="step0" class="arrow_box_grey">
Shopping Cart</div>
</a>
</li>
<li><a href="http://localhost:59213/Cart/Student">
<div id="step1" class="arrow_box_grey">
Student</div>
</a>
</li>
<li><a href="http://localhost:59213/Cart/Delivery">
<div id="step2" class="arrow_box_grey">
Delivery</div>
</a>
</li>
<li>
<div id="step3" class="arrow_box_green">Payment</div>
</li>
<li>
<div id="step4" class="arrow_box_blue">Finish</div>
</li>
</ul>
</div>
</section>
<div class="clear-fix"></div>
</section>
</div>
</div>
And here if my fiddle with the code: http://jsfiddle.net/M74Em/
You need to change this style:
.main-content .checkout ul.steps li div {
display: inline;
width: 1000px;
}
You can't set widths for inline elements so try this:
.main-content .checkout ul.steps li div {
display: inline-block;
width: 100px;
}
Example
From twBootstrap, applied to <ul>'s (demo):
.ul-justified {
display: table;
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
.ul-justified > li {
display: table-cell;
float: none;
width: 1%;
}
and slap .ul-justified to any ul-list you want aligned, and you get equal width <li>'s automatically fit parent ul's width.
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I want to select #com19 ?
.comment {
width:470px;
border-bottom:1px dotted #f0f0f0;
margin-bottom:10px;
}
.comment:last-child {
border-bottom:none;
margin-bottom:0;
}
That does not work as long as I do have another div.something as actual last child in the commentList. Is it possible to use the last-child selector in this case to select the last appearance of article.comment?
jsFiddle
:last-child only works when the element in question is the last child of the container, not the last of a specific type of element. For that, you want :last-of-type
http://jsfiddle.net/C23g6/3/
As per #BoltClock's comment, this is only checking for the last article element, not the last element with the class of .comment.
body {
background: black;
}
.comment {
width: 470px;
border-bottom: 1px dotted #f0f0f0;
margin-bottom: 10px;
}
.comment:last-of-type {
border-bottom: none;
margin-bottom: 0;
}
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I guess that the most correct answer is: Use :nth-child (or, in this specific case, its counterpart :nth-last-child). Most only know this selector by its first argument to grab a range of items based on a calculation with n, but it can also take a second argument "of [any CSS selector]".
Your scenario could be solved with this selector: .commentList .comment:nth-last-child(1 of .comment)
But being technically correct doesn't mean you can use it, though, because this selector is as of now only implemented in Safari.
For further reading:
https://drafts.csswg.org/selectors-4/#the-nth-child-pseudo
http://caniuse.com/#search=nth-child
If you are floating the elements you can reverse the order
i.e. float: right; instead of float: left;
And then use this method to select the first-child of a class.
/* 1: Apply style to ALL instances */
#header .some-class {
padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
padding-right: 20px;
}
This is actually applying the class to the LAST instance only because it's now in reversed order.
Here is a working example for you:
<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
border: 1px solid red;
padding-right: 0;
}
#header .some-class~.some-class {
border: 0;
padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
<img src="some_image" title="Logo" class="lfloat no-border"/>
<ul class="some-class rfloat">
<li>List 1-1</li>
<li>List 1-2</li>
<li>List 1-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 2-1</li>
<li>List 2-2</li>
<li>List 2-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 3-1</li>
<li>List 3-2</li>
<li>List 3-3</li>
</ul>
<img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>
Something that I think should be commented here that worked for me:
Use :last-child multiple times in the places needed so that it always gets the last of the last.
Take this for example:
.page.one .page-container .comment:last-child {
color: red;
}
.page.two .page-container:last-child .comment:last-child {
color: blue;
}
<p> When you use .comment:last-child </p>
<p> you only get the last comment in both parents </p>
<div class="page one">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
<p> When you use .page-container:last-child .comment:last-child </p>
<p> you get the last page-container's, last comment </p>
<div class="page two">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
The new :has() pseudo class (not yet supported by all browsers) lets you get pretty close to a solution:
.class:has(+ :not(.class))
The limitation is that this will find any element with .class which is followed by an element that doesn't have this class. But this would match the use case of the question.
What about this solution?
div.commentList > article.comment:not(:last-child):last-of-type
{
color:red; /*or whatever...*/
}
This can now be solved with careful use of :has(), specifically:
/* switch out the {class} below */
.{class}:not(:has(~ .{class}))
A similar technique also allows you to select anything but the last occurrence of a class in a container, or the last occurrence within a group of elements. See the snippet below for examples.
Note: has() is currently supported in Chrome, Edge and Safari, but not Firefox (Jan 2022)
/* last in group */
.class:has(+ :not(.class)) {
background: pink;
}
/* anything but last in container */
.class:has(~ .class) {
box-shadow: 0 0 0 1px #F00A;
}
/* last in container */
.class:not(:has(~ .class)) {
background: #0F0A;
}
<div>
<div class="class">not-last</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">last-class</div>
<div>---</div>
</div>
There are two ways to select the last element of a class.
Wrap your elements in a container element.
html:
<div class="container">
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
<div>
css:
.container:last-child {
color: red;
}
If you don't want to wrap your elements within another element then you can leverage last-of-type.
html:
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
css:
.member:last-of-type{
color: red;
}