Grow your CSS skills. Land your dream job.

Full Browser Width Bars

Published by Chris Coyier

Updated on December 17, 2014 by Parker Bennett.

As the line length of text content gets longer, it can be harder to read. So it's common practice to limit the width of content as the viewport widens. Often, this is accomplished by giving the content a max-width and centering it, either within a wrapping element, or section by section.

But what if we want an element to extend visually to cover the full width of the viewport, say, a background color for a header or individual headings?

One approach is to use an inner wrapper for the content we want width-constrained, but leave the outer element at 100% width. However, this adds extra markup and it's (arguably, GASP) non-semantic!

  <div class="wrap">

<h3 class="full-width">
  <div class="wrap">Heading</div>
<div class="wrap">
  <p>... text ... </p>
header, .full-width {
  width: 100%;
  background: #ccc;
.wrap {
  width: 80%;
  max-width: 24em;
  margin: 0 auto;
  padding: 0.25em 0.625em;

It would be better to wrap the content semantically (e.g., main or section) and have the headings break out visually as needed. Here are a few ways we can:

Using negative margin

A simple approach (from Timothy Mackey) uses negative margins and padding to extend the background in both directions. To avoid triggering horizontal scrolling, we need to set overflow-x:hidden on both the html and body elements.

html, body {
  overflow-x: hidden;
.full-width-bar {
  margin: 0 -9999rem;
  /* add back negative margin value */
  padding: 0.25rem 9999rem;
  background: rgba(0, 0, 0, 0.5);

See the Pen Full Width Bars Using Negative Margins by Chris Coyier (@chriscoyier) on CodePen.

Want to make the full-width bar a different color than the heading background? One way is to use left and right borders. But it turns out super-wide borders have some issues. For borders over 960px, you need to make them exactly 9600px or 10240px (or equivalent ems) to avoid a bug in Chrome. Also, you need to use solid colors, since RGBa values display a tiny gap in Safari. This is because of rounding errors when the containing element is centered.

html, body {
  overflow-x: hidden;

.full-width-borders {
  /* also subtract section padding (1.5rem) */
  margin: 0 -601.5rem;
  /* add back section padding (1.5rem) */
  padding: 0.25rem 1.5rem;
  background: red;
  /* border has to be solid, not RGBa */
  /* 9600px or equiv (600rem = 9600/16) */
  border-left: 600rem solid maroon;
  border-right: 600rem solid maroon;

See the Pen Full Width Bars Using Borders by Parker Bennett (@parkerbennett) on CodePen.

Given the fussiness of using borders, let's look at an alternative:

Using pseudo elements

By adding a :before pseudo-element to the heading, you can make the background behind it distinct from the full-width bar, using absolute positioning and a negative z-index. This also lets us use RGBa for the full-width bar.

.full-width-tinted {
  position: relative; /* for child pseudo-element */
  z-index: 0;
  margin: 0 -600rem;
  /* add back negative margin value */
  padding: 0.25rem 600rem;
  background: #666;
  background: rgba(0, 0, 0, 0.25);

.full-width-tinted:before {
  content: "";
  position: absolute;
  z-index: -1; /* behind parent */
  top: 0;
  bottom: 0;
  /* subtract h2 padding (1.5rem) */
  left: 598.5rem;
  right: 598.5rem;
  background: green;

See the Pen Full Width Bars Using Negative Margins by Chris Coyier (@chriscoyier) on CodePen.

You need to be a little careful with negative z-index, since it tends to work only in fairly simple situations without many nested elements with their own backgrounds.

If you want even more flexibility, you can use two pseudo-elements, :before and :after, to extend the header background both left and right. This way the background could include different color, widths, or heights, extend in only one direction, fade with a gradient, etc.

.full-width {
  position: relative; /* for the child pseudo-elements */
  /* negative offset = section padding */
  margin: 0 -30px;
  /* add back section padding value */
  padding: 0.25rem 30px;
  background: #333;
.full-width:before, .full-width:after {
  content: "";
  position: absolute;
  /* fill vertically */
  top: 0;
  bottom: 0;
  width: 9600px;
  right: 100%;
  background: green;
.full-width:after { 
  width: 320px;
  left: 100%;
  /* you're free to do something totally different here */
  background: green;

See the Pen Full Width Bars Using Pseudo-Elements by Chris Coyier (@chriscoyier) on CodePen.

Using box-shadow

A clever way to not trigger horizontal scrolling is to use box-shadow to generate the background extensions (at least on the right). Andreas created a demo of this:

See the Pen Full Width Browser Bars with box-shadow by Andreas (@receter) on CodePen.

Unfortunately, there are issues with this. Charles Stuart pointed out a bug in Internet Explorer 11 (v11.0.9600.17501) that makes using box-shadow unreliable. It appears IE is using sub-pixel antialiasing on the box-shadow even when blur is set to 0.

Using viewport units

Lisa suggested a way to not trigger horizontal scrolling by using a combination of vw and calc(), which now have pretty solid browser support. It could be useful in the right circumstance (but doesn't yet factor in things like padding or min-width).

See the Pen Full width bars by Chris Coyier (@chriscoyier) on CodePen.


  1. Great and Nice :D

  2. Nice solution, but it is pretty buggy under low resolutions. There comes out an unneccesary horizontal scroolbar.

  3. Thanks for this great Tutorial.
    But why do you use and tags? Is there a reason why do you use both?

  4. This is a spectacular tip! I’ve always wondered if there was a clean, semantic way of doing this without any extra markup. It seems there are huge amount of websites that choose to implement something like this style, but they all seem to employ tricks using wrapper divs or something similar. That’s what I’ve done on my website. Will have to make this change now.

    Thanks for this!

  5. Well, i was looking for something similar, but how would you make something like this: ? i had huge problems to make it without tables.

    • Salim Bensiali

      h2 { border-radius: 10px 0 0 }
      h2:before { top: 50% }// Or whatever percentage you want

  6. Kawohi

    Damn I always wondered how to do this!

    I wish you made a list of all your demos, it would help

  7. I’m probably ignorant, but why couldn’t you just include a span instead of a div?

    Alternatively, wouldn’t it be better to have something non-semantic & working everywhere, than something semantic that doesn’t?

    Lastly, why not just have padding be 25% on the right & left of each element?
    Doesn’t that do the exact same thing?

  8. I think, I have better solution, without disabling horizontal scrollbars.


    (some z-index bug in IE8, but other browsers works great)

    And don’t forget to add min-width in pixels to section tag (from demo), or any other element that have percentage width specified.

    • That’s clever too, but you are setting exact pixel heights on the headers which probably isn’t a great idea. To avoid that, you set relative positioning on the header and make the height of the pseudo dynamic by using both top and bottom of 0. But when you make the header relative, AND you put a background-color on the section (very likely in a real environment) the pseudo elements disappear. Still clever, I like minimizing the use, just a warning.

  9. Dima

    Chris, under iOS, the demo page contains an extensive horizontal scrolling area.

    How would you suggest dealing with the overflow in this scenario?

    • I tested the page in mobile safari and didn’t see that problem. (well I did at first then I fixed it, at first I was hiding overflow on html element but that didn’t work, changed it to body). What version are you using?

    • Dima

      iOS 4.3.3 (8J2). Just reset the iPad as well, the issue still occurs.

      Chris, I am curious, do you get the feeling that iOS Safari is becoming the new “IE”? A much more capable, standards compliant and constantly improving browser but nonetheless a barrier to implementing a feature that otherwise would have no issues on a non-mobile browser.

      Beginning with rethinking the UI elements such as hover (interesting view on possible solutions to this by Trent Walton at ) and rollover to JavaScript that sometimes runs very sluggishly on not at all (due to what I can only assume is due to underpowered devices having difficulty with unoptimized code) to certain elements just performing differently under iOS (eg. music samples on not playing in background but rather on their own pages).

      I am graphic design student prepping to put up my portfolio online and have been scouring the web learning HTML, CSS and JQuery (your website has been invaluable by the way). While I understand the need to support older browsers, at least at the moment I must ensure that portfolio works flawlessly on mobile browsers. Thus iOS has become a ruler by which to judge feature implementation.

      Would be very interesting to read your position on this matter.

  10. Dmitry Khasanov

    Hello, Chris.

    Great site, awesome articles, I’m your fan, blah-blah-blah. It doesn’t matter this time.

    Now a few words about comments form validation: it’s not as good as it should be (we say about, right?).

    When one of the fields “name” or “email” is empty and submit button pressed, a nice tip pops-up and says about an error. It’s good.

    When comment field is empty and submit pressed, page reloads, message “Error: please type a comment.” appears. No buttons, no links, no text around. It’s terrible.

    WordPress can do better. Please, make something, ajax is an option.

    Best regards, Dmitry.

  11. Chris

    Another great yet simple pseudo article. Rep +100 =)

  12. Steffest

    Ouch… Is it just me that thinks the quest for semantic HTML should NOT turn into bloated CSS garbage?

    • Yes, it’s more CSS. It turned 4 lines of CSS into 22. But if used on every page of a big website that has headers all over it, we might save thousands of div’s. Who’s bloated now?

    • I would much rather have bloated CSS because it’s re-used as Chris mentioned, and in a philosophical sense, CSS isn’t supposed to mean anything, so sloppy code doesn’t obscure data and content.

  13. artem.ka

     not necessarily must be a container for element, semantic tags is need for a search engine.You may clearly operate conventional divs and then wrap your markup by semantic tags. Browsers don`t need semantic tags, they are for search engines, so we don`t need to style them. At least in the next couple of years.

    The holds no semantic meaning, it’s only for style.

    “div” derived from “division”, so it’s more semantic that you think to put div in h1.

    About this solution, it`s terrible, not only terrible, it’s ugly. And here’s why: Instead of simple light cross-browser solution, you are in pursuit for semantic, to remove an 1 element of markup, wrote a ton of CSS that don`t working in older browsers. WHAT FOR?

    Semantic is an ideal, semantic is the point to look toward, searching for better solutions is good, but it`s impossible to use what is said here on real projects.

    • artem.ka

      <section> not necessarily must be a container for element *

    • artem.ka

      The <div> holds no semantic meaning, it’s only for style.

    • artem.ka

      fu**** editor >:o
      here’s without mistakes:

      <section> not necessarily must be a container for element, semantic tags is need for a search engine.You may clearly operate conventional divs and then wrap your markup by semantic tags. Browsers don`t need semantic tags, they are for search engines, so we don`t need to style them. At least in the next couple of years.

      The <div> holds no semantic meaning, it’s only for style.

      “div” derived from “division”, so it’s more semantic that you think to put div in h1.

      About this solution, it`s terrible, not only terrible, it’s ugly. And here’s why: Instead of simple light cross-browser solution, you are in pursuit for semantic, to remove an 1 element of markup, wrote a ton of CSS that don`t working in older browsers. WHAT FOR?

      Semantic is an ideal, semantic is the point to look toward, searching for better solutions is good, but it`s impossible to use what is said here on real projects.

    • As of last month, pseudo element support was 92.1% on current browser usage levels, and that’s increasing fast. I’d wager within a year that’ll be so close to 100 it’s a total no-brainer for “real projects.”

      Semantic tags aren’t “just” for search engines. In fact this is how I’d think about semantics in order of importance:

      1) Keeping things trim for understandabability and quicker page load

      2) Accessibly – helping screen readers accurately describe and navigate the content.

      3) As a side benefit, search engines understand the content better as well and can rate and classify it better.

    • Chris, you’re going by W3Schools stats in that post you linked to. The better stats to use are StatCounter. I don’t know if those are the best, but they are much more accurate than W3Schools.

      W3Schools is counting only visitors to their own web pages, which are exclusively tech-oriented people. Just as an example, according to W3Schools, both Chrome and Firefox had more usage last month than all versions of Internet Explorer combined. That is completely false, and very misleading statistics to go by for client projects. And unfortunately W3Schools continue to have the #1 spot in Google for “browser stats” and related terms, causing many people to think they are giving legitimate numbers.

      As of this moment, for some reason StatCounter’s data is down (I assume that will be fixed shortly), but you can view StatCounter’s stats on this WikiPedia article. You’ll see there that last month’s usage for IE (all versions) was about 44%.

      So everyone should do themselves a favour and ignore pretty much anything to do with W3Schools, especially their browser stats. See Paul Irish’s site W3Fools for more info on them.

      And Chris, you would be well advised to add a “nofollow” to your link that leads to W3Schools stats page (or better yet, update the article to include better stats) — they already have enough misleading link juice, they don’t need any more. :)

    • Using StatCounter, we’re looking at 88% compatibility. Still pretty good. And depending on the exact scenario, fallback of nothing might be no big deal.

      StatCounter looks pretty legit.

      Stats are based on aggregate data collected by StatCounter on a sample exceeding 15 billion pageviews per month collected from across the StatCounter network of more than 3 million websites. Stats are updated and made available every 4 hours, however are subject to quality assurance testing and revision for 7 days from publication.

      Also, I’m not as hater on W3Schools as many. I don’t really care about the name. I wish they would be more responsive and make all the changes suggested on W3Fools, but I also think they’ve helped a shitload of people learn about this stuff.

      I’ll make a note to update that pseudo elements article though.

    • You’re right, they have helped a lot of people, myself included. But if they aren’t responsive, then it invalidates everything they’ve done, because then it’s obvious that they care more about their page views and advertising than they do about delivering accurate content. (Which is odd, because if they would just fix things, they would become a more valuable resource, leading to a better bottom line long-term.)

      And FYI – here’s an alternative source for browser stats, that seems to be more relevant to corporate environments. According to their stats, support for pseudo-elements would be a bit lower, at around 81%.

    • artem.ka

      Okay, let’s say we dont care about 8%(!!!) of users.

      But why you doing that?
      body {
      overflow-x: hidden;

      other 92% desktop browser’s users remain without horizontal scroll, and then you talk about accessibility…

      1) Keeping things trim for understandabability and quicker page load

      Take google, did you see his source code?

      This is what i see there:
      1. <table></table>
      2. <div style=””></div>
      3. <div class=”gbh”>, <div class=”lgpd”>, <div class=”lsb”>
      4. onclick=””
      5. align=center

      Did you think they care about html semantics and clear code? i dont think so.

      quicker page load – yes.

      Keeping things understandable – yes, but not on production site, only on local project.

      On production site, we dont need understandable html, css, we need to our pages load and render as fast as they can, so we must minified html,css,js reduce the number of http-requests to the server, enable gzip, reduce images size, even reduce class names to 3 – 5 letters.

      People dont care about your code, they care about how that look and how fast that loads, google know that.

      Like i say: if you can implement something with the same functional simpler, cleaner, and cross-browser, that would be good.

      2) Accessibly – helping screen readers accurately describe and navigate the content.

      4 questions:

      1. Have you ever tested site on screen readers?
      2. Which of them currently most popular?
      3. Are you sure that screen readers are able to read html5 semantic tags? (proof link?)
      4. What percentage of your users browse pages from screen readers?

      3) As a side benefit, search engines understand the content better as well and can rate and classify it better.

      Where did you get that google or other search engine supports html5 semantics? (proof link?)


      You say html5 semantic tags is good for screen readers it’s good for search engines, yes it is, but not now, may be in future.

      All i want to say that we don`t need to style them, if you want html5 semantics on your site just wrap your div.aside,div.header,div.footer,ul.nav, with them.
      For old browser’s it will be ignored, and your site dont break without javascript.

      Sorry for my english

    • The small percentage of users aren’t screwed, they just don’t see “full width browser bars”, which… big deal. And if you want to accomodate them…

      Hiding overflow-x on the body causes some need for consideration but 1) if your website is fluid width it will probably never matter and 2) can be dealt with easily with media queries, which are also polyfillable.

      I don’t understand how Google using shitty markup in some of their apps has any bearing here. Are you saying we should use shittier markup on purpose?

      Here’s the deal, this:


      is more semantic than this:


      Period. A header is a header, not a header with a single “division” inside of it. It’s less code (you seem to care about page speed right?) it’s more understandable, it’s more semantic. I’m not sure I can be convinced otherwise.

    • artem.ka

      Keep your code clean is important.

      If that dont cut functional and perform the same steps that the old solution, but it’s easier or more efficient and should not be more time-consuming.

      Real world.

      Users do not care what is happening in your code, it is only important how fast it is loaded and how good it looks in all browsers.


      For example you have done site with old proven solutions and it works and looks good anywhere(even in ie6), but then you thought of something here is not semantically correct and spent another 8 hours to do it all on javascript and pseudo elements. why?


      User came to your site with ie6, he looks that in his browser your site looks like shit, and he do not buy your product, not order a service, not register, or just go away, because in his browser your site looks bad.

      “Money ie6 users are no different from money other users.”

      When you grow up from a semantic frame, maybe you’ll understand, for whom you are doing your site and what they need from your site.

      “You make the experience as good as you can make it.”

      About speed.

      1. Very slow library, quickly works only on small pages.
      2. The user who has no javascript, or whose javascript is not loaded yet, his page will fucking collapse. And it’s even worse than just not show a fully featured, beautiful site.

      Do you think that the faster .class or 2 :before?
      your article ?

      “Universal, child, adjacent selectors, pseudo-selectors, should be applied only in cases when they are really needed as they are much more resource intensive than the selectors id, class.”

      fast and pretty vs slow and ugly, what do you choose?

  14. Chris, I like this technique. This is a problem that I’m rolling over all the time in my head trying to thing of better ways to solve it. The only thing I’m missing with this technique is how to account for horizontal scrolling in narrower browser windows. For example, if you have your content width set at 960px, and the user has their browser window sized to 900px, how will the access the content that overflows into the remaining 60px?

  15. matias

    joya como siempre los tutos! pero poneme un boton para tweet ;) dale que si!

  16. These days I am working on a design that has the same effect, and was already thinking how to implement it, and here I came across this post without even start looking for the solution.
    Thank you for the tip

  17. This is brilliant. Exactly what I was looking for to keep code simple on a project I’m working on.

    Now the hurdle I’m trying to solve, and I don’t see an obvious solution – Getting it to work with a clearfix…

  18. Simon

    I think this tip is really good, but i have one problem with it on my mac in safari. A horizontal scrollbar doesnt appear but if I scroll diagonal(or just not perfectly straight) on my touchpad the site scrolls horizontally. Does anyone experience the same issue, if so, any solutions?

    • Just had this issue, looks like it can be fixed by adding ‘overflow-x: hidden’ to html as well as body =)

    • Gunnar
      Permalink to comment#

      Dan – That didn’t seem to work for me. Do you have any other suggestions?

  19. Matt Royce

    Now this is pretty awesome – and I’m pretty sure I’ve noticed a tiny little error! It won’t effect the demo page, or anything, I just thought you’d like to know so you can correct it on this post. ;)

    In the first chunk of HTML, you’ve wrapped a [second-level] header in a div tag – fair play. Non-semantic, rabble rabble rabble! :P But then, in the first chunk of CSS, you style the “h1″ element – and not “h2″. Just thought I’d point that out. :P

  20. why don’t we use “width:auto” ?

  21. hm … I don’t get the problem somehow. What is wrong about this?

    h1 {
    background: red;
    padding:0 25%;

    • Or this, if you use a wrapper container.

      h1:before {
      background: red;
      height:1.5em; /* height of the element */

    • Or if you want a super huge Element:

      h3:before {
      background: red;

      All of them are much easier in my opinion.

  22. Awesome tutorial! This could be of use for this project I’m currently working on.. :) cheers!

  23. This is really interesting solution. Unfortunately I also had some issues with scroll bars.

  24. Dxniel

    Wasn’t easier just to give the style “width:100%” to the div and asign a fixed height?

  25. Michał Czernow

    Another idea:

    h1 {
    padding-left: 50%;
    text-indent: -480px; (or whatever to align with desired fixed width)
    background: #blabla;

    Now, it’s only idea; it won’t work in every environment (imagine, how second line would behave; also, there is nothing that would narrow text to a fixed width).

    Just exploring some possibilities :).

  26. Pam

    What does this mean?

    content: “”;

    And why do you have to set positions (relative, absolute)?

    • That’s what makes a pseudo element a pseudo element. If you use :before or :after, you HAVE to use some kind of content, even if it’s just an empty string. In this case, we just need a generic empty element in which to position and color, hence the empty string.

  27. Marcus Tucker
    Permalink to comment#

    Hi Chris, looks good but sounds like there’s potential conflict with elements (e.g. DIVs containing login, nav, ads, etc) floating left, center, and right… is that correct or is there no issue? Would be nice to see a more complex version of your demo showing how these can all co-exist fine… or not, as the case may be…?

  28. Kyarn
    Permalink to comment#

    I found I had to add a height:100%; to the html, body tags, otherwise I’d get a vertical scroll at the bottom of the full width element.

  29. I really dont like the idea of this tutorial, and there is a much effective way of achieving a full length field with a middle inside of it.

    Simply put.

    header {
    background-color: #whatever
    margin: 0 auto;

    Then create a header content for the inside of the header.

    headercontent {
    position: relative;

  30. The massive width and negative margin methods mentioned in the article resulted in the ability to scroll horizontally, even with “overflow-x: hidden” applied to the html and body elements. There was no horizontal scrollbar, but if you selected text and moved your cursor off the right side of the page, the page would scroll (this is true even of the demos given in the article). The only method which prevented the horizontal scroll was the box-shadow method.

    • Turns out this problem is only in Chrome. It may be a bug recently introduced.

    • I’ve found the same issue – I also tested on Browserstack all the way back to Chrome version 14 and it did the same thing so not sure if this was an issue that just got missed originally? I’d be surprised if that was the case.

      It’s a shame none of these are perfect – the box shadow does seem the best but I’m attempting to create a class I can just drop on to an element and have it extend. This is fairly straight forward until you run in to this bug.

  31. So, I have to say: THANK YOU! I know this post is old, but you have saved me countless times and this post really, really just helped me SO much. Much <3 to you!_

  32. mitya
    Permalink to comment#

    I’ve used it in the header. and was, thank you very much. but I have a question like this. When I give shade looks like two pieces of header .. before and after receiving different shades.

  33. Gunnar
    Permalink to comment#

    Peter Sieg is right. I’ve found this same issue on Chrome and, unfortunately, it seems to create an issue in responsive sites on mobile devices. On mobile devices it seems that the zoom is automatically set to include the “off page” area (even when using <meta name="viewport" content="width=device-width, initial-scale=1">). Leaving a mobile width site with a bunch of empty space to the right.

    Does anyone have a suggestion to resolve that?

  34. naty
    Permalink to comment#

    What if I wanted to have an image background right after an h2 text and wanted it to strech all over the div horizontally?
    I’m having trouble with it. I used a span:after but the repeat-x won’t work in this case :( does anyone know how to fix it?

    • M. Adil
      Permalink to comment#

      background-repeat: repeat;
      it should work as I also had adopted the same method at the very first day of playing with css.
      Sorry in case I posted something wrong as m new to css :)

  35. M. Adil
    Permalink to comment#

    Being a newbie to css, really enjoying it and this post is one of those which I visited at the very start of this journey.
    What if I want to create many similar divs of the full sizes at a page? Should I follow the same way?

    What’s about something like this?
    #header {
    position: fixed;
    display: inline-block;
    top: 0px;
    left: 0px;
    z-index: 5;
    overflow-x: visible;
    overflow-y: visible;

  36. maxim postoronca

    to fix the BORDER TECNIQUE that shows 1px white bar on the left that is seen in firefox, or when you zoom in chrome
    use left: -9990px instead of left: -9999px

  37. Lisa

    My idea with some vw and calc magic

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".