Replicating a stack of paper is a common design found on the web; it’s an easy way to make a design a little less harsh and digital by giving it an “analog” look. For a quick example, take a look at the “Chapters” WooThemes WordPress theme.
In the past I would have used a couple of wrapper divs in HTML, and some background-image CSS to get a vertically expandable (but probably fixed-width without a lot more work) content box. However, with the improvements in CSS3, along with rapidly improving browser support, I wondered if it would be possible to make a similar – and more flexible – effect without images.After a bit of a brain-storming session I came up with the following theory:
- A wrapper with
position:relative - A content block (such as article, or a div)
- use of the
:beforeand:afterselector to create pseudo-elements which could be placed under our content block usingposition: absoluteandz-index transformandbox-shadowto apply the effects
A quick mock-up in a text-editor later and I had a working proof-of-concept.
Given a sample HTML page like this:
<!doctype html> <html> <head> <title>Test Page</title> <link rel="stylesheet" href="./style.css" /> </head> <body> <div class="hfeed"> <article class="entry post"> <header class="entry-header"> <h1 class="entry-title">This is a Test Page</h1> </header> <div class="entry-content"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </div> </article> </div> </body> </html>
Now we apply some CSS (only showing the bit which makes the “magic” happen):
div.hfeed {
position:relative;
}
article.post {
position:relative;
margin: 0 0 2em 0;
background: #fff;
padding: 10px;
border: 1px solid rgba(0, 0, 0, 0.150);
-webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.18);
-moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.18);
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.18);
}
article.post:before {
z-index: -1;
position: absolute;
top: -2px;
left: 0;
content: '';
width: 100%;
height: 100%;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.150);
-webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.19);
-moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.19);
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.19);
-webkit-transform: rotate(1deg);
-moz-transform: rotate(1deg);
-o-transform: rotate(1deg);
-ms-transform: rotate(1deg);
transform: rotate(1deg);
}
article.post:after {
z-index: -2;
position: absolute;
top: 1px;
left: -2px;
content: '';
width: 100%;
height: 100%;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.150);
-webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
-webkit-transform: rotate(359deg);
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-ms-transform: rotate(359deg);
transform: rotate(359deg);
}
This will give you something like this screenshot:
The sample code above has the effect being applied to a single content block. If you want each block to have the paper effect (such as each entry on a blog archive page) then you will need to slightly change your CSS and HTML. I will leave this for you to discover – after all, half the fun of learning is experimenting!
As far as compatibility goes: I’ve tested in Chrome, IE9, and Mobile Safari and all work fine. I don’t envision Firefox or the Android web browser would have a problem with this code.
You can find the complete code for the sample page + CSS here, as a Gist on GitHub


Works fine in Firefox 8.
Thanks for checking that for me :)