remodelling the house
“Text is responsive”
– Laurel Schwulst
“You dumbass. You thought you needed media queries to be responsive, but no. Responsive means that it responds to whatever $^%^@) screensize it’s viewed on.”
– http://motherfuckingwebsite.com
In this session, we’ll start to explore the principles of responsive web design, looking at ways that sites can change depending on the environment they’re in.
intro
c s s s s s s i p e s:
- what was weird?
- what was hard?
- what felt good?
- what happened that you didn’t expect?
- did your impression of any elements change?
lecture: responsive design
It’s worth saying that not all responsive design has to be terribly fancy (indeed, many very simple sites fill lots of responsiveness criteria, just being vanilla HTML and CSS!). What we’re going to talk about today are tools that can help you realise more complex ideas across a range of different screens, but it’s always worth figuring out what works for your site and content first.
Developing on her comment about text, Laurel also talks about ideas of going ‘with’ rather ‘against’ the grain of the web: the web has a way of arranging things and a natural flow to it.
Remember, CSS is declarative! It’s a language of suggestion rather than control. Browsers have the control here -> we’re not ‘describing steps to achieve an outcome’, we’re declaring an end goal we want the browser to achieve. This way of thinking can be really helpful: it’s the same reason you get no ‘errors’, as such: it can look how you don’t want it, but it will always run. In the end: if you over-define, the browser will not make the right decision…
layout history
Way back in the olden days of web design, sites could have either fixed or liquid layout (like this site, lol).
For simple sites these are fine, but they get less ideal if you 1) want to have more than one main block of text and/or 2) stray very far from the size of the browser it was designed for. In the early days of mobile, developers would make a separate version of the site just for mobile screens, where users would be redirected if the window was below a certain size (these have addresses like “m.example.com”).
responsive design
The term ‘responsive design’ was coined by web designer Ethan Marcotte in 2010, and refers to a kind of design that adapts itself to different screens, without needing to be specified at lots of different breakpoints, or render different pages for different screens.
Responsive design relies on 3 major techniques:
- media queries: how to figure out what kind of display you’re on
- flexible grids: multi-column layout, flexbox and grids
- fluid images: min- and max-width properties
Many ideas in responsive design are concerned with how to make the elements on your page change relative both to the changing screen, and to one another. They require you to be a bit smarter in designing the rules for how your components should interact together, and consider the page in terms of relationships, rather than fixed values.
min and max width
playing along? min-max-width.html
Min and max width are really useful for defining fluid images and columns. This can also be done for height, but it’s much less common.
A popular way to do this is to set the max- dimension to be variable as a proportion of the container, then the minimum dimension stay fixed.
img {
min-width: 500px;
max-width: 50%;
}
Note: if an image is smaller than the max-width
property set for it, it won’t stretch to fill it!
the display property
playing along? display.html
The ‘display’ property determines if and how an element is displayed. It’s the basis for defining whether elements feature in more complex kinds of layout formations (like grids and flexboxes), but it can also define things like whether an element is
Note: Setting the display property of an element only changes how the element (or the element’s children) is displayed, NOT what kind of element it is. So, an inline element with display: block;
is not allowed to have other block elements inside it.
The first 3 settings we’re going to look at are inline, block, and inline-block. (there are 20 possible values of display! we will not look at them all here).
- inline elements like spans can have padding and margins set, but no width or height. These will not cause a newline
- elements with property block can have a width and a height, and will cause a newline
- elements with property inline-block behave like inline elements, but they can have a width and a height too!
hiding things – an aside
There’s a few cases where hiding things can be really useful, particularly in responsive design! There are two ways to do it:
- display: none – this will make it like the div was never there…
- visibility: hidden – this will keep the space where the div was, but the content becomes invisible
CSS grids
playing along? grid.html
CSS grids, in their simplest sense, are a bunch of boxes in another box. (So are flex-boxes!) In order to become a grid, the outer box needs to have the property display: grid
set.
Grids allow us to define rows and columns where our content sits. Columns can be defined with the property grid-template-columns
, and rows with the property grid-template-rows
, These grids can be fixed-width:
.grid-container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
This will create 3 columns, each of width 200px, where my divs will sit.
But perhaps we want our columns to change width when the page changes. We can use flexible length units to define these columns:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
Or perhaps, we’d like to mix and match!
.grid-container {
display: grid;
grid-template-columns: 500px 1fr 2fr;
}
How do we deal with rows?
Because the rows have been created automatically (just by defining columns!) we can’t specify grid-template-rows
in the same way. Instead, we need to use grid-auto-rows
, which will automatically set the row height . The catch? If we don’t know how many rows we have, we can’t use fr
as a unit.
.grid-container {
display: grid;
grid-auto-rows: 200px;
}
One of the most useful properties of grids is that they allow you to place items of different shapes and sizes relative to the grid layout. Using the grid-column-start
and grid-column-end
properties, it’s possible to tell the browser to map out part of the grid for particular boxes.
.grid-box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
}
.grid-box2 {
grid-column-start: 1;
grid-row-start: 3;
grid-row-end: 5;
}
If you want grid practice, particularly of this part, css grid garden is a great tutorial.
Just as in typesetting, we’re able to define gutters for our grids. This is done with the column-gap
and row-gap
property, or grid-gap
if they’re the same.
This is not all there is to know about grids! For a longer and more thorough guide the MDN docs have a lot of good info. Questions such as ‘can I put a grid in a grid?’ will be answered.
Both Chrome and Firefox come with Grid-Inspector tools that let you look in detail at how a grid is laid out!
flexboxes
playing along? flex.html
Flexboxes, just like grids, are created by putting some boxes inside another box. Like before, the outer box needs to have the property display: grid
set. This outer box is called the flex grid-container.
Flexbox is interesting as it deals with layout one dimension at a time – either in terms of rows or in terms of columns, using the flex-direction
property. That means: if you want your boxes to be arranged left-to-right (then make new lines when they run out of room), set flex-direction
to row. If not, set flex-direction
to column. (to go backwards, row-reverse
or column-reverse
). This direction is called the main axis. The other axis (at 90 degrees) is called the cross axis.
.flex-container {
display: flex;
flex-direction: row;
}
To wrap our boxes onto multiple lines (or multiple columns, if our main axis is columns), we set the flex-wrap
property in the parent grid-container. If we set it to no-wrap
, our boxes would shrink to fit the width of the grid-container, and expand in the cross axis if their contents was too large. See this guide for more wrapping details.
.flex-container {
display: flex;
flex-wrap: wrap;
}
Flexboxes also give us a way of distributing leftover space on lines to our boxes. By setting the property flex-grow
in the inner boxes, we can control the proportion by which each box grows to fill the space. (note: these have to be whole numbers);
.flex-box1 {
flex-grow: 1;
}
.flex-box2 {
flex-grow: 2;
}
The flex-shrink
property does an equivalent thing, but if your flexboxes overflow the total space available in the main axis. In that case, this property sets the proportion by which each div will shrink in that direction.
To distribute flex-boxes, there are two properties used:
justify-content
controls the alignment of all flexboxes along the main axisalign-items
controls the alignment of all flexboxes along the cross axis
.flex-container {
display: flex;
align-items: center;
justify-content: center;
}
This can also be used to control the spacing. There are 4 different ways to space out the boxes:
- flex-start: this will pile the boxes at the start of the flexbox
- flex-end: this will pile the boxes at the end of the flexbox
- center: this will center the boxes in the middle of the main axis
- space-between: this will distribute the boxes evenly along the axis, with the first flush to the left side, and the last flush to the right side
- space-around: the boxes are distributed so that each has an equal amount of space around it (note that this means the space between the box and the edge appears half as wide)
- space-evenly: the boxes are distributed to make the spacing between each box and each edge even
MDN’s guide to aligning items in a flex container, and the CSS-tricks guide to Flexbox is helpful for this.
media queries
Media queries allow you to specify things like a device’s type and characteristics. These can include things like whether the page is intended for print or screen (HTML is just typesetting, remember!), and more specific parameters, like screen resolution and viewport width.
To test out media queries, and what your site looks like on different screens, go into your browser’s ‘responsive design mode’. In Chrome and Firefox, this is a little phone icon in the corner of the console (cmd-alt-i), in Safari, go to Develop > Enter Responsive Design Mode.
The and
keyword here means that the block will apply when both things are true. In this case, it will apply when the page is less than or equal to 600px wide.
@media screen and (max-width: 600px) {
}
You can have multiple @media
queries in one file.
breakpoints
Breakpoints are the points at which your site will ‘break’ into another orientation. These are defined by the CSS media query.
Every site is unique, and there isn’t necessarily a ‘correct’ set of breakpoints to aim for – this will depend on a lot of other things than just the size of the screen you want to deal with. This guide, however, has some good tips for choosing breakpoints based on the screens you expect to be viewing your site.
To get started, try the typical values listed here, and try the demo.
layout generators
grid layout generator
flexbox generator
accessibility
w3c web content accessibility guidelines
understanding WCAG in HTML in JS and CSS
things to watch out for
Mobile viewports are notoriously annoying to configure correctly, due to the way different phones will overlay different kinds of navigation toolbars at the top and bottom of the page, and scrollbars on the side.
In addition to considering mobile devices in ‘portrait mode’, make sure you include provision for ‘landscape’ too!
Don’t use grids and flexboxes together! Not only is it horribly confusing for you (and anyone that has to read your code), but it’s uneccesary, and will confuse the people using the site, too. They’re fundamentally different ways of looking at the same problem (how to arrange your objects on a page)
Tutorial: flexbox, grids
tutorials
resources:
general CSS resources:
- W3schools – consistent+extensive introductions to most features in CSS, good for reference. Their selectors guide is particularly extensive.
- CSSTricks – really good for specific CSS resources and explanations. Useful code snippets too!
- Mozilla Developer Notes – good for reference, and also understanding a feature in the context of other web developments, the theory of the language, and the history of the web. (why is this thing like this?)
an aside: measurements
The article px-em-%-pt-keyword has a really good run-down of the different units and what they mean for text.
- keyword – small, medium and large (surprising consistency across browsers, not recommended for anything flexible)
- px – accurate, will be the same number of pixels whatever you do
- em – these are a little more abstract: 1em is the current font-size of the HTML element that you’re in. These also allow you to define other measurements relative to the size of your fonts. This is the basis for an approach known as component-level sizing
- % – percentages give you a font size as a percentage of the font size of the parent div. This is a neat way to get fonts to scale relative to one another.
- pt – pt is only used for print CSS! Don’t use these for screen display: cross browser results vary wildly. It’s done relative to whatever the browser thinks an inch is… pt are accurate for paper the same way px are accurate for browsers
The idea of ‘cascading’ is important here: both % and em inherit values from a the font-size property of a parent, meaning that, if you set it up right, changing the value of the top-level font can change all the values on the page according to the same ratio. It can allow you to be very effective with media specifications without having to write lots of redundant code, and is worth experimenting with!
in-class assignment
In pairs or threes, make a page that changes as you resize it. You can choose any one of the techniques we’ve covered this class.
Can you tell a joke or reveal a mystery? (if you can commit it to git, find out what it looks like on your phone!)