Sample Video Frame
04: Simple Styling
In this module I'll go through many of the common stylistic properties you'll need to start doing basic HTML and CSS pages. There are many CSS properties but we'll start with most direct properties. By direct I mean that changing the property should make an obvious visual change to the HTML element. Other properties can be difficult to see when you change them, so we'll need to use some special tricks later to help with that.
That Border Trick
I give a constant piece of advice when people are learning to code:
Always be printing.
This means that when you have a problem with your code you print everything you can to see inside the program, or use a debugger to help you see how it's running. It's simply too difficult to solve most bugs by simply reading the code repeatedly. You need additional information.
CSS has the exact same problem except the results are visually obscured. Many times you can't figure out what is going on with CSS by simply staring at the webpage. All of the boxes that control CSS are invisible to you by default plus the mechanics behind CSS are far too complex and indirect to reason about them from just the visuals.
You need something similar to printing in CSS, and that "something" is the 1px red border:
p {
border: 1px solid red;
}
I recommend you add this to CSS rules when you first write them. I try to do this but old habits die hard and I still just go for it, then run into trouble, then add the border later. If you want an easier time then add the border right away, get the CSS right, then remove the border. I also recommend trying other colors like "hotpink" since they are easy to find later and remove with a single search (unless you've got a website that's all hotpink).
Display
The display
property is simply the worst. There are 22 different versions of this one property, and many of them are seemingly arbitrary combinations of others that seek to fix the previous versions. My main solution when something is displaying weird is to slap display: block
on it and see if that fixes it. 90% of the time that does it, and my research will show that this tag is display:list-item
unless it's inside a display: flex
then it's display: inline-flex
and honestly it's just the worst.
Added to this is that display: inline
ignores height and width, which is a great example of CSS's inconsistency. Many times I've tried setting the height or width of something only to find out that it's simply ignoring my commands because someone in 1997 decided that this tag should be inline, not block.
My recommendation is stick to display:block
, display:flex
, and display:grid
for most things, then when you have specific problems look at this list to see which one will work best.
- inline -- Any height and width properties will have no effect.
- block -- Starts on a new line, and takes up the whole width.
- contents -- Parent disappears, but children are there. Rarely used.
- flex -- Our saviour in all of this, the glorious flexbox, which we'll cover later.
- grid -- Flexbox's sidekick and totally not a table.
- inline-block -- It's inline but you can set width and height...ok sure.
- inline-flex -- Really? Ok it's flexbox but...inline? Rarely used.
- inline-grid -- Again? It's inline...but a grid.
- inline-table -- Sigh. And inline but a table.
- list-item -- Makes it act like a list tag like
<li>
- run-in -- Displays as either block or inline depending on context...wonderful.
- none -- Completely remove it, but probably not what you want since this also removes it's space. If you want to hide something use opacity.
- initial -- Sets this property to its default value.
- inherit -- Inherits this property from its parent element.
There are also properties that make tags behave like a table, but these are rarely used since you can just use grid
or use an actual <table>
.
The Display Property Savior
While I say that display
in general is a haphazard compendium of codified browser bugs, there are two recent improvements that have helped to redeem CSS:
display: flex
-- This is finally a modern layout algorithm that makes it easy to create complex layouts that can handle nearly anything.display: grid
-- Anything thatdisplay: flex
can't do thedisplay: grid
can, although it can also be more complicated depending on how you use it.
In this course we will mostly do our layouts using these two display mechanisms as they dodge all of the weird hacky issues found in other display settings.
Width and Height
The most basic property is width
and height
. This property randomly works depending on where your element is placed, so be careful when you specify it and it doesn't seem to work. In the Display property section of this module I described how different tags (elements) have different default display properties. These properties are very easy to use:
div {
width: 100px;
height: 100px;
}
That sets the width and height of all div
elements to 100 pixels...probably. Fixed sizes like this should be reliable but many times you'll specify a size and it doesn't really do what you want, especially with the height. You definitely want to use the red border trick to sort out size issues.
Units of Measure
There are many measurement units in CSS now which allow you to dynamically size your elements (among other things). First we get into the absolute measurements, which are mostly for fonts and print media, since they have to deal with real physical sizes:
cm
,mm
,in
-- centimeters, millimeters, and inches. Honestly real physical size specifiers don't work well on computer screens.px
-- pixels, which is as good a fixed unit as you'll find, but given the varying resolutions of screens probably isn't as exact as some people want.pt
-- points, which is based on 1/72nd of an inch and actually not that useful on the screen except for when giving sizes of fonts where it's more common.pc
-- picas which is another font based measurement that's not incredibly reliable
I find that I don't use these too often, but I will use px
for things that are specific sizes. A good example if icons and avatars, which are in specific multiples of 8 on most platforms. I'll have to set 24, 32, 48, 64, and so on since those fit different operating system's icon image guidelines.
The measurements I do use often are the relative measurements, and that's because computer screens come in all shapes and sizes. I think about once every 6 months I get some user with a 32:9 curved gaming monitor complaining that when she "full screens" my website it doesn't work right. It never occurs to her that it's her monitor and not my website that's messed up, but with relative size measurements I at least have a small chance to make this situation usable. I'd say without the relative sizes the 32:9 gaming screen owners would have to do something drastic like...shrink the browser to 1/4 the size of their screen.
Actually, why would you own a monitor that big and then full size everything you see? Weird. Anyway, let's use this as a clear--although insane--example for these sizes.
em
-- font-size of the element.ex
-- the x-height of the current font.ch
-- the width of the "0" (zero).rem
-- the font-size of the root element.vw
-- 1% of the width of the viewport. That means if someone is on a 3200x900 pixel sized monitor then1vw
will be 32 pixels wide.vh
-- 1% of the height of the viewport. That means if someone on a 3200x900 pixel sized monitor then1vh
will be 9 pixels high.vmin
-- 1% of the viewport's smaller dimension. On a 3200x900 pixel monitor that's the 900 side, so1vmin
will be 9 pixels.vmax
-- 1% of the vieport's larger dimension. On a 3200x900 pixel monitor that's the 3200 side, so1vmax
will be 32 pixels.%
--- % of the parent element's dimension.
Keep in mind that when I say "viewport" it's not the monitor size. I'm using the monitor size in these examples since it's from my example above and works to give you a size, but the "viewport" is the part inside the browser where the document is rendered, not the whole screen. That means you have to remove the window "chrome" which is the menu, slider bars, and other things the OS puts on all application's windows.
Margin and Padding
The margin
property sets the spacing between two elements, and the padding
property sets the spacing inside an element. You can use any of the units of measure you want, but it's usually best to stick to the relative units (em
, rem
are personal favorites) unless you're doing small changes in size then px
works. Finally, both of these come with specific variants for each side of the box:
margin: top right bottom left
-- This shorthand form goes clockwise giving the top, right, bottom, then left side.margin: top sides bottom
-- The 3 unit form works like the above but sets the left and right sides to the same.margin: topbottom sides
-- The 2 unit form gives the top and bottom one size (topbottom), but the left and right another size.margin: all
-- The 1 unit form sets all sides to be the same.
Padding has the same 4, 3, 2, or 1 unit forms as margin, and this is a common pattern in anything that sets sides to a box. I never remember these so I tend to use these more explicit forms when I need to set only one side:
margin-top: size
-- Sets only the top margin.margin-right: size
-- Sets only the right margin.margin-bottom: size
-- Sets only the bottom margin.margin-left: size
-- Sets only the left margin.
Again, padding has the exact same specific properties with padding-top
, padding-left
, padding-right
, and padding-bottom
.
Fonts
The font
property is fairly complex since there's so many fonts with so many names, but the most basic forms are:
font: font-style font-variant font-weight font-size font-family
-- This is the basic form where you specify all the properties for the font of that element.font-style
-- Only the font style.font-variant
-- Only the variant.font-weight
-- Only the weight. Are you seeing a pattern here?font-size
-- Gives a size of the font.line-height
-- The only one that doesn't start with font so you can explicitly set the line-height.font-family
-- This is the actual font name. Finally. If the name of a font has a space then quote it, like "Times New Roman".
Background
The background property can be something as simple as just setting a color, but it also can get very complex with images and positioning those images. You can also repeat background elements to create layered graphics. This is what many "CSS painters" do to create their complex paintings using a single <div>
. They're "simply" doing repeated background specifications.
background: color
-- This sets the color of the background for the element.background: url("/image.png")
-- Uses an image for the background.background: url("/image.png") repeat-style
-- The same but you can specify how the image repeats itself.
These are the three I use the most, and I think if you need more than that then your idea might be too complex, or you should use the "layer" trick I describe below. I find that background images become far too difficult to control in modern screens with their varying sizes.
The repeat-style
can be one of these (taken from the MDN documentation on background-repeat):
repeat
-- The image is repeated as much as needed to cover the whole background image painting area. The last image will be clipped if it doesn't fit.space
-- The image is repeated as much as possible without clipping. The first and last images are pinned to either side of the element, and whitespace is distributed evenly between the images. The background-position property is ignored unless only one image can be displayed without clipping. The only case where clipping happens using space is when there isn't enough room to display one image.round
-- As the allowed space increases in size, the repeated images will stretch (leaving no gaps) until there is room (space left >= half of the image width) for another one to be added. When the next image is added, all of the current ones compress to allow room. Example: An image with an original width of 260px, repeated three times, might stretch until each repetition is 300px wide, and then another image will be added. They will then compress to 225px.no-repeat
-- The image is not repeated (and hence the background image painting area will not necessarily be entirely covered). The position of the non-repeated background image is defined by the background-position CSS property.
Position
Position allows you to change the normal top/down flow of HTML tags, but it's another weirdly designed property with all sorts of footguns. First, let me give you all the property settings then explain why position
is sort of broken with a practical example.
static
-- The default positioning is just however the normal rendering works.relative
-- This will take a tag and move it from its current position, but it will keep the original box and space. Think of this not as moving the whole tag, but more projecting it to different coordinates. You'll probably use this position when you don't want static, but you want the tag to behave as if it's static.fixed
-- Positioned relative to the viewport of the browser page.absolute
-- Positioned relative to the nearest positioned ancestor...wrong! Gotcha, 'cause if you think this will position it relative to your parent you're wrong. It only positions relative to the parent if the parent is anything butstatic
, and that's why you needrelative
.sticky
-- This one is tough to use, but basically it will scroll like normal when its in view, but then when the page scrolls out of view this element will "stick" to the top or bottom. To support Safari you need-webkit-sticky
as well.
top, bottom, left, right
To make the position
property work you'll also need to specify it's location using these:
top
-- The location from the top.bottom
-- The location from the bottom.left
-- Yep, the location from the left.right
-- You guessed it, the location from the right.
These properties are how you "position relative to" the other tags. The only problem with these is they're inconsistent in what they do depending on how you use them and inside what position setting. I recommend you add the 1px-red-border to both boxes (parent and child), then change these until its right.
Layers, Overlays, and z-index
Remember how I said position
is another property that is full of footguns? The reason is the specification says some of these properties do different things depending on their parent's position setting. To me that's simply the worst design and leads to mysterious layout failings because I misspelled "relative" as "reletive". The way a computer program should work is if I say, "this here is positioned relative to the parent," then it's always positioned relative to the parent. If I say something is position: absolute
, then it is always position absolute. There should be no weird special cases and exceptions that I have to watch out for.
The situation where you'll most likely run into this is when you want to "layer" an image over something else. According to the description you'd think this would work:
<!DOCTYPE html>
<html>
<head>
<style>
container {
margin-top: 100px;
display: block;
font-size: 3em;
background-color: #aaa;
border: 1px solid green;
height: 100px;
width: 100px;
}
layer2 {
display: block;
position: absolute;
top: 0;
left: 0;
border: 1px solid red;
}
</style>
</head>
<body>
<container>
<layer1>A1</layer1>
<layer2>B1</layer2>
</container>
</body>
</html>
This is a full HTML page so you can try this yourself, but what I'm doing here is this:
- I create a
<container>
and two contents for it:<layer1>
and<layer2>
. - To better see the failing, I'm also moving
<container>
down 100px by settingmargin-top: 100px
. If I don't then it'll look like this works when it actually doesn't. - I then want
<layer2>
to "overlay" (or cover)<layer1>
. The effect should be that the letters "B1" cover "A1". - I'm also setting the
background-color: #aaa;
of<container>
so you can see the bounding box easily, and giving it a size ofheight: 100px;
andwidth: 100px;
so it's visible.
If you type this in (you should) and load it you'll see that B1 appears at the very top of the window at position 0, 0
. But I told CSS to do position: absolute
so shouldn't it be contained inside <container>
? No, because of an obnoxious footgun in CSS that none of the pros seem to know about. To make <layer2>B1</layer2>
stay inside the <container>
we have to set <container>
to be position: relative
, or anything that's not the default position: static
. Using relative
seems to work as a good alternative to static, so I use that and then it works:
container {
margin-top: 100px;
display: block;
font-size: 3em;
background-color: #aaa;
border: 1px solid green;
height: 100px;
width: 100px;
position: relative; /* magic! */
}
Now, there's one more little fix and we need to use something called z-index
. Normally when you stack things using position: absolute
they will be stacked in a kind of random order. Predicting this order is far too difficult, so what you should do is build the stacks, then if they're wrong fix them with z-index
. The alternative is reworking your HTML until its just right (at which point you'll hit something else that makes it fail). With z-index
you just set the order and you're done.
This is the process I use when I want to create layers consistently:
- Create each element as siblings of a parent tag.
- Set the parent tag to
position: relative
. - Set the children to
position: absolute
and give themtop: 0
or any other coordinates they need. - If they're out of order I then add
z-index
to reshuffle them.
Lesson Challenge
I'm going to give you a puzzler piece of HTML that you need to type in and make work before you attempt this challenge:
<!DOCTYPE html>
<html>
<head>
<style>
A1 {
border: 1px solid yellow;
}
<!-- your answer here -->
</style>
</head>
<body>
<A1>
<B1>red box</B1>
<C1>blue box</C1>
<D1>
<G1>green box <b>blue background</b></G1>
<H1 id="orange box">orange box</H1>
</D1>
</A1>
</body>
</html>
I've started you off with the CSS you'll have to use to place a border around an element. You know how the selector works, but in the next exercise I'll go deeper into how the property border: 1px solid yellow
works and cover many more. For this challenge though you only need to know that putting border: 1px solid red
would put a red border around things, and using background-color: blue
would make its background blue.
Your challenge is to make boxes and backgrounds that match the text. For example, the <B1>red box</B1>
should have a border: 1px solid red
to create a red box around it. For the blue background text you'll want to use the property background-color: blue
. You'll see what that does later, but for now try to figure out from what you know so far how the background-color
might work to solve this puzzle.
Lesson Challenge
I've explained some of the theory behind the CSS rules and you should be trying to play with these while you work through this module. As I mentioned earlier the best way to really learn something visual is to attempt to apply what you learned to copies of other people's websites. In this challenge your task it to find a simple blog that you like and make the best copy you can of it. You don't know about many positioning CSS properties yet, but attempt what you can and see how close you can get with just what you know.
After you copy one site, either do one more copy, or delete this and do this copy one more time. Doing things twice helps you confirm that you actually can do it and that it's not just plain luck. If you did it twice then it's not luck, it's skill. If you can't do it again, then go back and figure out what knowledge you're missing.
Remember to have fun doing this, take your time, and push the accuracy as far as you can. The goal is not to make something perfect, but to learn everything you can from the website you are copying.
Register for Learn JavaScript the Hard Way
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.