Year #2, Week #9 đ» đ
New stuff we learned this week: đ€
Webfonts
- the font you specify in a CSS
font-family
declaration will only be visible to the user if they have that font installed on their system. Sadly, there are only a few fonts that are reliably found on nearly all computers. These fonts are generally referred to as web-safe fonts. They are safe for the web because they will be available for almost everybody. - the web-safe fonts are (approximately):
- âArialâ (sans-serif)
- âArial Blackâ (sans-serif)
- âVerdanaâ (sans-serif)
- âTahomaâ (sans-serif)
- âTrebuchet MSâ (sans-serif)
- âImpactâ (sans-serif)
- âTimes New Romanâ (serif)
- âDidotâ (serif)
- âGeorgiaâ (serif)
- âAmerican Typewriterâ (serif)
- âAndalĂ© Monoâ (monospace)
- âCourierâ (monospace)
- âLucida Consoleâ (monospace)
- âMonacoâ (monospace)
- âBradley Handâ (cursive)
- âBrush Script MTâ (cursive)
- âLuminariâ (fantasy)
- âComic Sans MSâ (cursive)
- One way to deal with the fact that a user might not have a font installed on their system is by using the concept of fallback fonts â that is, specifying a list of fonts in a CSS declaration:
html {
font-family: Baskerville, "Times New Roman", serif;
}
- from the above code, if the user doesnât have
Baskerville
(which generally only Mac users do), they will getTimes New Roman
â also a serif font. Sometimes this is good enough. - however, because many web designers really wanted to be able to design their
pages with specific fonts, eventually a standard called Web fonts emerged.
It works like this: first you declare a
font-face
in your css like this:
@font-face {
font-family: "Goat Banjo Rodeo";
src: url("goatBanjoRodeo.woff");
}
- a
font-face
declaration is comprised of a name for the font (line 2 above), and one or more sources for a font-file for that font. The most common and modern source format is a.woff
file, however, not all older browsers support that format, so you can supply a number of different sources, letting the browser choose which one they understand, like this:
@font-face {
font-family: "Goat Banjo Rodeo";
src: url("fonts/gbr.eot");
src: url("fonts/gbr-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/gbr-webfont.woff2")
format("woff2"), url("fonts/gbr-webfont.woff") format("woff"), url("fonts/gbr-webfont.ttf")
format("truetype"), url("fonts/gbr-webfont.svg#gbf") format("svg");
font-weight: normal;
font-style: normal;
}
classnames npm package
- itâs very common in react to be applying a number of classes to an item, often
with variables (from css modules) or conditionally based on some state. This
can lead to some ugly-looking junk trying to set the
className
prop of components:
const Block: React.FC = () => {
const [ok, setOk] = useState(false);
return (
// this next line is yucky
<div className={`${style.wrap}${ok ? " ok" : ""}`}>
<h1>Howdy</h1>
<p>Partner</p>
</div>
);
};
- the npm classnames package is a widely-used solution to this problem. It gives you a bunch of flexibility for passing values to it, and always produces a nice string of space-separated css classes:
import classnames from "classnames";
// pass it plain old strings:
classnames("foo", "bar");
// -> "foo bar"
// or an array of strings:
classnames(["foo", "bar"]);
// -> "foo bar"
// it pitches falsy things and non-empty strings:
classnames(undefined, null, false, "", "foo");
// -> "foo"
// good for CONDITIONALLY adding a class:
let isOpen = true;
let isBlue = false;
classnames("menu", isOpen && "open", isBlue && "blue");
// -> "menu open"
// also accepts object syntax where KEYS are the classnames
// and VALUES are booleans controlling if class is added
// so we could rewrite the above example as:
classnames("menu", {
open: isOpen,
blue: isBlue,
});
// -> "menu open"
// you can MIX AND MATCH all the ways of passing args:
classnames(["foo"], "bar", null, { lol: true });
// -> "foo bar lol"
CSS Transitions
- by default, when certain CSS values change dynamically, the browser renders the change instantaneously. Consider this CSS:
a {
color: red;
}
a:hover {
color: blue;
}
- when a user hovers over an
<a>
tag, the color will instantly change to blue. But if we wanted the transition to blue slowly, we could indicate that by addingtransition-<x>
properties, like so:
a {
color: red;
transition-duration: 200ms; /* LENGTH of transition */
transition-property: color; /* WHAT to transition */
transition-timing-function: linear; /* SHAPE of trans. */
transition-delay: 100ms; /* DELAY before transition */
}
a:hover {
color: blue;
}
- examples of
transition-timing-function
includelinear
,ease
,ease-in
,ease-out
,ease-in-out
, and more⊠- some css properties can not be transitioned â and itâs fairly intuitive
to figure out which ones those are. If there is no way to mathematically
calculate intermediate states, then it probably canât be transitioned. For
instance, moving from
display: none
todisplay: flex
is not transitionable, because there is no way to smoothly transition from one to another. But you can transition fromopacity: 0
toopacity: 1
to achieve a âfade-inâ effect.
Typescript: Type âNarrowingâ
- Typescript can NARROW types inside of conditional statements.
- Study this code block, reading the comments, until it makes sense.
type MyUnion = string | boolean | Array<string>;
function takesUnion(val: MyUnion) {
// on this line TS only knows that `val` is
// one of 3 things: string, boolean, or array of strings
if (Array.isArray(val)) {
// inside these rabbit ears
// đ TS KNOWS that `val` must be `Array<string>`
// so you can safely do:
val.forEach((item) => console.log(item));
} else if (typeof val === "string") {
// đ in here TS KNOWS that `val` is a string!
// so this works and typechecks!
val.toLowerCase();
} else {
// đ and in here TS KNOWS `val` must be a boolean!
let x: boolean = val; // OK â
}
}
Useful Links:
Homework Plan
𩠠A bit lighter on homework this week because of Thanksgiving. But make sure to do FOUR separate days of Execute Program!
- 1 day review all flashcards (in your app)
- 1 day Flashcard App assignment
- 1 day classnames assignment
- 1 day touch typing practice
- 1 day touch watch CSS Transitions video
- 4 days Execute Program homework
Flashcard App Homework
- Slowly and carefully review the âNew Stuffâ above ^^^.
- Watch the CSS Transitions Video first.
- Merge your MR from last week, switch to master, pull changes from
origin
, delete your branch from last week, and make a new branch. - Integrate 2 webfonts from Google Fonts into your Flashcards app.
- commit your work.
- Add 2 CSS Transitions to your Flashcards app â but no using the
transition:
shorthand property! Use the longer-formtransition-<x>
format. Shorthands are (almost always) evil! - commit your work.
- add 5 new
css
cards:@font-face
transition-duration
transition-property
transition-timing-function
transition-delay
- add 15 new cards from your old physical/digital location.
- commit your work.
- build your site, push up a MR, put links in Slack.
Classnames Homework
- Slowly and carefully review the âclassnamesâ section and the âtype narrowingâ section in New Stuff above ^^^.
- visit this url, copy the git clone url, clone the repo and open up the cloned repo through vscode.
- install the dependencies
- create a new branch
- read ALL the rest of these instructions before getting started!
- run the test with
npm run test
ornpm run test:watch
(for watch mode) - one by one get the tests passing, changing the next
xit()
toit()
one by one. - hints/clarifications:
- the real
classnames
package takes variadic arguments, meaning, it can take as many arguments as you pass it. I havenât taught you how to do that in JS yet, so for this assignment, weâre limiting the function to take 1 - 3 arguments. I already created the function signature types for you, and made the last two arguments optional by using the?
char. You will have to slowly morph theInput
type, making it a Union of all the things that the function can accept. - because the function takes up to 3 arguments, each of which can be all of
the same things, you might find itâs helpful to create a helper function,
something like
handleSingleArgument()
and then call it 3 times, using it somehow to build up the final output of the function. - you might want to review some of the Array functions from here.
- you can use the function
Array.isArray(x)
to test if something is an array. Donât usetypeof
because it returnsobject
for arrays. - if you have a Union type in typescript, something like
type Foo = string | boolean;
you can test the type using various tricks (like thetypeof
operator andArray.isArray()
). Typescript is smart enough to narrow the type inside anif
block. - if you havenât read the âType Narrowingâ section above including watching the video I made (linked above) â stop and do that now. It will be very helpful for this assignment.
- the real
- commit your work when you finish, submit a MR, slack the MR url.