More Advanced CSS - Zombie in a Ballgown
Shaping the Undead
CSS shapes allow you to cut different shapes out of text to illustrate a point or to allow more interesting layouts. It doesn’t draw or create shapes—it flows text around them. The element you’re creating the shape around must be floated either right or left, and the text only flows around it in one direction. For example, if you have a circle that you’d like to smash a horde of text upon, the text will not flow down both sides—it will only flow down the opposite side you floated the element toward. So if you float the circle left, text will flow down the right side, and vice versa. Use the CSS property shape-outside to set the shape your content can flow around.
Night of the living tip:
Funnily enough, like a proton-sized zombie antidote, shape-outside will only work within an element. You set the outside shape of the element—so you determine how external elements and text will interact with the element when it’s floated. Every element's default shape is a rectangle. If you use a circle function on that element, the circle needs to be within the rectangle to have an effect. If the radius of the circle is bigger than the distance between the rectangle’s corner and its center, the circle will have no effect on the content that flows around the element.
Circle: The circle function creates a circle, based on the radius value you give it.
.zombie-circle {shape-outside: circle(3em);}
You can also change the placement of the center of the circle using “at” and an x and y dimension:
.zombie-circle-at {shape-outside: circle(100px at 50% 60%);}
Ellipse: allows you to create an ellipse by setting both a horizontal and vertical radius.
.zombie-ellipse {shape-outside: ellipse(100px 140px at 50% 55%);}
Inset: will create a rectangle, just like the default behavior, but allows you to do two special things with it. One is that you can create that rectangle inset from the edge of the element.
.zombie-rectangle {shape-outside: inset(20px 30px 50px 0);}
The second is the ability to create a rounded rectangle.
.zombie-rounded-rect {shape-outside: inset(10px 10px 10px 10px round 50px);}
Polygon: lets you create a polygon of any shape to flow text around.
.zombie-trapezoid { shape-outside: polygon(37px 9px, 157px 7px, 189px 131px, 7px 127px);}
You can also use an image or gradient, depending on the image’s or gradient’s alpha values (the amount of transparency in the image/gradient at any particular pixel) and what you set as the shape-image-threshold. It takes a value from 0 (fully transparent) to 1 (fully opaque) and sets the amount/level of alpha along which the text flows i.e. the edge that the text bumps up against.
.zombie-image { shape-outside: url(zombie.png); shape-image-threshold: 0;}.zombie-gradient{ shape-outside: linear-gradient(37deg, yellowgreen 0%, rgba(0,0,0,0) 100%); shape-image-threshold: 0.45;}
We’ll discuss gradients in detail later in this book, so don’t worry if they don’t make sense right now.
Just like you need to create a buffer between the walls of the human resistance fort and the place where zombies live, you can use shape-margin to give you an extra buffer between the edge of the shape you’ve created and the text that’s flowing around it. (Similar to the Night of the Living Tip above, the shape-margin property will not push the text beyond the edge of the element you’ve shaped.)
.buffer { shape-margin: 5px;}
Codepen Demo:
Functional Zombies
CSS has quite a few functions that let us calculate values and pull data from other places.
Unlike most programming languages, CSS does not allow you to make your own functions, but there are still plenty of useful things you can do with the ones available.
Calc(): allows you to calculate numbers on the fly. This is good for centering or when you want an element’s width to be 100% minus the width of a sibling element—or any time where a calculation can make the site more responsive and/or more flexible (able to handle a wide variety of contexts and situations without breaking).
.zombie-accountant { width: calc(60% - 5em);}
As you work on different layouts, and particularly as the zombies swarm around you, you’ll probably want to calculate the odds (or widths) that two or more elements can fit together horizontally. With the variety of units available to set widths in—percent, pixels, ems, rems, vws, and so on—you sometimes need to mix units to make things work…but what’s 100% minus 600px, or 10vw minus 2em? That's where calc rides in to save the human race from utter annihilation.
.zombie-accountant-2 { width: calc(100% - 100px);margin: calc(10vw - 2em) 1em;}
You can use it wherever a length, frequency, angle, time, number, or integer is allowed.
Night of the living tip: Particularly when subtracting, be sure to put spaces around your hyphen. If you don’t the browser could interpret the subtraction sign as a negative sign (negative 5 pixels instead of minus 5 pixels) and the results may be different than expected or the browser might choke on the lack of an operator.
Cubic-bezier(): is used for creating custom timing functions in animations and transitions. The cubic-bezier is a curve that determines how fast or slow an animation starts and ends—that is, a line or curve that represents the acceleration of the animation or transition. You build a cubic-bezier curve using four points. The beginning point in CSS is always 0,0, and the ending point is always 1,1. So in the cubic-bezier function, you give four values that are the x and y position for two other points that determine how the line curves. All values should be between 0 and 1.
div.re-animated-zombie { animation-timing-function: cubic-bezier(0.7, 0.12, 0.9, 0.3);}
Steps(): Sometimes you need an animation to work in quantified steps rather than in a smooth transition. To create those intermediate steps use the steps() function.
div.re-animated-zombie-2 { animation-timing-function: steps(5, end);}
For more information on animating things in CSS, check out CSS Animation: De-Animating the Undead. (coming August 2020)
Attr(): allows you to grab the value of an attribute. You’ll use this most often for showing attribute data using pseudo-elements—for example, printing out the linked-to URL in a print style sheet. You can also use it to display data-* attributes, show alt text, and provide other accessibility info to users.
.printing-zombies::after{ content: “ { “ attr(href) “ }”;}
Gradients: are technically functions, but we’ll discuss them in detail later, in the gradients section.
Color Me Zombie
The next four functions are all about color.
Hsl(): stands for hue, saturation, and lightness. This is the way to manipulate a color that makes the most sense (at least to me). Hue is a number from 0 to 360 and represents degrees on the color wheel. For instance, red is at 0/360, green is at 120 degrees, and blue is at 240. The rest of the colors are somewhere in between those numbers on the color wheel.
Saturation determines how much of the color is in the final color. Values run from 0% to 100%, with 0% being some version of gray, depending on what lightness is set to. 100% is full saturation (i.e., as much of the color you can put into it).
Lightness also runs from 0% to 100%. 0% is full black, no matter what hue and saturation are set to, and 100% is full white, no matter what hue and saturation are set to.
.zombie-colors { color: hsl(80, 61%, 50%);}
Hsla(): is the same as hsl(), except it includes a fourth value for alpha (better known as transparency). Valid values are between 0 and 1.
.zombie-colors-alpha { color: hsla(80, 61%, 50%,0.5);}
Using a somewhat transparent color for a background of a text block can add texture and visual interest to a design, as long as it doesn't make the text hard to read. Hsla() or rgba() (discussed in a moment) are the best choices for this effect. The opacity property and the opacity filter that we'll discuss later in this book would make the text transparent too.
Rgb(): Another way to define a color in a projected medium is by giving amounts of red, green and blue light. Rgb() uses three decimal values, each between 0 and 255, to define a color. All 0s is black, and all 255s is white.
.zombie-colors-rgb { color: rgb(154, 205, 50);}
Rgba(): is the same as rgb(), except it includes a fourth value for alpha like hsla(). Valid values are between 0 and 1.
.zombie-colors-rgb-alpha { color: rgb(154, 205, 50, 0.5);}
Night of the living tip
In a recent update to the specification, both hsl() and rgb() were changed so that they could take four values, making hsla() and rgba() unnecessary. That said, as of this writing, browser support is spotty, so check support before you use four value hsl()/rgb() in production.
Codepen Demo:
Var(): This is an essential part of custom properties, so we’ll go over it in more detail in the next section. The var() function takes the custom property as an input when you use it.
.zombie-colors { background-color: var( --zombieBobsFavoriteColor)}
Counter() and Counters(): allow you to print out a counter’s value. We’ll discuss these in depth in the Counters section.
The Effortlessly Variable Zombies
CSS Custom Properties operate very similarly to what would be called variables in any other programming language. Custom property names start with two dashes and can hold any valid property value. They are particularly good for setting all your colors or default sizes in one location, allowing you to make one change that will cascade through the rest of the site. What happens when your Zombie Boss decides the shade of green is just too “mehhhhh”? Make the change in one place, and watch the new color ripple through the site like a zombie contagion rippling through humanity. (Okay, it probably happens too quickly to watch the ripple, but you get the idea.) It’s also a good way to avoid writing long or complex numbers over and over and over again.
Scope is an important concept here. Scope is a shorthand way of saying where a variable can be used. Where you set the variable (i.e., on what selector you set it) will determine where that custom property can be applied. If you set it using html or body or :root as the selector, you can use it pretty much anywhere on the page because all elements are children of those elements. But if you set the custom property using a more specific selector, it will be scoped (only work) on that selector and the child elements of that selector.
To set a custom property, you name it, using double dashes before your custom property name, and then give it a value, just as you would with any other property.
:root { --zombie-color: yellowgreen;}
To use the custom property within your code, put the variable name in the var function.
.zombie-face{ background-color: var( --zombie-color );}
Codepen Demo:
Counting the Horde
CSS counters were early forms of variables in CSS, but they were only good for counting. As such, they were great for helping you count things that weren’t in an ordered list but you still needed to count (e.g., sections in a document, links on a page, or zombies in the horde coming after you)—but not a lot else, which is why custom properties exist.
Counter-set: creates a counter if one with that name doesn’t already exist. It can take two values: the name of the counter and the starting value. The starting value is optional (it defaults to a starting value of zero).
.counting-zombies { counter-set: number-of-zombies 75;}
You can also set multiple counters in one statement by separating each counter and beginning value pair with a space.
.counting-zombies { counter-set: number-of-zombies 75 number-of-humans 10;}
Counter-reset: sets or resets the counter. Like counter-set, you can also reset multiple counter values by using a space-separated list.
.counting-zombies { counter-reset: number-of-humans;}
Counter-increment: coincidentally enough, increments the counter. It can also take two values. First, it takes the name of a counter, and, second, it takes the amount to increment (or if you put in a negative number, the amount to decrement).
.zombie-plague-infection { counter-increment: number-of-zombies 1 number-of-humans -1;}
Counters use the content property and either the counter() or counters() functions to display the counter value.
Counter(): displays the counter’s current value, hence the name.
.zombie-counter::after { content: counter( number-of-zombies );}
This function only returns the counter for this particular element. It will not return a counter that has been set for other elements of the same type or sub elements of the same type.
Counters() takes two values. It will return all the counters of that name. If you reset counters at every ol in an ordered list with multiple levels, there will be a counter for each level, and it will return all of these. Counters() takes a name and a string. The name is the name of the counter, and the string is the separator between the values of each level of counter. In this way, you can create a numbering scheme in an outline, such as, for example, 2.3.5 to delineate the fifth item in the third section of the second chapter, and so on.
.hordes-and-zombies-counter::after { content: counters( number-of-zombies, “.” );}
Codepen Demo:
Night of the living tip:
There’s a version of counter() that takes two values, and a version of counters() that takes three values. In both cases, the additional value allows you to set your own style of counter. As of this writing, though, those versions only work in Firefox, so only use them when Firefox is your audience’s zombie weapon of choice.
Zombie Blend(er) Modes
There are two ways to do blend modes in CSS. The first, and best supported, is the background-blend-mode property. You can use this to blend a background color and image or to blend multiple images together.
Before we get into blend modes, we need to lay down a few terms and concepts. Blend modes require two “layers”: one thing/image/color on the top, and one thing/image/color on the bottom. If you’re familiar with layers in Photoshop, GIMP, or another graphics editor, then you already understand these types of layers.
The lightness of each pixel on a layer is represented mathematically on a spectrum between full black, at 0, and full white, at 1. Blend modes combine the numbers of each pixel on each layer to create the blended layers. While you can use multiple layers to do blend modes, we’ll simplify it to a top and bottom layer in our discussion. Also the inverse, in our usage below, means 1 – the value in question. Also if math ain’t your strong suit or the below makes you feel like a zombie, feel free to skim this section/look more at the description than the math. I've italicized the parts of the description that are most useful and least mathy.
Practically, you’ll probably need to test a few blend modes before you find the one that gives you the look you want, but having some idea about how they work can help you narrow down the list. Rather than trying every possible substance as a zombie antidote, you can start with a set of things that are more likely to work, and save time.
Background-blend-mode
The possible values of background-blend-mode are:
Multiply: does exactly what it says and multiplies the two numbers (the top and bottom layer) together. Since both values will be less than one (unless they are full white), the result of their multiplication will be lower, closer to zero and, thus, closer to black.
.zombie1 { background-blend-mode: multiply;}top layer * bottom layer = result
Screen: has the opposite effect, although it’s mathematically different. The values are inverted, then multiplied, and then inverted again. This makes the resulting pixel closer to one and, thus, lighter.
( 1 – ( ( 1 – top layer) * ( 1 – bottom layer ) ) ) = result
Overlay: combines multiply and screen. When the bottom layer is above 0.5 (middle gray), it uses screen, and when the bottom layer is below 0.5, it uses multiply. If it’s equal to 0.5, the algorithm does nothing. This has the effect of making dark areas of the bottom layer darker and light areas of the bottom layer lighter.
If ( bottom layer > 0.5 ) then ( 1 – ( ( 1 – top layer) * ( 1 – bottom layer ) ) ) = resultIf ( bottom layer < 0.5 ) then ( top layer * bottom layer ) = result
Darken: compares the values of the layers and keeps the lowest value for the resulting pixel, darkening the overall result.
If ( top layer < bottom layer ) then top layer = resultIf ( top layer > bottom layer ) then bottom layer = result
Lighten: opposite of darken, it compares the values and keeps the highest for the resulting pixel, lightening the resulting image.
If ( top layer > bottom layer ) then top layer = resultIf ( top layer < bottom layer ) then bottom layer = result
Color-dodge: first invert the top layer, then divide the bottom layer by it. W hen the top layer is brighter, the result is brighter. When the top layer is darker it still lightens the bottom layer, but the effect is of smaller magnitude.
bottom layer / ( 1 – top layer ) = result
Color-burn: first invert the bottom layer. Next divide that by the top layer. Finally invert the result. This process makes the result darker in proportion to how dark the bottom layer is.
( 1 – ( ( 1 – bottom layer ) / top layer ) ) = result
Hard-light: uses the same algorithm as overlay, except it uses the top layer instead of the bottom layer to determine whether to use multiply or screen. This has the effect of making dark areas of the top layer darker and light areas of the top layer lighter
If ( top layer > 0.5 ) then ( 1 – ( 1 – top layer) * ( 1 – bottom layer ) ) = resultIf ( top layer < 0.5 ) then ( top layer * bottom layer ) = result
Soft-light: is as similar to hard-light as a zombie apocalypse is to a nuclear apocalypse: pretty much just have the name. Soft-light is most like overlay and uses a linear interpolation of multiply and screen to produce a result. The formulas may vary between programs (e.g., photoshop vs. GIMP vs. other graphics programs) but should be fairly consistent across browsers.
Difference: subtracts the larger layer number from the smaller layer number, making it overall darker.
If ( top layer > bottom layer ) then ( top layer - bottom layer ) = resultIf ( top layer < bottom layer) then ( bottom layer - top layer ) = result
Exclusion: very similar to difference, but the resulting image has lower contrast than difference’s result.
All the Colors of the Zombie
The next four blend modes work differently than the ones above and aren’t based on the same kind of math we’ve been using thus far. They are based on a different calculation of color involving hue, chroma, and luma (which is similar to, but different from the hsl—hue, saturation, and lightness—that we talked about earlier. That said, for our purposes, the differences are relatively minor, so you can approximate chroma as saturation and luma as lightness.)
Hue: keeps the bottom layer’s luma and chroma and takes the top layer’s hue.
Saturation: keeps the bottom layer’s hue and luma but takes the chroma of the top layer.
Color: keeps the luma of the bottom layer and takes the chroma and hue of the top layer.
Luminosity: keeps the bottom layer’s hue and chroma and the top layer’s luma.
You can reset background-blend-mode using the keyword: none.
Mix-blend mode
The second way to use blend modes is the mix-blend mode property. Mix-blend mode is well supported, but not quite as deeply as background-blend mode. It uses the same blend modes laid out above but allows you to mix different elements together rather than just an element’s background. This is particularly great for creating text effects that wouldn’t be possible with background images/colors.
Codepen Demo:
Filtering the Undead
Blends aren’t the only changes you can make to images while the hordes are attacking. You can also use CSS filters. The filter property allows you to make graphic changes to the color and style of images, backgrounds, and so on.
Filter Functions
Blur(): lets you blur an element/image/border. It takes one length value for the blur radius, but, unlike the local post-apocalyptic auction house, it will not take a percentage.
.zombie1 { filter: blur(10px);}
Brightness(): allows you to adjust the brightness of an image. A value of 0 or 0% makes the image black, while 1 or 100% will keep the image the same. Values over 1 or 100% will make the image lighter or brighter. Values above 1000% will remind you of pictures from the government’s ill-advised nuclear strike on the Wisconsin Cow Horde.
.zombie2 { filter: brightness(150%);}
Contrast(): allows you to adjust the contrast. A value of 0 or 0% will make the image full zombie—errr...full gray. A value of 1 or 100% makes no change to the image, and a value above 1 or 100% will increase contrast.
.zombie3 { filter: contrast(150%);}
Drop-shadow(): this is largely the same as the box-shadow property discussed later in this book. It has the added advantage of sometimes having hardware acceleration (depending on your browser and your device). If you use box-shadow once or only a few times, it shouldn’t matter much, but if you use a whole horde of them or plan to animate them, you should probably switch over to filter: drop-shadow(). Box-shadow and drop-shadow() use the same syntax. The first two values are the x and y offsets respectively. Next is the blur radius (optional), followed by an optional color value.
.zombie4 { filter: drop-shadow(15px 15px 5px greenyellow);}
Night of the living tip:
One important distinction in the syntax between drop-shadow and box-shadow is how to do multiple shadows. In drop-shadow you need to repeat the drop-shadow function for each shadow you add to the element. Box-shadow allows you to just add a comma.
.zombie4a { filter: drop-shadow(15px 15px 5px greenyellow) drop-shadow(-15px -15px 5px greenyellow);}.zombie4b { box-shadow: 15px 15px 5px greenyellow, -15px -15px 5px greenyellow;}
Grayscale(): converts the image to grayscale, matching your marriage prospects after the apocalypse. Values for the effect run from 0 or 0% to 1 or 100%. 0% leaves the image unaffected, while 100% is full grayscale.
.zombie5 { filter: grayscale(80%);}
Hue-rotate(): rotates the hue of the image around the color wheel. Hue-rotate values are given in angles or degrees. 0 leaves the image unchanged, as does 360. All changes repeat every 360 degrees.
.zombie6 { filter: hue-rotate(90deg);}
Invert(): inverts the colors of the image, kind of like how zombies inverted the color and intelligence and wonder of the human race. Values of 1 or 100% mean the image is fully inverted. Values of 0 or 0% leave the image unchanged. Values in between apply the effect to varying degrees.
.zombie7 { filter: invert(0.80);}
Opacity(): similar to the opacity property, this changes how see-through the image is. Values go from 0 or 0% to 1 or 100%. 0 means the image is fully see through, and 1 means the image is fully opaque (no change). Using filter opacity over the regular opacity property will provide hardware acceleration in certain browsers/devices.
.zombie8 { filter: opacity(0.5);}
Saturate(): plays with the saturation of the colors in the image. 0 or 0% completely desaturates the image, and 1 or 100% leaves the image unchanged. Values over 1 or 100% will supersaturate the image, increasing the vibrancy, while also decreasing the natural look of the photo. It’s kind of like how the zombie plague would desaturate people, taking them from 100% to zero, but when zombies try to infiltrate humanity, they skip right past 100% saturation and go straight to 350% saturation. Clearly these spies aren’t like zombies, but they’re also way unnatural.
.zombie9 { filter: saturate(350%);}
Sepia(): takes the input image and changes it to sepia tone (i.e., how everything looks after the apocalypse: amber shades of gray). 0 or 0% has no effect, but 1 or 100% is full sepia tone.
.zombie10 { filter: sepia(80%);}
Codepen Demo:
SVG filters: You can use SVG filters with the filter property by using the url() function and the path to the SVG filter.
You can also stack filters on top of each other—just separate each function with a space.
Gradated Zombies
Gradients allow you to create a slow (or sometimes fast) transition between two or more colors. CSS treats them as if they were images so, for example, you can add them to background-image but not to background-color. Typically, a gradient has no intrinsic length or dimension. It fills the element in which you place it. (If you need a repeating gradient, you can use the repeating gradient functions. We’ll discuss those functions shortly.)
Linear-gradient: can take a number of arguments. First, you can optionally set an angle along which the gradient will run. Next, after a comma, you can set color and percentage pairs (space separated) to mark the color stops of the gradient. You should have at least two stops.
.zombie1 { background-image: linear-gradient( 20deg, #960B0B, yellowgreen);}.zombie1a { background-image: linear-gradient( 40deg, #960B0B, black 30%, yellowgreen);}
You can also use keywords instead of angles to tell the gradient which direction to use. You can use the word “to” in combination with top, right, bottom, or left to angle the gradient towards any side or use two words in combination to angle the gradient toward a corner. For example: to bottom left.
.zombie1b { background-image: linear-gradient( to top, #960B0B, black 30%, yellowgreen);}.zombie1c { background-image: linear-gradient( to bottom left, #960B0B, black 30%, yellowgreen);}
Radial-gradient s: are defined by the location of the center, the outside shape, and one or more color stops.
.zombie2 { background-image: radial-gradient( #960B0B, black, yellowgreen);}
To define the location of the center of the gradient, you can use the same keywords you’d use with background-position or transform-origin. Radial gradients can either be a circle (constant radius) or an ellipse (different horizontal and vertical radii).
.zombie2a { background-image: radial-gradient( circle at right top, #960B0B, black, yellowgreen);}.zombie2b { background-image: radial-gradient( circle at left bottom, #960B0B, black, yellowgreen);}.zombie3 { background-image: radial-gradient( ellipse at 50% 20%, #960B0B, yellowgreen);}
You can then set color stops using a color and a percentage. The percentage is optional and will use the midpoint between two colors as the transition spot. Percentages are used for the color stops so that they can apply to any element you place them in, no matter the size.
There are also four keywords that can be used to set the extent or size of a radial gradient:
Closest-side: For circles, the edge of the gradient meets the side of the containing element closest to its center. For ellipses, it’s the closest vertical and horizontal sides.
.zombie4 { background-image: radial-gradient( closest-side at 30% 30%, black, #960B0B);}
Closest-corner: the gradient is sized so that it meets the closest corner of the containing element.
.zombie5 { background-image: radial-gradient( closest-corner at 30% 30%, black, #960B0B);}
Farthest-side: similar to closest side, except it is sized to meet the element side that is farthest from the gradient’s center.
.zombie6 { background-image: radial-gradient( farthest-side at 30% 30%, black, #960B0B);}
Farthest-corner: You guessed it, it’s the same as closest corner, except it’s sized to meet the corner farthest from the gradient’s center.
.zombie7 { background-image: radial-gradient( farthest-corner at 30% 30%, black, #960B0B);}
Repeating-linear-gradient: exactly the same as the linear gradient and takes the same arguments, except it accepts color stop distances in other units. The gradient is repeated to cover the entire background.
.zombie8 { background-image: repeating-linear-gradient( 40deg, #960B0B 10px, black 20px, yellowgreen 30px);}
Repeating-radial-gradient: is the same as the radial gradient and takes the same arguments, but it repeats the gradient. Color stops can take a length instead of just a percentage.
.zombie9 { background-image: repeating-radial-gradient( #960B0B 1px, black 20px, yellowgreen 30px);}
Codepen Demo:
While hand coding your own gradients is pretty awesome and can give you serious apocalyptic street cred, using one of the many CSS gradient generators is also possible (and recommended over puling your hair out over a complicated implementation).
Night of the living tip:
As of this writing (March 2020) Firefox is the last holdout that has not yet implemented a new kind of gradient: the conic gradient. They are similar to a combination of linear and radial gradients. They start at a point with a color at an angle and end with a different color at a different angle.
Zombies Breaking Words
Word-spacing: lets you set the distance between words.
.zombie1 { word-spacing: 8px;}
Letter-spacing: lets you set the distance between letters. It’s like kerning, but it sets all distances at once.
.zombie2 { letter-spacing: 3px;}
Night of the living tip:
You should use word and letter spacing rarely and intentionally. Fonts generally have built-in kerning for most situations, but there will be times when you need to make adjustments. This will often be for headings and larger text as opposed to body copy. For instance, if you create a headline in all caps, adding a little letter-spacing can make it more readable.
White-space: is used to change how white space is handled. White space is typically collapsed into a single space, no matter how many spaces or line breaks exist. Possible values are:
Normal: default behavior. New lines, spaces, and tabs are all collapsed.
Nowrap: same as normal (spaces, tabs, and new lines are collapsed), except the text never wraps. It continues in the same direction as originally set and goes beyond the boundaries of its containing element (assuming the CSS overflow property isn’t applied).
.zombie3 { white-space: nowrap;}
Pre: keeps all white space intact.
.zombie4 { white-space: pre;}
Pre-wrap: keeps all white space intact, but wraps lines when they reach the edge of the containing element.
.zombie5 { white-space: pre-wrap;}
Pre-line: collapses white space and wraps content but keeps new line characters.
.zombie6 { white-space: pre-line;}
Night of the living tip:
For reasons I cannot explain, if you look at any of the “pre”-flavored keywords in codepen, they will operate like pre-line, keeping new lines and collapsing other white space. They should work properly if you use the HTML files.
Overflow-wrap: allows you to break words that are too long to fit in their containers. Microsoft originally implemented this as word-wrap. When the standards group adopted it, they renamed it overflow-wrap.
Normal: default. Does not break any long words.
Break-word: will break long words—those that are too big for their containers—into smaller pieces so that they can be contained within their parent elements.
.zombie7 { overflow-wrap: break-word;}
Word-break: determines where, when, and if a word is broken into multiple pieces.
Normal: default. Use default line-breaking options.
Break-all: word breaks can happen between any two letters to prevent overflow and occur whenever a word would overflow the wrapper, even if putting the word on the next line would also solve the overflow issue.
.zombie8 { word-break: break-all;}
Hyphens: specifies how hyphenation happens in your content.
None: default. No hyphens will be added.
Auto: the browser makes the call on where hyphens will be placed. You can override this by manually including a hyphen or by adding the HTML entity to the text you want hyphenated. ( does not visibly show until the browser breaks the word at that spot.)
.zombie { hyphens: auto;}
Manual: words are broken only when a ‐ or suggests a hyphen.
.zombie { hyphens: manual;}
Text-overflow: determines how or whether text can overflow its container. Possible values are none (the default), which lets it overflow; clip, which cuts the text off; and ellipsis, which adds an ellipsis at the end. Both white-space: nowrap and overflow: hidden are required for text-overflow to work.
.zombie9 { text-overflow: clip; white-space: nowrap; overflow: hidden;}.zombie10 { text-overflow: ellipsis; white-space: nowrap; overflow: hidden;}
Codepen Demo:
At-Rules for the At-pocalypse
@charset: tells the browser what character set the CSS file is using. (It's not a requirement, but can help make it clear to the browser what character set is in use.)
@charset “utf-8”;
@import: allows you to import another CSS style sheet into your current style sheet. You can also use a media query after the file name to determine when or how the file is imported (i.e., as a print stylesheet or a screen stylesheet, etc.). Use imports sparingly, as an over abundance of @imports can negatively affect performance.
@import url(zombie.css) screen;
@supports: shows or uses certain CSS code only when the browser supports the feature. In this way, we can progressively enhance a page. For example, if the page supports flexbox layout, then you can use it. If not, you can fall back to floats or another layout style. You can also use logical operators (and, or, not) to test for multiple conditions or, in the case of not, for when something is not supported.
Note: The example below changes the color in order to make the change visible. Typically, you would test if display: flex was supported and determine your layout by that support. For instance, if flex box is supported, you’d probably use it. If it’s not supported, you would approximate the flex box layout with a floated layout.
@supports(display: flex) { .zombie7 { background-color: blue; }}
@supports not (display: flex) { .zombie7 { background-color: purple; }}
Codepen Demo:
Zombie Fit-ness
Just as you can change how a background image appears within its containing element, you can also do that with replaced elements, such as img and video.
Object-fit: determines how the image will be displayed (i.e., what algorithm is used to display the image).
Fill: fills the space regardless of whether that squashes or stretches the image. This is the default.
Contain: similar to background-size: contain. This retains the image’s aspect ratio and sizes the image so that it fully fits within the window.
Cover: same as background-size: cover. This retains the image’s aspect ratio and sizes the image so that the image covers the entire area.
None: the image is not resized in any way.
Scale-down: image is sized as if either none or contain were used, whichever results in the smallest size.
.zombie img { object-fit: cover;}
Object-position: determines how the replaced image is positioned in the element in the same way that a background image is positioned.
.zombie7 img { object-fit: none; object-position: right top;}
Codepen Demo:
Zombie Potpourri
Box-shadow: creates a drop shadow on any element. It's also smart enough to know if you are using border-radius (discussed next) to modify the shape so that you can make round shadows as well. It takes four values just like drop-shadow(): x offset, y offset, blur radius and color.
.zombie1 { box-shadow: 5px 7px 3px #567134;}
You can also use the keyword inset to make the shadow appear inside the element.
.zombie1a { box-shadow: inset 5px 7px 3px #567134;}
Border-radius: allows you to easily round off the corners of any square or rectangular element.
.zombie2 { border-radius: 1em;}
You can also create a circle, by using a border-radius of 50%.
.zombie3 { border-radius: 50%;}
Caret-color: allows you to change the color of the caret (i.e., the insertion cursor that blinks to show where the next letter you type will go). This is usually seen in inputs, text areas, and any element with the content editable attribute set.
.zombie4 { caret-color: #960B0B;}
Pointer-events: Sometimes you need to disable an element so it won’t interfere with a tap or a click, either because it’s between the user and the click target or because you need to handle the interaction differently. For this, set pointer-events to none. The click will then pass through the element, allowing the user to click something below it. This property should be used sparingly and never in a way that prevents the user from pursuing a valid choice on your website. Pointer-events: auto will bring mouse clicks and finger taps back.
.coveringzombie { pointer-events: none;}
Cursor: Similar to above, you may have times when you make an element work differently than the default. One way to help users recognize that difference (e.g., so that they don’t mistake a zombie nest for a human fort) is by changing the cursor/mouse image so that it matches the action you want them to take. This may also be useful if you are creating an action that happens regularly within the operating system so that people understand what the cursor image refers to, but doesn’t often happen in the browser such as copy or zoom.
.undead-cursor { cursor: pointer;}
You can also supply your own cursor image and a comma separated list or other images or cursor keywords for a fallback.
.zombie-cursor { Cursor: url(zombie.png), url(zombie-head.png), zoom;}
Codepen Demo:
Until Z Meet Again
Thanks for following me on this second tour of CSS zombie-fighting weapons. You should now have the knowledge you need to end a zombie wherever you come across it. You know how to filter, blend, and function a zombie in the throat. You can count them, gradient them, and object-fit them into the undead afterlife, and so much more. Go forth, and use your skills wisely; the post-apocalyptic world awaits your brilliance!
Testing Your Zombie Patience
Let’s make sure you’re geared up for that zombie fight you’re about to step into before you end up throwing a filter: blur() when you meant to unleash @supports. Complete the following zombie destruction steps. The provided codepen is a skeleton from which to start https://codepen.io/undeadinstitute/pen/poJympZ?editors=1100#0 or grab the skeleton as an html file from https://undead.institute/files/gown/012-belle-of-the-zombie-ball.html
- Use a counter to count the section tags.
- Apply a blend mode to the header picture.
- Set the object-fit so that the full image in the header is shown without being squashed or stretched.
- Apply a filter or two to the black and white illustration.
- Add a repeating gradient background of at least four colors to the page.
- Set the letter-spacing on the title heading.
- Calculate the width of the content element, using the width of the parent and subtracting 50vw.
- Create a custom property whose value is a half-opaque color, using hue, saturation, and lightness values. Use the custom property to set the background color of the heading title.
- Create a circle CSS shape using the “circle” div and set it so that the text flows around the div on the right side.
- Change the border-radius of the summary element and add a drop-shadow.
Work through these on your own. Your solutions can—and probably should—vary from mine, but here’s how I completed the steps above: https://codepen.io/undeadinstitute/pen/YzXWeVP?editors=1100 or https://undead.institute/files/gown/013-belle-of-the-zombie-ball-answers.html.
Got Questions?
Join the Undead Institute Facebook group and get answers. https://www.facebook.com/groups/490540551375786/
You Know what else kills Zombies?
Honest reviews. Please consider leaving one to help the fight against the apocalypse.
I’d also love to see where and how you’re reading or using the book. Twit me a pic at @storykaboom and/or use the hashtag #GetBraaains