Content Security Policy

As a full-stack dev, I try my best to keep up on front and back end technologies,
methods, and techniques. One of the many ways I do this is by utilizing my time
through reading, watching, and listening. I have, at any time, 3-5 books I’m reading,
a slew of videos on my watch list, and a myriad of podcasts that I listen to which
help me stay aware of the numerous things that are relevant to me as a web dev.

One of the podcasts I listen to is Shop Talk Show. Aside from the various tips,
tricks, and information that I’ve absorbed from the podcast, I’ve also learned
how to talk about what I do through Chris and Dave. They constantly get
interesting questions and go down rabbit holes. In the” target=’_blank’>Last episode (#273), they get
into Content Security Policies. It’s something that I don’t hear people talk about
often and though it’s something I’ve always used and been aware of, I don’t think
I’ve ever written or posted about it. So I wanted to offer up a blog post.

The goal of a Content Security Policy (CSP) is to prevent Cross-Site Scripting
There are a lot of ways it does this, which we’ll get into. How it works
is by directing the browser to enforce the policies set forth through HTTP directives.
The CSP sets a whitelist of content sources which the browser understands will be
the endpoint of requests made from the page. The browser uses this whitelist to
block requests made to content sources outside of the whitelist. Keep in mind that
CSP is not meant to be the only defense against XSS, just another tool in the
box. You should utilize other tools (like input sanitization) in addition to a
CSP to prevent XSS

How It works

When a browser makes a request to your website, the CSP should be provided with
the HTML as an http-header. It’s part of the header because it’s hard to forge.
The policy itself is a set of directives which instructs the browser to only
render or execute content from the whitelisted sources.

What A CSP Contains

CSPs contain source directives, or, a list of sources for specific content types.
Here’s the list of those:

  • default-src: the default source of all content types. This is used when a source
    type is not defined. When a more specific source type is defined, it overrides the
    default source.
  • base-uri: sets the URLs that can appear in the <base> element.
  • child-src: sets the URLs for workers and embedded frame contents. For example:
    child-src would allow embedding videos from YouTube but
    not from other origins. This should be used instead of the deprecated
    frame-src directive.
  • connect-src: sets the endpoints to which the page can connect via XHR, WebSockets,
    and EventSource.
  • font-src: sets the origins that can serve fonts.
  • form-action: sets the endpoints for <form> submissions.
  • frame-ancestors: sets the sources that can embed the current page. This applies
    to <iframe>, <frame>, <embed>, and <applet> tags. It can’t be used in
    <meta> tags and applies only to non-HTML resources.
  • img-src: sets the origins from which images can be loaded.
  • media-src: sets the origins from which video and audio can be loaded.
  • object-src: sets control over Flash and other plug-ins.
  • plugin-types: sets the types of plug-ins pages may invoke.
  • report-uri: specifies a URL where a browser will send reports when a security
    policy is violated. This can’t be used in <meta> tags.
  • style-src: sets the origins from which stylesheets can be loaded.
  • script-src: sets the origins from which scripts can be loaded.
  • upgrade-insecure-requests: instructs browsers to rewrite URL schemes, changing
    HTTP to HTTPS. This is for websites with large amounts of old URLS that need to
    be rewritten.

Why It’s Needed

By default, directives are open, meaning that all sources and endpoints are
allowed. It’s important to restrict the sources and endpoints because attackers
can use unknown sources to perform XSS.

How To Implement

To specify sources, there are a few valid values:

  • *: All origins/endpoints are valid
  • data:: Allows data: URIs to be used as a content source. This is insecure.
    An attacker can inject arbitrary data: URIs. This should be used sparingly and definitely not
    for scripts.
  • All domains of using the http:// OR https://
    schemas are valid.
  • All domains of using ONLY the https://
    schema are valid.
  • http://* All subdomains of using the http://
    OR https:// schema are valid.
  • https://* All subdomains of using ONLY the https://
    schema are valid.
  • All attempts to access port 433 on are valid.

Keywords are also used. When using keywords, single quotes are required.

  • 'none': An empty set. No URLs are allowed.
  • 'self': The origin from which the originating document is served, including the
    same URL scheme and port number.
  • 'unsafe-inline': Allows the use of inline resources (i.e. <script> elements or javascript: URLs)
  • 'unsafe-eval': Allows the use of eval() and similar methods for creating
    code from strings.

Notes on the Above:
http:// can redirect to https://, but https:// will not redirect to http://.
If a port number isn’t specified, the default port will be used. If no schema is
specified, the same on used to access the originating document is assumed. Allowing
a domain does not include it’s subdomains, but does allow extensions (i.e. will
allow to be used but not

Setting the CSP HTTP Header

The CSP’s best delivery method is through HTTP headers. Here are some examples how:

Apache config

Header set Content-Security-Policy "default-src 'self';"

# IIS Web.config
      <add name="Content-Security-Policy" value="default-src 'self;'" />
# nginx conf file
add_header Content-Security-Policy "default-src 'self';"

A lot of languages and frameworks support adding the headers programmatically, such
as PHP or Node.js.

header("Content-Security-Policy", "default-src 'self'");
# node-js
request.setHeader("Content-Security-Policy", "default-src 'self'");

CSP <meta> tag

There is also an HTML5 <meta> tag.

<meta name='Content-Security-Policy' content="default-src 'self'; script-src 'self'; ...; ...;" />

This tag goes in the <head> of the page.


When setting directives, you should always include multiple URLs in one directive
(if multiple URLs are necessary). For example, if you want to allow images from AND, setting it across two directives would render
whichever came first useless because the latter would override the former.


The second directive overrides the first directive.

Instead, multiple URLs should be declared in one directive, i.e.


Specific directories are not allowed, i.e. If you want
to use a specific directory, just use the web root (i.e.

Other Resources

I use a lot of resources to write my articles and make sure everything is up to snuff.
Here are some great articles/documentation:
Level 2 Spec on W3C
SitePoint article
Mozilla Dev Article
HTML5Rocks Article

In Conclusion

We reviewed Content Security Policies, what they are, why they’re needed, what
they do, how to implement them, and the syntax.

Disappearing Nav

Disappearing navbars are found all over the web. This feature may seem like an
advanced technique, but it’s actually really easy to implement.

With just a little bit of JavaScript, you can have a disappearing navbar.

The logic

When the user scrolls down, the navbar fades out. When the user scrolls up, the navbar fades in. Easy, right? We need to take into account the page position
when the user starts to scroll. This helps determine if the direction of the
scroll is up or down. So, when the user starts to scroll, we need to
save the pageYOffset, or, the distance from the top the page is scrolled. Then,
we need to figure out if the user has scrolled up or down. To figure that out,
we check if the current position is greater than the last saved position. If
the current position is greater, that means that the user has scrolled down. If
the position is less, the user has scrolled up. Let’s code this out:

var lastPosition = 0;
window.onscroll = function() {
  var position = window.pageYOffset;

  if (position > lastPosition) {
    //the user has scrolled down
  } else {
    //the user has scrolled up

That’s the bulk of our code. Now, we just need to hide and show the header. There
are a few different ways to do this. I’m using CSS classes, hidden and active,
with different opacities. Here is that code:

.hidden {
  transition: opacity .4s ease;
  opacity: 0;
  pointer-events: none;
.active {
  transition: opacity .4s ease;
  opacity: 1;

This adds a little bit of a transition and makes whatever is in the header
non-interactive while it’s hidden. Putting it all together is simple: when the
user scrolls down, the header’s class should be hidden, and when the user scrolls
up, the header’s class should be active. Here’s the code:

var lastPosition = 0;
window.onscroll = function() {
  var position = window.pageYOffset;

  if (position > lastPosition) {
    //the user has scrolled down
    document.getElementById("header").className = "hidden";
  } else {
    //the user has scrolled up
    document.getElementById("header").className = "active";

Of course, this snippet only works with navbars that are fixed to some side of
the screen. I think this effect looks great on mobile and really frees up a lot
of screen real estate. Here’s your demo:

See the Pen Disappearing Navbar by Nate Northway (@the_Northway) on CodePen.

Add jQuery

You can get a little more into this with jQuery. The first thing I did was
replace the <header>‘s hidden and active class names with the jQuery fadeIn()
and fadeOut() effects. This handily also takes care of disabling interaction
in the header. The jQuery code is not that different. We should also adjust the
threshold so that a small amount of scrolling up does not trigger the menu –
this is important when thinking of more sensitive input devices like a touch screen
or a track pad. That’s just a little bit of logic. If the difference between the
last position and current position is greater than 20, we know that the user has
scrolled up a lot and quickly, so we should show the navigation.
Here is that demo, with the relevant
jQuery below:

$(document).ready(function() {
  var lastPosition = 0;
  $(window).on('scroll', function() {
    var position = $(window).scrollTop();

    if (position > lastPosition) {
    } else if (lastPosition - position > 20) {

    lastPosition = position;

Really Get Into It

The next thing you can do to bring this effect to being fully fleshed out is
changing the opacity based on the amount that the user has scrolled. To do this,
we have to take into account the <header>‘s opacity before scrolling,
decrement it, and set the new opacity to that decremented amount. If the new
opacity is 0 (or less), we should also disable pointer-events. Here is that

  if (position > lastPosition) {
    opacity = getOpacity($("#header").css("opacity"));
    $("#header").css({"opacity": opacity});
    if (opacity <= 0) {
        "opacity": 0,
        "pointer-events": "none"

function getOpacity(x) {
  var rate = .25;
  return x - rate;

This decrements the opacity by .25 every time the user scrolls. Remember to
set pointer-events to auto on scroll up, otherwise, your users will not be able
to interact with your navbar after scrolling down or refreshing. Here is that demo:

See the Pen Disappearing Navbar (with jQuery) by Nate Northway (@the_Northway) on CodePen.

I had fun building this set of demos. Hopefully it can come in handy on your site!


I posted this on Reddit
and got a good reply from /u/alejalapeno:

All iterations of this need a debounce/threshold put on them because a 1px scroll-up on a trackpad should not re-summon the menu. It needs a threshold like 10-20 pixels scrolled-up at least.

I added that in as a condition to the if statement in the JS. It checks if the
difference between lastPosition and position is greater than 20px before
showing the navbar. I’ve already updated all the sample code above and on in the
CodePen demos, but here’s a closer look at it:

if (position > lastPosition) {
  document.getElementById("header").className = "hidden";
} else if (lastPosition - position > 20) {
  document.getElementById("header").className = "active";

Browser Defaults

Browser defaults are generally rather sensible and malleable, but there are a
few things I strongly urge you not to mess with.

Chrome, Firefox, Safari, Opera –
all of these browsers have their own way of rendering HTML elements. From margins
to padding to font-sizes, they determine how a page will render without CSS
telling it what to do. Though each might do it differently, all browsers employ
some styling for native UI components.


Though each vendor slightly differs in default stylings, there are a few
ubiquitous native UI components that stick around – not just in browsers, but in desktop
and application environments, too. A good example of what I’m talking about is
the focus ring on input fields, especially those that are text based.

Examples of Focus Rings in Chrome, Firefox, and Safari

See? Ubiquitous. There is a reason for that.

For Reasons

Not only do focus rings appear in web browsers, but in a lot of applications, too.
Keyboard users depend on them to determine where they are on the page. Mobile
users also find the focus rings helpful when navigating forms. Knowing which of
the multiple input boxes is the selected one makes sure they know what to enter
on their keyboard. And before you say ‘but they clicked it, they should know’,
most mobile browsers have a ‘next’ button that works just like ‘tab’ on a
keyboard. People with vision impairment also utilize the focus ring to help them
navigate the page.

It’s important to keep some of these native UI components around in
your website/app/tool/thing because users may be lost without them. Restyling is
OK, but removing is a big step to take to inconvenience your users.

…if an alternative focusing style isn’t made available, the page will be significantly less usable for people who primarily navigate pages using a keyboard, or those with reduced vision who use focus outlines to help them navigate the page.
HTML Living Standard, section 6.4.6

The HTML Living Standard
really has a lot to say about the focus property. And that’s just one property. There
are dozens (if not more) of more ubiquitous default styles out there. Sara Cope
compiled a great list
of CSS properties that are a part of native UI components (there are a lot more than 12).


Restyling defaults is a different story. I understand that the mediocre grays that
Chrome and Firefox offer may not match your color palette, and that’s fine, go
ahead and restyle. In fact, I encourage it. But please, don’t remove native UI

I like to write after reading some stuff:
TJ VanToll wrote a great article on the focus outline.
Baymard Institute wrote an interesting article on restyling Native UI components.
The Government dabbles in writing about UI Design Basics.


I’m seeing some debate on prefixing box-shadow (and other properties). This is
my solution to figuring out browser prefixes.
recent article
by appendTo discusses the CSS Box-Shadow property. It
does a decent job explaining the values and what they do, but they superfluously
suggest prepending browser prefixes to the box-shadow property.
In my last post, I discuss
browser-prefixing as a general topic, and suggest a few tools to help determine
if you need prefixes, namely, Autoprefixer. It’s a great tool with lots of
different possible applications, including plug-ins for Atom
(the text editor I use) and Sublime Text.

CSS Bloat

The problem I have with unnecessary prefixing is bloat. CSS bloat can be a huge
problem for mobile users, and for anyone on slower connections. Browser
prefixing can increase a property’s weight by a lot. In this case, the unprefixed
box-shadow property is 51 bytes unminified, 43 minified. The prefixed version
(what appendTo suggests) is 134 bytes unminified and 118 bytes minified. The
difference is not negligible. 83 unminified bytes and 75 minified bytes is a

I understand the need to cater to your users, I really do, because I have to do
it, too. But unnecessarily using browser prefixes is a disservice, and that’s why
I very strongly suggest using the tools I mentioned in my last post (and above).
Not only will they save you time but they will also save your users bytes.

Browser Prefixes

Responsive design makes your design work across screen sizes. But what about working across browsers? Responsive design is only part of the solution to making your site accessible to all platforms. Another part (among many) is using browser prefixes and testing your solutions.

What Is A Browser Prefix?

A browser prefix is a string of text that targets specific browsers at the beginning of a CSS property. They are surrounded by hyphens (-) and help vendors use no-yet-standard or working-draft versions of CSS properties. Some browsers implement different versions of properties and their prefixes help developers implement similar behavior across platforms. Browser prefixes look like this:

.item {
  -webkit-transition: all .5s ease;
  -moz-transition: all .5s ease;
  -o-transition: all .5s ease;
  transition: all .5s ease;

Why Are Prefixes Needed? What About Standards?

Standards sometimes take a while to implement, and, are often tested over long periods of time. So, until a standard is declared, prefixes help the testing/development process and allow developers to use new properties.

How Do I Know What Properties Need Prefixing?

After a while, you start to remember, but there are a lot of ways to check if a property needs prefixing. ShouldIPrefix is a go to, as well as CanIUse. If a property discussed on CSS-Tricks needs prefixing, it’s mentioned in the article. Another tool to help you prefix is Autoprefixer


Yeah, don’t forget to test. After you’ve designed your site, loaded in your browser prefixes, compressed your images, css, js, whatever, pull your smartphone out and navigate to wherever that site lives. I’d be surprised if it looks as good as it did on desktop right from the get go. Chances are, you’ll need to do some adjusting. During the design process, I’m constantly resizing my browser window, moving to different platforms and browsing contexts, and testing my local sites with BrowserStack. This helps me make sure that not only is my site going to work on different screen sizes, but also in different browsing contexts.

Borders, Pseudo Elements, and Folds

I’ve recently fielded a lot of questions about Ribbons and Folds done with pure CSS. It’s a lot more than just a few lines of CSS, though.
A lot more. Understanding how borders and pseudo-elements work is not only a good nugget of knowledge to have, but also necessary to understanding CSS folds. To kick off this article, I’m going to walk you through how borders work in CSS. Then we’ll talk about pseudo elements. Finally, I’ll talk about how to use borders and pseudo elements to create stunning effects like folds!


To understand folds, you should first understand how borders work in CSS. Basically,
where each border meets, there is a diagonal line. I’ve built a pen to exemplify that.

See the Pen CSS Borders by Nate Northway (@the_Northway) on CodePen.

As you can see in the demo, each border is just a triangle. This is how CSS triangles are made. An element with
3 transparent (or white) borders, and one colored border. Now, we can take this a step further.

Pseudo Elements

Pseudo Elements are very cool. They can do all sorts of cool, useful, entertaining, and handy stuff.
One really useful example is tooltips. A pseudo-class is basically a phantom state or specific characteristic of an HTML element that can be targeted with CSS. Common pseudo classes include :link, :visited, :hover, and :nth-child. But there are a lot more.

A few things to note: pseudo-classes are always preceded by a colon (:). After the colon is the pseudo-class’
name, then, perhaps, a value in parentheses, like in :nth-child(1).

Pseudo-elements are like bonus elements for every HTML element on the page. Though they can be manipulated with CSS, they aren’t a part of the document tree, nor the DOM. So, they are only accessible with CSS.

Single Colon vs. Double Colon

I’ve seen a little debate over single vs. double colon. I use both, just to be safe, but some people who are more
careful about their byte usage might bite my head off for suggesting that. But, a more honest answer might be: it doesn’t matter.

The double colon is a part of CSS3. It differentiates pseudo-elements like ::before and ::after from pseudo-classes like :hover and :active. All browsers support the double colon syntax except IE8 and below. But
it is good to know that some, like ::backdrop, only accept the double colon syntax.

Personally, I use both, like this:

button::active {
  -webkit-outline: none;
  -moz-outline: none;
  outline: none;

I think this keeps me honest.

CSS Generated Content

Content can be generated through CSS by using the content: ""; property with a pseudo-element. The content
might be plain text or it might be a glyph, but usually, it it just a container, used to create a nice looking ‘thing’ (like a ribbon or page fold).

Keep a few things in mind when using CSS generated content, though. CSS generated content will not be accessible to screen readers, and, it will not be selectable. CSS Generated content should only be used for non-vital stuff, like a ribbon or page fold.

What we’ll be using CSS pseudo-elements and classes for

Since we can manipulate the boxes created by pseudo-elements, we can use them to create ribbons, tooltips, and page folds. Basically, it’s another div we get to work with without adding to the HTML markup. We’re going to be working with ::before and ::after for this snippet.

Using :before

I really like this snippet. Having documentation, a blog, or a page about coding means that you’ll have
a lot of code samples on your pages. It’d be really nice to be able to label the languages being used, wouldn’t it? With :before, you can! Here’s the HTML markup.

<code rel='html'>
  <h1>Hello, World!</h1>

And the CSS:

code {
  display: block;
  background: #efefef;
  color: #292929;
  padding: 10px;
  font-family: monospace;
code:before {
  content: attr(rel);
  display: block;
  width: 100%;
  height: 20px;
  font-family: 'Sans-serif';
  background: #292929;
  color: #efefef;

Put it all together in a demo:

See the Pen Styling Code Blocks by Nate Northway (@the_Northway) on CodePen.

Cool! So now, you can see pseudo-elements taking up space in the real world. Groovy!

Creating A Page Fold

Creating a page fold, ribbon, and a myriad of other effects comes naturally, now. What we have to do is combine
our knowledge of borders and psuedo-elements to create the fold. So, imagine you have an element that needs a page fold. You know the its width, its height, and background color of its parent element. Groovy! You can create a fold.

What we have to think of is the anatomy of a fold. Two triangles of different colors, pushed into a corner of an element. The triangle furthest from the center of the parent element has the color of it’s parent element’s parent element – probably white, but maybe not. The triangle closest to the center of the parent element has a darker (or lighter) shade of its parent element’s background color.

We’ll use borders to create the triangles. Remember earlier, when we discussed how borders meet at angles and how two colored borders form a triangle? Well we’re going to use that property to create our ‘fold’. We’ll start by defining our parent element, then, the borders and position of our pseudo-element.

div {
    background: green;
    width: 100px;
    height: 100px;
    margin: 0 auto;
    position: relative;
    top: 20px;

div::after {
    width: 0px;
    height: 0px;
    position: absolute;
    margin-top: 80px; //parent container height - pseudo-element border width
    margin-left: 80px; //parent container width - pseudo-element border width
    content: "";
    border: 10px solid white;
    border-top-color: #004d00;
    border-left-color: #004d00;

Depending on where you want your fold (top left, top right, bottom right, bottom left), you may need to change up the border declarations and positioning a bit. Here’s the code for that:

//top right fold
div::after {
    width: 0px;
    height: 0px;
    position: absolute;
    margin-top: 0;
    margin-left: 80px; //parent container width - pseudo-element border width
    content: "";
    border: 10px solid white;
    border-left-color: #004d00;
    border-bottom-color: #004d00;

//top left fold
div::after {
    width: 0px;
    height: 0px;
    position: absolute;
    margin-top: 0;
    margin-left: 0;
    content: "";
    border: 10px solid white;
    border-right-color: #004d00;
    border-bottom-color: #004d00;

//bottom left fold
div::after {
    width: 0px;
    height: 0px;
    position: absolute;
    margin-top: 80px; //parent container width - pseudo-element border width
    margin-left: 0;
    content: "";
    border: 10px solid white;
    border-top-color: #004d00;
    border-right-color: #004d00;

And here is the result of that.

See the Pen zKRbJj by Nate Northway (@the_Northway) on CodePen.

I got inspiration to write this post from this Reddit thread.
I used a lot of resources to supplement my lack of word-juggling capabilities, mostly
this CSS-Tricks article and a wonderful article
on Smashing Mag. I also
look at this other CSS-Tricks article a lot, just because it’s good inspiration juice.

Collapsing Content

The cornerstone of responsive design is collapsing (and expanding) content to fit on differently sized screens. But what’s the best way to do it? There are many ways to accomplish a responsive design. If you use front-end frameworks like Bootstrap or Materialize.css, responsive design is usually built right in. But, if you don’t use frameworks, it’s easy to forget about what looks good across platforms, and it gets hard to test for it.

It’s important to design responsively.

A lot of internet traffic (like, 56%) comes from mobile platforms. So, engaging with your audience means implementing a responsive design. Not only does responsive design ensure that your mobile user base is taken care of, but it also makes your users with large screens feel at home. And, as screens are becoming bigger, higher in pixel density, and easier to attain, it’s becoming just as important to serve those users.


There are a lot of ways to implement a responsive design. I’ve already mentioned one: using a front-end framework. Bootstrap, Materialize.css, and Foundation all do a wonderful job implementing responsive design out-of-the-box. But, if you’re like me, you like to eliminate learning whatever framework is popular and hand-coding your sites, or, maybe, using your own, custom built set of modules, or even your own framework.

Media Queries

Media Queries are the groundwork of a responsive design. In CSS, they can be used to change the styles of elements depending on screen size, orientation, and media type. Here are a few standard media queries that I use.

@media screen and (max-width: 575px) {
  //desktop, browser sized to < 575px

@media print {
  //printed version of a webpage

@media screen and (min-width: 1400px) {
  //large desktop

@media screen
  and (max-width: 1400px)
  and (min-width: 575px) {
    //medium desktop, browser sized 575px to 1400px

Inside the media query blocks, your declarations change the behavior of the selected elements. If I have an image that is half width on a large desktop that I want full width on a smaller screen, I may have a media query that looks something like this:

img {
  width: 50%;
  float: left;
@media screen and (max-width: 575px) {
  img {
    width: 100%;
    float: none;

That’s all fine and dandy, but it’s definitely not all that responsive web design is. There are a lot of other tools in this bag.

Percentages over pixels

I’m a strong proponent of using percentage values over absolute values, except in very rare cases, like declaring border width. And using percentages isn’t difficult either. Relative sizes can be calculated easily:
target ÷ context = result
Proportional sizing encourages responsive design. Let’s dive in a little bit here. Say you’ve got a layout, a .psd from your designer, that calls for a main-container at 960px wide, with two containers inside of it, one large-container at 556px wide and one small-container at 331px wide. If we were content with pixel values, and that everyone had the same size screen, we might do this:

.main-container {
  width: 960px;
  margin: 0 auto; //centers the page
.large-container {
  padding: 0 18.25px; //fill out the container widths
  width: 556px;
.small-container {
  padding: 0 18.25px; //fill out the container widths
  width: 331px;

This will do the job on screens larger than 960px, but, definitely not on screens smaller than that. If we want to make our grid more responsive, we could throw in some calculations. Don’t be scared! Remember, target ÷ context = result. So, 556px ÷ 960px = 0.5791666666666667. Bump up that number by a factor of 100 and you get 57.91666666666667%. That’s the large-container width. The small-container width is 331px ÷ 960px = .344791666666667, or 34.4791666666667%. Our content is almost to 100% width (960px). We just need to figure out the padding of each element. To do that, we take the remaining width of 73px, divided by 2 to distribute between the two elements, and divided by two again to distribute to either side. That’s a padding of 18.25px, or 1.901041666666667%, or a total combined padding of 7.604166666666667%, which, when added to our previously calculated element total (92.39583333333337%) equals 100%. Let’s plug these numbers in:

.main-container {
  width: 960px;
.large-container {
  padding: 0 1.901041666666667%;
  width: 57.91666666666667%;
.small-container {
  padding: 0 1.901041666666667%;
  width: 34.4791666666667%;

Here’s the demo:

See the Pen Percentage over Pixels by Nate Northway (@the_Northway) on CodePen.

So, using percentages over pixels can help, for sure. But that’s just the first step. The next step is knowing when to break that design and go for something else. Using margin: 0 auto on larger screens helps your site stay centered when it’s reached it’s max-width, but that doesn’t help on small screens. What? I haven’t talked about max-width yet?


The max-width CSS Property is so great, really, it’s one of the best properties out there. Say your designer gets you a .psd designed at 960px. That’s great, that’s fine, you can code that out. But what if people have screens bigger than 960px? Do you change the design to be super wide? max-width becomes your friend, here.

@media (min-width: 960px) {
  #page {
    max-width: 960px; //your page is never larger than 960px
    margin: 0 auto; //and it's always centered

Boom. If you want to have the background image/color/other elements go side-to-side of the browser window, the parent element (like <body>) can always be set to a larger width. Personally, I set my HTML up to account for this, as follows:

    <div class='container'>...</div>

    <div class='container'>...</div>
footer {
  max-width: 100%;
main {
  max-width: 960px;
  margin: 0 auto;

This way, the navigation, site title, footer links, and all content is always center aligned and, more importantly, on the same grid that everything else exists on. The overflow of the background colors and borders moves to the edge of the screen, making your site look full, rather than clipped and pasted on to the page. max-width is great, isn’t it?

Ok, so onto collapsing now, yeah?

Using media queries, percentages, and a nugget of knowledge, we can collapse.

Utilizing the above examples, let’s work out some breakpoints. Breakpoints are a point at which the layout of the page changes to allow for better usability and readability. Usually, I make my breakpoints at about 2/3 and 1/2 of the original design. If the original design is 1000px, I’ll have a break point at 660px and another at 500px. The 660px breakpoint will collapse the columns to full-width, and the 500px breakpoint will hide the menu, bring up the navigation icon button, and further collapse any content. Here’s the code, going off of our last example.

@media screen and (max-width: 639.9999936px) {// 960px * 2/3
  .small-container {
    width: 100%;

This spreads out the containers to full-width. Now, at the smaller breakpoint, I’ll add in more media queries to further widen content, if needed. For example, articles with floated images. This is what an article with image might look like:

    <img src='example.jpg' />
    XOXO glossier fingerstache quinoa. Cardigan migas affogato knausgaard keffiyeh, artisan lomo biodiesel meggings small batch gluten-free salvia tofu pop-up. Lomo cold-pressed aesthetic.
p {
  width: 100%;
p>img {
  float: left;
  width: 33.33333333%;

So, the image is floated left and has a width of 33% of the parent element, the <p> tag. This probably looks fine on desktop, and possibly even on tablets, but on mobile, the image will be very small. So, in our media query, we can 1. ‘unfloat’ it, and 2. widen it.

@media (max-width: 480xp) {//960 * .5
  p>img {
    width: 100%;

Here’s a demo of that (probably best to view it in CodePen):

See the Pen Responsive Resizing by Nate Northway (@the_Northway) on CodePen.

If that math is too crazy for you, there is another way to do it, which may be more intuitive, and uses more abstract definitions: Flexbox.

Flexbox Is My Hero

I love flexbox. I use it for everything. From <body> layout to create fixed headers and footers, to using it to display my <nav> correctly, to using it in articles and for tables, flexbox is awesome. Using it to help with responsive design takes a little bit of knowledge though. I’ll break it down best I can for you here, but I’ll also link to other articles written by people with much greater skill than I.

The Idea

The Flexbox Layout (as it’s officially known) aims at providing a more efficient way to lay out, align, and distribute space among items in a container, even when their size is unknown and/or dynamic. The primary idea behind it is to give the parent container the ability to change it’s children’s width, height, and/or order to best fill the available space. A flex container shrinks items to prevent overflow or grows/expands them to fill space.

The Basics

The parent, or flex-container, contains all of the flex-items, or children. It has 5 properties.


The display property defines the flex container and enables a flex context for it’s children.

.container {
  display: flex;

The flex-direction property defines an axis and the direction the flex-items are placed in the container. The values can be:
row: default value, left-to-right in ltr, right-to-left in rtl
column: top-to-bottom
row-reverse: right-to-left in ltr, left-to-right in rtl
column-reverse: bottom-to-top

.container {
  flex-direction: row;
  flex-direction: column;
  flex-direction: row-reverse;
  flex-direction: column-reverse;


The flex-wrap property defines whether your rows will wrap or not. By default, rows will always try to fit on one line. Setting this property to wrap avoids overflow. It has three possible values:
nowrap: default value, single-line/left-to-right in ltr, right-to-left in rtl
wrap: multi-line/left-to-right in ltr, right-to-left in rtl
wrap-reverse: multi-line/right-to-left in ltr, left-to-right in rtl

.container {
  flex-wrap: nowrap;
  flex-wrap: wrap;
  flex-wrap: wrap-reverse;


Shorthand for flex-direction and flex-wrap. The first value is any of 4 from the flex-direction property, and the second value is any of the the 3 from the flex-wrap property.

.container {
  flex-flow: row nowrap;
  flex-flow: column-reverse wrap-reverse;


The justify-content property defines alignment along the main-axis. It helps distribute extra free space left over when either all flex items on a line are inflexible or are flexible but have reached their maximum values. It also has some control over the alignment of items when they overflow the line. It has 5 possible values:
flex-start: default value, items are pushed towards the start of the container
flex-end: items are pushed towards the end of the container
center: items are centered along the line
space-around: items are evenly distributed along the line with equal space between them.
space-between: items are evenly distributed along the line, with the first item pushed to the start of the container and the last item pushed to the end of the container.

.container {
  justify-content: flex-start;
  justify-content: flex-end;
  justify-content: center;
  justify-content: space-around;
  justify-content: space-between;


The align-items property defines the default behavior for how flex-items are laid out along the cross-axis on the current line. It’s like justify-content for the cross-axis (perpendicular to the main axis). It has 5 possible values:
flex-start: cross-start margin edge of the items is placed on the cross-start line
flex-end: cross-end margin edge of the items is placed on the cross-end line
center: items are centered on the cross-axis
baseline: items are aligned according to their baselines
stretch: default, items are stretched to fill the container (still respects min/max-width)

.container {
  align-items: flex-start;
  align-items: flex-end;
  align-items: center;
  align-items: baseline;
  align-items: stretch;


The align-content property defines the behavior when there is extra space in the cross axis across multiple lines. It’s like align-items, but for wrapped lines of content. It has 6 possible values:
flex-start: lines pushed to the start of the container
flex-end: lines pushed to the end of the container
center: lines packed to the center of the container
space-between: lines evenly distributed, with the first pushed to the start of the container and the last pushed to the end of the container
space-around: lines evenly distributed, with equal space around each line
stretch: default, lines stretch to fill remaining space.

On to the flex-item’s properties.


The order property defines the order in which flex-children are laid out. By default, they are laid out in the source order, however, you may want to change this given different contexts. Any whole integer can be used as a value.

.item {
  order: 1;
.item {
  order: 2;


The flex-grow property defines how much an item can grow if needed. It’s value is unit-less and serves as a proportion which dictates what amount of the available space inside the flex-container the item should take up. If all flex-items have flex-grow set to 1, remaining space will be distributed evenly among all children. If one of the children has a value of 2, the remaining space would take up twice as much as the others (or try to, at least). The default value is 0.

.item {
  flex-grow: 1;


The flex-shrink property defines the ability to shrink, if necessary. Whole integers are accepted but negative numbers are not. The default value is 1.

.item {
  flex-shrink: 1;


The flex-basis property defines the default size of an element before remaining space is distributed. It can be a length, like 20%, 20px, or 20rem, or a keyword. The auto keyword means ‘base this items flex-basis off it’s width or height property’. If set to 0, the extra space around content isn’t factored in. If set to auto, the extra space is distributed based on it’s flex-grow value.

.item {
  flex-basis: auto;


The flex property is the shorthand for flex-grow, flex-shrink, and flex-basis. The flex shorthand should be used as it sets the values of all three properties intelligently.

.item {
  flex: 1 1 auto; //flex: <flex-grow> <flex-shrink> <flex-basis>


The align-self property overrides the the default item alignment or the one specified by align-items set in the parent element’s declarations. It defines the behavior for how this flex-item is laid out along the cross-axis on the current line.
flex-start: cross-start margin edge of the item is placed on the cross-start line
flex-end: cross-end margin edge of the item is placed on the cross-end line
center: item is centered on the cross-axis
baseline: item is aligned according to their baselines
stretch: item is stretched to fill the container (still respect min/max-width)

.item {
  align-items: flex-start;
  align-items: flex-end;
  align-items: center;
  align-items: baseline;
  align-items: stretch;

Putting it all together

So, now we’ve got some flexbox knowledge, some knowledge on percentages, and some knowledge on why we need to make things different sizes on different screens. Let’s put it all together. Let’s assume that I don’t know exactly how wide my main content area and sidebar should be, but I’ve got a good estimate that the .main-content wrapper should be 3/5 of the screen width, the .sidebar should be 1/5 of the screen width, and the remaining 1/5 of space should be evenly distributed. We can use flexbox to do this job!

<div class='wrapper'>
  <div class='main-content'>...</div>
  <div class='sidebar'>...</div>
.wrapper {
  display: flex;
  flex-flow: row nowrap;
  align-items: stretch;
  justify-content: space-around;

.main-content {
  width: 60%; // 3/5
  flex: 0 1 auto;

.sidebar {
  width: 20%; // 1/5
  flex: 0 1 auto;

This sets the width of the items to 60% and 20%, respectively. No need to set margin or padding, this is done by assigning the space-around value to justify-content in the parent element. Here’s a demo:

See the Pen Simple Flexbox Demo by Nate Northway (@the_Northway) on CodePen.

This is great, and would work fine, but only until you get to the point where your content starts overflowing it’s containers. This is where things get real fun. We can set a media query to the point where content starts to overflow. In this case, let’s say it’s at 500px screen width. Inside the media query, we set the width of the flex-items to 100%, the flex-flow property of the flex-container to column nowrap, and violia, we have a collapsing system.

See the Pen Simple Flexbox Demo With Collapse by Nate Northway (@the_Northway) on CodePen.

Figuring out where to collapse your system

It takes a bit of trial and error. First off, know that no design system is perfect. Figuring out your breakpoints can be tough. Bootstrap’s grid system is as follows:

Extra-small: < 768px
Small: >= 768px
Medium: >= 992px
Large: >= 1200px

I think that’s a good starting point for figuring out your own breakpoints, but it may not serve you quite as well as others. I get my numbers on a per-project basis. If the design is very complex, using a lot of small elements, my breakpoints are usually numerous and closer together. If the design is simple, two or three columns, I usually have two or three breakpoints, spread apart. It depends on context, is what I’m trying to say, just as anything in web design: context is king.

I use a lot of other sources when I write things.
The CSS-Tricks Guide to flexbox is a wonderful reference that I use quite often.
I highly suggest reading Ethan Marcotte’s book, Responsive Web Design. And if you’re a podcast listener, I strongly suggest subscribing to his Responsive Web Design Podcast, as well.

Mobile Menus

Mobile menus are seen throughout the internet. The way mobile menus collapse is
summarized by one image: the hamburger icon.

The Hamburger Icon
The Hamburger Icon, in all it’s glory

But going from a fully expanded menu on desktop to a menu that has to be
expanded based on user input isn’t as simple as one might think. Sometimes, some
CSS & JavaScript is necessary. I’m going to walk you through my method to
implement an effective menu collapse.

First, the markup

Some frameworks and developers encourage you to bloat your HTML by creating a
<nav> element with two menus inside, one with id='mobile-nav' and one with
no id or id='nav'. I’m certain that’s not necessary and only serves to
complicate things.

My method goes a little more like this: Simplify the markup so the menus are the
same across platforms. Include the hamburger icon, but hide it above your
breakpoint. Clicking the hamburger icon triggers the menuToggle(), which tests
the #menu for it’s class and assigns it the opposite class. In the CSS, define
the 'hidden' class to display: none; and the 'active' class to
display: inline-block;. Hiding and showing the hamburger icon can be done in
CSS, as well. Here’s the markup:

    <button onClick='menuToggle()' id='hamburger'>
        <img src='hamburger.png' />
    <div id='menu' class='hidden'>
        <a href='#'>Link 1</a>
        <a href='#'>Link 2</a>
        <a href='#'>Link 3</a>

This menu serves two purposes: easier understanding of the markup and definite
consistency between larger screen views and smaller screen views. Encouraging
use of different menus opens the door for menu items to be missed or a similar
oversight. A menu that shares the same markup between small and large screen
views encourages consistency and eases inserting new items or removing old items
or refactoring or just updating your site.

The CSS Looks something like this:

#hamburger {
  display: none;
@media (max-width: /*your breakpoint here*/) {
  #hamburger {
    display: inline-block;
  .active {
    display: block;
  .hidden {
    display: none;

And that’s all there is to the CSS, besides styling it the way you want. Now to
the easy part: the JavaScript

$menu = document.getElementById('menu');
function menuToggle() {
  $state = $menu.className;
  if ($state === 'active') {
  else {

Again, pretty simple. All of this works together in harmony. A demo of
the above with a little extra CSS for styling is found on my CodePen. As you can
see, JS can be used to effectively control a nav menu. It can be done quickly
and easily, too. If you want your menu to look fantastic all it takes is a
little more CSS. You can go even further and add another button in the #menu
which calls menuToggle() if you want your menu to overlay the whole page. I’ve
used this method lots and lots and find it effective, explainable, and easy to
work with.

Project Flow

Prior to starting a relationship with a client, I like to walk them through the website design and development process. Often times, a lot of standard business practices are implemented, however, there are a few things unique to web design that (in my experience) have come as a surprise to the client.

The first step: Quote Request/Initial interaction

Normally, the first thing a potential client asks for is a quote. They give me a five minute breakdown of what their site needs, a timeframe, and a possible budget. They communicate this after hearing that I build websites, in a hasty email, or through the contact form on my website. They usually end their sentence with "How much will that cost???". I don’t know. I could do what you describe, but to accurately answer your question, we need to move on to step two.

Step two: Project Discovery

Project discovery helps me answer a potential client’s first question: how much will their website or app cost to build? My quote depends upon a lot of things, generally:

  • What technologies need to be implemented

  • How long it will take

  • How busy I am

  • What type of client you are

  • Features

  • Complexity of Design

I’ll break these variables down.

What Technologies Need To Be Implemented

I work mainly in HTML, CSS, JavaScript, PHP, and MySQL. I work with CSS preprocessors, jQuery, PHP libraries, and SQL extensions for PHP. Each of these skills has their own cost associated with them. A half hour of HTML & CSS work costs less than a half hour of PHP Programming, which also costs less than a half hour of MySQL programming.

I determine the technologies necessary to build your site from learning what problems your site needs to solve. Is there a lack of information in the world? Do you need a static, informational site? HTML, CSS, and JavaScript oughta do the trick. Do you need a blog attached to it? Add in PHP and MySQL. Do you also need your site to be translated? There’s an extra week (or two or three depending on which languages you need). Will your site have users with privileged access (such as admins to edit, delete, and add posts)? Tracking and analytics? All of these things add up.

Basically, the more complex, the more expensive.

The Site Itself

Site features and design complexity take skill to build, test, rebuild, debug, deploy, maintain and hotfix. The more complex your site or design, the higher your price point will be.

How Long Will It Take To Build Your Site

A big factor of your quote is time. If your site is going to take a lot of my time, it will be more expensive. There is a lot that I do in my life and web design isn’t the only thing. If your project deadline is in a short time frame and you need work turned around quickly, this probably means that I’ll be cutting into my personal time to build your site, which probably means that, unless I really really like you, you’ll be charged a premium for this time.

Generally, I work out time based on a few things. First, I take a look at the pages, functions, design, and every other aspect of the site and use my previous experience to gauge how many hours it will take me to build it. Factoring in an additional 5-10 hours of non-response time (link to ‘non-response time’ article), I then compare my hours estimate to your project deadline, based on 8 hours of work in a day, 24 per project per week. If, at these daily and weekly rates, your project deadline can not be met, I add $15 per hour to my hourly charge and adjust my timing so that your project can be delivered on time.

How Busy I Am

At any given point, I’m juggling at least 3 clients. Since I like to spend at least 24 hours in a week on each client, that means I’m juggling 72 hours of work per week before factoring in non-response time and 42 hours after factoring that in. So, if I have three clients and you want to jump on my client list, I’ll be honest with you and tell you if you can fit on my schedule. Generally, I try to flip every project within 3 weeks. Anything that takes longer than that should be considered a long-term project and we’ll be talking about gainful employment at that point. If you can fit in my schedule, I’ll give you a lower quote. If I’m really busy, your quote will be a little higher, simply because I’m usually tired at the end of the day as it is.

What Type Of Client Are You?

In a nutshell there are three types of client: the easy client, the mediocre client, and the annoying client. If you’re an easy client, your quote is lower. If you’re the mediocre client, your quote is unchanged by your client-type status. If you’re the annoying/helicopter client, I’m charging you as much as 20% more than the mediocre client.

Finishing up with Project Discovery:

Usually, at the end of project discovery, I’ll ask a few questions pertaining to design and UI/UX. I’ll ask what sites, colors, designs, artists, and cars you like. This helps me get a feel of what I’ll be aiming for design wise. Usually, I’ll try to sketch out some design elements, bring up some ‘inspiration’ sites, and explore some design patterns and UI/UX patterns using the demos that I have already built (mostly with CodePen). This really helps me determine project complexity and how it is to work with you as a client.

Once we’ve finished project discovery, I’ll be very clear about whether or not I think we could have a good relationship and start talking about the quote and the contract that I’ll be sending over for review.

Step Three: Quote Delivery

After we’ve determined all of the things that factor into the price of your site, I itemize the total quote and break it down. Usually, it looks a little something like this:

   Static Site: $   750
          Blog: $   350
 Dashboard/CMS: $   500
        Design: $   500
Implementation: $   250
           SEO: $   250
         Total: $ 2,600

This quote is further broken down in person so I can explain why and how I came up with these numbers. I’ll email this quote to you and request a meeting to answer any questions and discuss our contract.

Step Four: Quote and Contract

So you’ve got the quote. You know what you should budget. You talk to your boss. Your boss says ‘bring his price down’. You want to haggle a little bit. That’s cool. Haggle away. Everytime you suggest the price of your site to go down, it goes up because you’re becoming more of the annoying client.

Anyways, once we’ve agreed on a quote, we can start talking about the contract. Generally, I bring up a template I have and we talk it through, discussing the stipulations and applying any changes unique to our relationship. Doing it this way helps avoid confusing and lets the client know that I really am there for them.

After we negotiate the contract, I tell you that I’ll be emailing you within a week. Then I drop the contract off with my lawyer and make sure that nothing illegal or sketchy has been agreed upon, and I call you back for a contract signing.

Step Five: Contract Signing

Woah. Finally to the actual start of our relationship! At the contract signing, we sign the contract and you pay me 20% of the total quote. Then i run away in a frenzy and start building your website.

Step Six: iterative Design

Once I’ve built out most of the features, I put a development site on my server and give you access to it. You look at it, tell me what you like, don’t like, etc, and I explain or fix these issues. Usually, this is also a great time to test UI/UX to make sure it meets the needs of your customers. We do this a few times.

Step Seven: Testing

I test my sites a lot. I have a small team of beta testers whom I pay to break the sites I have built. I also try to break sites. This helps me identify edge cases and provides real world feedback so your site doesn’t break ‘out in the wild’. Once I’m satisfied that no more edge cases are being discovered and there are no errors with your site on any platform that we’ve deemed necessary, we can move on.

Step Four: Pushing the Site

Now that we’ve iterated over design and features and tested, we can push. This really isn’t hard and doesn’t take long, but it’s a milestone.

Step Five: immediate Maintenance

For one week after pushing your site, I provide 24/7 maintenance. I don’t mean that I don’t sleep for a week, I mean that if I’m awoken by a call from you saying that your site is down, I wake up and fix it. Sometimes this has to with DNS errors, floods of bots, crawlers, and people trying to break into your site. There are also some things that could happen with your web server configuration that need adjusting. That’s what this first week of being live is about. Finding those things and fixing them before they become too much of a problem.

Step Six: We’re Done!

Once that week of maintenance is over, you pay your final invoice, and our relationship is almost back to where it started – but now, you have a website.