If you’re seeing this, the site behind it is likely broken!

Hi, there. I use these course sites as little sandboxes to experiment with and learn various “brand new” CSS properties—and your browser does not support (at least) one of them. Apologies. It “should” always work in current/updating Safari and Chrome!

  • Typography & Interaction

    ’25–26

  • The Syllabus

  • Our Class

  • Unit Nº 1: “Type and the Web”

    Wks. 1–6

    • Week Nº 1

      Aug. 29

    • Everything Is a “Web Page”

    • Week Nº 2

      Sep. 5

    • It’s All About Type

    • Week Nº 3

      Sep. 12

    • An Intro to HTML

    • Week Nº 4

      Sep. 19

    • An Intro to CSS

    • Week Nº 5

      Sep. 26

    • The Box Model

    • Project Nº 1: “Manuscript”

      Oct. 3

    • Week Nº 6

      Oct. 3

  • Unit Nº 2: “There Is No Perfect Layout”

    Wks. 7–10

    • Week Nº 7

      Oct. 10

    • Responsive Design

    • DevTools (Web Inspector)

    • Week Nº 8

      Oct. 17

    • Finally, Flexbox

    • And (CSS) Grid

    • Week Nº 9

      Oct. 24

    • Some Additional, Advanced CSS

    • Our HTML/​CSS focus up to this point has been relatively broad, to start with the basics. Here we want to sand down some of the rough edges, and introduce you to some specific, advanced techniques you can use to refine and enliven your work⁠—still with just CSS, no JavaScript (yet)!

      It is vain to do with more what can be done with less.

      William of Ockham, 1324

      A good pattern to follow in web (and all) development is to use each technology only for what it does best⁠—using HTML for semantic meaning, CSS to handle how we form a page, and, later, JavaScript to introduce more interaction. But even before we get to JS, we can start to layer in some more interest and liveliness with our CSS.

      Let’s look at some examples.

      Overflows and Scrolling

      An overflow in CSS happens when there is too much content to fit in a container⁠—usually because you have manually constrained its block-size or inline-size. (By default, the browser will try to show you everything!)

      • overflow – MDN
      • Overflowing Content – MDN
        There are going to be a lot of MDNs, here.

      But we can use this behavior intentionally to crop our content, or create interally-scrolling areas:

      Importantly, this creates a new stacking context⁠—which means things with position (namely, position: sticky)⁠—and some other properties⁠—will now use the overflow container as their reference/​origin:

      • The stacking context – MDN
        Always confusing; think of these as frames or groups in Figma.

      text-overflow /​ -webkit-line-clamp

      You can also excerpt text (perhaps on a landing page) with the text-overflow (for a single line) or -webkit-line-clamp (for multiple lines) properties⁠—which will add an ellipsis … where the text overflows. Only do this when the full text is available on a subsequent page:

      • text-overflow – MDN
        For single lines…
      • -webkit-line-clamp – MDN
        And multiple lines!
      This -webkit stuff is hokey, but still how it is done! Browsers are weird.

      Precise Text Positioning

      You have probably noticed that HTML renders a lot of extra space around text elements, called the line box (or, in design software parlance, the bounding box).

      • Font Metrics, Line-⁠Height and Vertical-⁠Align
        A deep-dive on type positioning.
      • Vertical Spacing and Line-Height in Design Systems – Google Fonts
        It’s all very complicated.

      It is based on the font-family, the font-size, and the line-height, which basically means it is different all the time⁠—and crucially, often different from Adobe/​Figma to HTML. This makes it difficult to position type precisely⁠—especially at large, expressive sizes like your headings! It’s always annoying, and you’ll often be adding/​subtracting your spacing (margin or padding) to account for it, if you want to line everything up just right, optically.

      Let’s avoid it. We can use pseudo-elements, ::after /​ ::before⁠—which you may remember are entirely created by CSS, not in your HTML⁠—to negate this vertical space with a negative margin. By doing this on the pseudo-elements, we can still position the parent element normally, otherwise:

      Here we also move the text with margin-inline-start and margin-inline-end, though usually this adjustment is much more minor (to the point of ignoring).

      text-box is coming

      Figma was actually ahead of CSS here with its recent Vertical Trim option. The code for this kind of thing is getting much easier with the analogous text-box-trim and text-box-edge properties! These will negate all this pseudo-element, negative-margin dance with one line of code.

      • text-box - MDN
      • text-box-trim - web.dev
        So… much… easier!

      Caution: uneven browser support

      After a decade of workarounds and discussion, both shipping Chrome and Safari now support the super-easy text-box properties! But Firefox still does not, and it might be some time there.

      (This course site uses these heavily⁠—among the reasons it appears slightly broken in Firefox/​older browsers!)

      Text Ragging (Kinda)

      We’ve gone on-and-on about how you can’t treat the web like print⁠—always perfectly ragging your text for nice, smooth blocks. In modern (responsive) web design we don’t always know what our text will be, nor where it will wrap!

      But we can do a handful of things to make for better ragging/​wraps, given the unknowns⁠—judiciously using hyphens /​ &shy;, <wbr>, white-space, <nobr> and &nbsp;, and text-wrap to somewhat control your line breaks.

      hyphens /​ &shy;

      The hyphens property allows long, multi-syllable words to be hyphenated when they wrap across multiple lines. This can be done automatically by the browser, or by manually inserting &shy; (for soft hyphen) as an HTML entity:

      • hyphens - MDN
        This depends on the browser and lang, unless you manually add &shy;.
      Note <html lang="en"> is needed⁠—as the auto property works from each browser’s different, internal (and usually, only English) dictionary⁠—so this all has somewhat limited utility/​reliability/​consistency.

      <wbr>

      Somewhat related/​similar to &shy;, the <wbr> is a (void/​empty) HTML element that denotes a word break opportunity⁠—a bit like an optional <br> ! You can use these to manually control where single long word will wrap, without a hyphen:

      wbr – MDN
      These are often needed with slashes/​URLs.

      white-space: nowrap; /​ <nobr> /​ &nbsp;

      But much more often, you’ll want to keep certain words together⁠—to avoid a widow or orphan, or to keep important/​related text together⁠—like in dates, October 24, or with names like van Zanten.

      • white-space – MDN
        Prevents text from wrapping.
      • nobr – MDN
        This is technically deprecated. But one of your instructors is a “stan.”

      You can keep multiple words (or whole phrases) together with white-space: nowrap;. Historically, the <nobr> tag applied this⁠—keeping in mind that like <em> or <strong>the default behavior is cleared by most resets (ours included)⁠—so likewise you have to restore the property in your own CSS.

      You can also use a manual &nbsp; entity between words:

      On a Mac, you can insert an encoded &⁠nbsp; with ⌥ Space . (It’s apparently much harder on Windows.) This works in many programs, not just your IDE! It’s harder to see, but easier to read.

      text-wrap: balance;

      After many, many years of patient, typographic waiting (and some JS shenanigans) we now have widespread (and mostly even) browser support for “balancing” uneven line lengths with text-wrap: balance; :

      text-wrap – MDN
      Don’t overuse/​abuse this in running text, though!

      This is particularly noticeable (and helpful) for centered text! There is also pretty, but Safari just started to support it and Firefox still doesn’t.

      Hanging Punctuation (Sorta)

      Ideally we could set punctuation outside of our text blocks, for visual alignment based solely on the letters⁠—a traditional design technique called hanging punctuation. (There is actually a CSS property for this, but only Safari supports it! …ish.) But we can still approximate the behavior, at least for quotes:

      • ::before and ::after – CSS Tricks
        Another great CSS Tricks article.
      Note that the (pasted-in) curly quotation marks are not in the HTML here in the last example! Pseudo-elements again, ::before and ::after.

      When in doubt, The Elements of Typographic Style explains these conventions.

      But also, as Bringhurst says, “read the text before designing it.” Always put yourself in the mind of your reader!

      Reminder: There is no perfect layout

      These strategies only work if you can manually edit your text content, which is not always feasible⁠—with templating/​content management systems, editors, time, and so on.

      Do it when feasible⁠—and give more attention to your large headings, then your body copy, etc. going down your hierarchy.

      Filters!

      CSS can apply visual effects on elements⁠—adjusting their graphical display after they are laid out and rendered in the page⁠—with the filter property:

      • filter – MDN
        Back to MDN.
      Note that multiple filters are applied in sequence⁠—changing the order changes the end/​rendered result.

      These have corresponding backdrop-filter values⁠—which apply the effect to the page behind an element! You’ll often use these in conjunction with an opacity (or semi-transparent color) or a mix-blend-mode for interesting Photoshop/​Figma-like layer-blending effects:

      • backdrop-filter – MDN
      • mix-blend-mode – MDN
        Often used together.
      These are “hot rn.”

      Transforms!

      Beyond our standard sizing and layout afforded by CSS, you can also visually manipulate elements using CSS transforms⁠—scaling, skewing, translating, or rotating elements after they are laid out in the DOM. It’s like grabbing the “corner handles” in Adobe/​Figma!

      scale() /​ scaleX() /​ scaleY() /​ scaleZ() /​ scale3d()
      Change the displayed size of the element⁠—as if it is an image.
      skew() /​ skewX() /​ skewY()
      Tilt an element to the left or right, like turning a rectangle into a parallelogram.
      translate() /​ translateX() /​ translateY() /​ translate3d()
      Move an element left/​right and up/​down, and also in three-dimensional space.
      rotate() /​ rotate3d()
      Rotate the element.
      perspective()
      Doesn’t affect the element itself, but sets the distance between the user and the three-dimensional plane.

      transform – MDN
      These are fun⁠—but should not be used for actual layout!

      The units for these are all a bit different; MDN is your friend here, as usual. You can apply single or multiple transforms, which are written space-separated and applied one after the other:

      						.rotated {
      	transform: rotate(-5deg);
      }
      
      			
      	
      						.rotated-and-scaled {
      	transform: rotate(-5deg) scale(120%);
      }
      
      			
      	

      Keep in mind that these transformations are applied after the rest of the CSS is parsed, and thus treat your element a bit like an image. And like overflow above, transform also creates a new stacking context for its children:

      Note how the elements don’t take up more space in the document flow/​layout⁠—but they do cause an overflow!

      You shouldn’t use transform for layout⁠—as in, don’t use translate when margin, padding, flex, or grid can achieve your layout. This is bad practice, and usually very brittle! Especially when working responsively.

      Use transform only for what other properties can’t accomplish!

      Transitions!

      CSS transitions allow us to move nicely between CSS property values.

      • Using CSS Transitions – MDN
        Every state change is better with some easing.

      Instead of having a property take effect immediately when a pseudo-class is applied (or later, and more commonly, with JS⁠—a proper class), we can tell a CSS property to transition from one value to another over a given amount of time (duration), and with a specific acceleration (timing-function), or a delay. Motion can quickly get very complex!

      You’ll often see a transition in shorthand:

      						.some-cool-transition {
      	transition: all 2s 1s linear;
      }
      
      			
      	
      						.some-cool-transition {
      	transition-delay: 1s;
      	transition-duration: 2s;
      	transition-property: all;
      	transition-timing-function: linear;
      }
      
      			
      	

      You can also control how different properties of an element transition independently, with a comma-separated list:

      						.some-cool-transition {
      	transition: background-color 2s linear, transform 1s ease-in-out;
      }
      
      			
      	
      						.some-cool-transition {
      	transition-duration: 2s, 1s;
      	transition-property: background-color, transform;
      	transition-timing-function: linear, ease-in-out;
      }
      
      			
      	

      Sometimes the shorthand here is easier than discrete properties, where you have to maintain the same order across all of them. It’s all the same to the computer!

      Often, CSS transitions will be used with JavaScript when adding/​removing classes, to make a state change less abrupt. For now, we’ll use pseudo-classes to demonstrate:

      You can get even more control over the easing with a custom curve function.

      Nearly all CSS properties can be transitioned⁠—but keep in mind that changes that cause a reflow (re-triggering layout, sometimes called paint) are slow and can make your page feel glitchy⁠—especially when you start having many of them. Each in-between state causes the browser to re-render your entire document! So stick to changes of color, opacity, and transform for the smoothest performance.

      And Animations!

      Sometimes, transitioning a property from one value to another isn’t enough⁠—you may need more complicated (or repeating) motion behavior. CSS animation allows precise state sequencing with @keyframes (akin to… keyframes or a timeline in other software contexts).

      • Using CSS Animations – MDN
        Some of you already got into these!

      To create a keyframe animation, we define an element’s initial state in CSS⁠—then an animation property, which includes timing and behavior, as well as an animation name (something that you make up). Again, you’ll often see these in shorthand:

      						section {
      	animation: blinking 3s infinite ease-in-out;
      }
      
      			
      	
      						section {
      	animation-duration: 3s;
      	animation-iteration-count: infinite;
      	animation-name: blinking;
      	animation-timing-function: ease-in-out;
      }
      
      			
      	

      Importantly, we then define the actual keyframes of an animation in a separate at-rule. Each keyframe is specified with a percentage of the animation’s duration, and can specify multiple properties⁠—a bit like selectors for the time:

      Don’t go overboard! A little animation goes a long way.

      For accessibility, it is best-practice to scope your transitions and animations to folks who don’t mind the motion with media queries.

      With great power there must also come great responsibility.

      Stan Lee, 1962

    • Project Nº 2: “Spread”

      Oct. 31

    • Week Nº 10

      Oct. 31

  • Unit Nº 3: “Typography as Interface”

    Wks. 11–15

    • Week Nº 11

      Nov. 7

    • Working with Images

    • Week Nº 12

      Nov. 14

    • Week Nº 13

      Nov. 21

    • Thanksgiving Week

    • Project Nº 3: “Binding”

      Dec. 5

    • Week Nº 14

      Dec. 5

    • Week Nº 15

      Dec. 12

  • Winter Break

  • Unit Nº 4: “Interface as Interface”

    Wks. 16–21

    • Week Nº 16

      Jan. 21

    • Week Nº 17

      Jan. 28

    • An Intro to JavaScript

    • Week Nº 18

      Feb. 4

    • Some More JavaScript

    • Week Nº 19

      Feb. 11

    • Week Nº 20

      Feb. 18

    • Project Nº 4: “Links”

      Feb. 25

    • Week Nº 21

      Feb. 25

  • Unit Nº 5: “If All You Have Is a Hammer, Everything Looks like a Nail”

    Wks. 22–30

    • Week Nº 22

      Mar. 4

    • Putting a (Link/​Meta) Bow on It

    • Week Nº 23

      Mar. 11

    • Spring Break

    • Week Nº 24

      Mar. 25

    • Week Nº 25

      Apr. 1

    • Week Nº 26

      Apr. 8

    • Week Nº 27

      Apr. 15

    • Project Nº 5: “Functions”

      Apr. 22

    • Week Nº 28

      Apr. 22

    • Week Nº 29

      Apr. 29

    • Week Nº 30

      May 6

    • “Everything Else”

    • The end