STEP BY STEP GUIDE CSS in 44 minuteshipermedios.gilbertoleon.io/css_in_44_minutes.pdf · the...
Transcript of STEP BY STEP GUIDE CSS in 44 minuteshipermedios.gilbertoleon.io/css_in_44_minutes.pdf · the...
Build your own webpagefrom scratch
Build your own webpagefrom scratch
CSS in44 minutes
CSS in44 minutes
Jeremy ThomasWritten by
S T E P B Y S T E P G U I D E
© Copyright 2018 – Jeremy Thomas
Class TrainingPatricia Pinedo - Web Development Program
1Introduction
Thisbookisastepbystepguidethatwillteachyouhowtobuildthiswebpagefromscratch:
It'sthewebpageofafictionaltechrecruitercalledAlexJefferson.AllimagescomefromUnsplash.Asyou
followthisguide,feelfreetochangethestylesandcontentthewayyouwant.
Whoisthisbookfor
Anyonecanreadthisbook!Nopriorwebdevelopmentorprogrammingknowledgeisrequired,sinceIwill
tellyouwhattodo,linebyline.
Whatyouwillbuild
Thiswebpagewillusethefollowingfiles:
1HTML5file
3CSSfiles
4images(provided)
1JavaScriptfile
Itwillalsomakeuseoftwothirdpartyservices:FontAwesomeandGoogleFonts.
Whatyouwilllearn
Throughthisguide,Iwillteachyouhowto:
SetupavalidHTML5document
Writesemanticmarkup
InsertresponsiveRetina-friendlyimages
LearnhowtostructureyourCSScorrectly
Designa100%responsivepage
Understandhowmediaquerieswork
UseCSSFlexboxtolayoutyourcomponents
Styleyourtextwithtypographyproperties
AddvisualfeedbackwithCSSTransitions
BringyourpagetolifewithCSSAnimations
MakeuseofGoogleFonts
IncludeandstyleFontAwesomeicons
Whatyouneedtostart
Youonlyneedtoinstall2programs:
adecenttexteditororIDEwithsyntaxhighlighting.IrecommendSublimeTextbutyoucanuse
Notepad++,Vim,Emacs,IntelliJ,Atom…
amodernwebbrowser.IuseGoogleChromebutyoucanuseFirefox,Safari,Opera,orEdge.
YoualsoneedafewfilesthatIhaveprovided:
1CSSfile: minireset.min.css
7images:
alex.jpg
austria.jpg
1x.png
2x.png
3x.png
Havethemavailableandreadytobeused.
2WritingtheHTML5content
Openyourtexteditor,createanewfileandpastethiscodesnippet:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Alex Jefferson – Tech Recruiter</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Savethisfileas index.html ,openitinyourbrowser,andyouwillseethefollowingpage:
Makesuretohavethe .html fileextension.Here'showtodoitonWindowsandMacOS.
AvalidandresponsiveHTML5document
ThispageisavalidresponsiveHTML5pagebecauseitsatisfiesthefollowingrequirements.
<!DOCTYPE html>
ThislinetellsthebrowserthatthiswebpageisanHTML5documentandshouldbeinterpretedassuch.
<meta name="viewport" content="width=device-width, initial-scale=1">
Thisistheresponsivemetatag.Ittellsthebrowsertosetthecontentwidthtotheviewportone,ensuring
forthecontenttoadaptautomatically.Italsotellsthebrowsertosetthezoomlevelto1initially,whilestill
allowingtheusertozoomin(especiallyonmobilephones).
Also,eachHTMLtag( <html> , <head> , <body> …)isopenedandclosedintherightorder.Onlythe
<meta> tagsneedtobeself-closing.
AddingtheCSSreset
Beforedesigningyourpage,youwanttostartwithacleancanvas.Sinceeachbrowsercomeswithitsown
defaultstyles,youwanttoremovethemfirst,otherwisethesestyleswillclashwithyours.Thisprocessis
thepurposeofaCSSreset.
Bestpractice
Separatecontentandstyling
YouwanttochooseanHTMLtagforitssemanticmeaning,notitsappearance.
Ifchanginganelement'staginyourHTMLchangesitsappearance,thenyou’reessentiallystylingyour
webpageintheHTML,whichiswhatwewanttoavoid.
MostcurrentCSSresetsareeithercomplicatedoroutdated,soIcreatedasmallonecalledminireset.css.I
useitforallmyprojects,andit'sincludedbydefaultinBulmatoo.
Theonlytworealrequirementsareto:
removethemarginsandpaddingsfromallblockelements
use box-sizing: border-box
Feelfreetoreadthroughthesourcecode.
Alongsideyour index.html file,createa /css folder,andmovethe minireset.min.css fileinit.
Let'slinkourCSSfilefromtheHTMLfile.Justbelowthe <title> ,addthisline:
<title>Alex Jefferson – Tech Recruiter</title>
<link rel="stylesheet" type="text/css" href="css/minireset.min.css">
Thetext "Hello world!" isnowunstyled.
YourownCSS
Inthe /css folder,createanewemptyfilecalled main.css .
YounowhavetoincludethisCSSinyourpage.In index.html ,rightbelowtheminireset,linkyour
main.css file.Younowhave2CSSfiles:
<link rel="stylesheet" type="text/css" href="css/minireset.min.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
ToseeiftheCSSwascorrectlyincluded,addthisto main.css :
html {
background-color: blue;
}
Ifyourscreendoesn'tturnblue,makesureyour index.html fileisalongsideyour /css folder:
TheCSSnowworkssoyoucanremovethebluebackgroundfromtheCSS.BeforewritinganyCSS,you
havetostartwiththemostimportantofawebpage:thecontent.
Writingcontent
Thepurposeofdesignistoenhancethepresentationofthecontentit'sappliedto.Itmightsoundobvious,
butcontentbeingtheprimaryelementofawebsite,itshouldnotbeestablishedasanafterthought.Written
contentmakesupformorethan90%oftheWeb.
Remove "Hello world!" fromyourpage,andputthiscodeinsidethe <body> :
<div class="wallpaper"></div>
<div class="content">
<aside class="side">
<figure class="picture">
<div class="picture-shadow"></div>
<img id="pictureImage" class="picture-image"
src="images/alex.jpg"
srcset="images/alex.jpg 1x,
images/[email protected] 2x,
images/[email protected] 3x"
alt="Portrait of Alex Jefferson"
width="320"
height="320">
</figure>
</aside>
<main class="about">
<h1 class="name">
Hi, I'm Alex Jefferson
</h1>
<p class="job">
Tech recruiter
</p>
<hr class="hr">
<div class="description">
<p>
I spend my time traveling the world,
helping startups and tech businesses
hire the best people.
</p>
</div>
<div class="contact">
<a class="button" href="mailto:[email protected]">
Get in touch
</a>
</div>
</main>
</div>
Asyoucansee,HTMLisnoisy:thereislotscodefornotmuchcontentonscreen.ButalltheseHTMLtags
arehereforsemanticreasons,andalltheseCSSclassnamesareherefor(future)stylingpurposes.
HTMLstructure
The wallpaper willdisplayatransparentimageinthebackground,coveringthewholepage.
The content isthecontainerforthereadablepartofthewebpage,andwillcoverthewholepageaswell.
Ontheright,the side willdisplaytheportraitimage.
Ontheleft,the about sectionisawrapperforalltext.The button actsasalinkforvisitorstoclick,so
makesuretoreplace [email protected] withyourownemailaddress.
ResponsiveandRetina-friendlyimages
Asyoucansee,sincethe alex.jpg imageismissing,thebrowserisshowingthe alt text"Portraitof
AlexJefferson"asafallback.Tofixthis,createan /image folderalongsidethe /css one,andmovethe4
images( alex.jpg , [email protected] , [email protected] and [email protected] )inside:
Wewanttodisplaythisimageatamaximumof 320x320 pixels.Butscreenshavedifferentpixelratios,
especiallymobilephones.Forexample,theSonyXperiaShasapixelratioof 2 ,theAppleiPhoneX 3 ,
andtheSamsungGalaxyS8 4 .
Wecouldshowthe 1280x1280 versiontoeveryoneandresizeitto 320x320 .Butwewouldpenalize
userswhoownadevicewithapixelratioof 1 becausetheywouldendupdownloadinganimage10
timesthesizethattheirdevicecanactuallydisplay.
Thesolutionisto:
showtheuserthehighestqualityimagepossibletheirdevicecansupport
preventthebrowserfromdownloadingtheotherimages
Thisispossiblethankstothe srcset attributewhichtellsthebrowserthelistofimagealternatives
availableforeachpixeldensity,andlethimfigureoutwhichimagetodisplay.
Ifthebrowserdoesn'tsupport srcset ,itwilluse src asafallback.
Thisisallthecontentthatyouneedfornow:
aportraitimage
aname
ajobtitle
adescription
acontactbutton
Thiscontentwillbeextendedfurthermorelater.It'stimetoaddyourfirstlinesofCSS.
3SettingupaCSSbase
Beforestylingindividualelements,youneedtosetaglobalbasestyleforyourwebpage.
Thehtmlstyles
Thegeneralstylingofawebpageisdonethroughstylesappliedtothe html elementbecausemostof
themarecascadedthroughalltheotherchildelements.
Inyourempty main.css file,addthiscode:
/* 1. Base */
html {
background-color: #5f45bb;
background-image: linear-gradient(to bottom right, #180cac, #d054e4);
color: #fff;
font-family: "Quicksand", sans-serif;
font-size: 16px;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
line-height: 1.5;
min-height: 100vh;
min-width: 300px;
overflow-x: hidden;
text-shadow: 0 3px 5px rgba(0, 0, 0, 0.1);
}
Thisrule-setisbasicbutdoesthejob:
the background and color declarationssettheoveralltone
the font and text-shadow setthebasetypography
the line-height andbrowser-specific font-smoothing declarationsmakethepagemorereadable
thedimensionsandoverflowvaluesensurethatthepagefillsupthewholeviewport
Bestpractice
OrderyourCSSrulesalphabetically
WheneditingaCSSfile,findingthedeclarationtochangecanbetimeconsuming.
Toreducethecognitiveloadwhenbothreadingandwritingrules,writethemalphabetically.
It'stheonlysortingrulethatisfuture-proofbecauseit'sopinionless.
Whenyouwillhavemorethan10CSSdeclarationsinarule,youwillbegladtoknowwheretofindwhatyou
werelookingforinasplitsecond!
The background-color usuallyactsasafallbackifthe background-image doesn'tload,butsincewe're
usinga linear-gradient() itwillalmostalwaysappear.Thisgradientappearsontopofthesingle-
coloredbackground,hencewhyweonlyseethegradient.
Thefont-familypropertytakesalistofpossiblefamilies.IftheQuicksandfontisnotavailable,thebrowser
willusethefallbackfontprovided: sans-serif .ThisusuallymeansArialorHelveticaonWindows
machines,SanFranciscoonMacOS,andUbuntuonLinuxmachines.Sinceyourvisitorswillprobablynot
havethatfont,wewillincludeitusingGoogleFonts.
The line-height hasaunitlessvalueof 1.5 .Itmeanseachlineoftextwillbe1.5timestheelement's
currentfontsize.Formostofthepage,andcombinedwiththe font-size: 16px declaration,thiswill
makeeachlineoftext 24px high.
Ialwayshavea min-width: 300px thatpreventsthepagefrombeingtoonarrowtobereadable.
The min-height: 100vh ensuresthepagetobeatleastastallas100%oftheviewportheight( vh ).
The overflow-x: hidden declarationpreventsthepagefromscrollinghorizontallywhilepreservingthe
usualverticalscroll.
AddingtheGooglefonts
In index.html ,beforeincluding minireset.min.css ,addthisCSSfromGoogleFonts.Younowhave3
CSSfiles:
<link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/minireset.min.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
Thisaddstwofontstoyourpage:QuicksandandMontserrat,bothinregularfontweightonly(valueof
400 ).Reloadthepagetoseethefontsinaction:
Stylinglinks
Linksarebydefaultblueandunderlined.AddthisinyourCSS:
a {
color: currentColor;
cursor: pointer;
text-decoration: none;
}
Using currentColor ispreferedbecauseitwillpickupthecolorsetby html before: color: #fff .
Updatingthecolorofbothonlyrequiresasinglelinechange.
Sometimes,thehandcursordoesn'tshowupwhenhoveringalink.That'swhyIalwaysadd cursor:
pointer toforcethehandtoshowup.
"Getintouch"isnowwhiteaswell:
4Definingthelayout
Thewallpaper
Attheendof main.css addthissnippet:
/* 2. Shared */
.wallpaper {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
Thisisthe 2. Shared sectionoftheCSS.Here,differentselectorswillsharethesamesetofrules.Wewill
extendthissectionasweneedalongtheway.
Fornow,thisruleensuresthatthewallpapercoversthewholepage.
Wenowenterthe 3. Specific sectionwherewewillstyleeachelementindividually.Addthe
austria.jpg filetothe /images folder:
Thenaddthissnippetattheendof main.css :
/* 3. Specific */
.wallpaper {
background-image: url("../images/austria.jpg");
background-position: center;
background-size: cover;
opacity: 0.2;
position: fixed;
}
Thisimageisnotdisplayedwithan <img> tagbecauseitspurposeisdecorativeandbelongsintheCSS.
Thankstothefixedpositioning,thewallpaperwillnotscrollwiththepage.
Bestpractice
Avoidtheshorthandnotation
We'reusingeach background-* propertyinsteadoftheshorthand background one.
Ifyouuse background: red ,youareessentiallysetting background-color: red andresetingallother
propertiestotheir initial value.
Itbecomesaproblemwhenyouactuallyoverrideadeclarationyouhadpreviouslywritten,andyouwonder
whyyourCSSlinedoesn'twork!
If background-color hadbeensetearlier,itwouldhavebeenundonehere.
Theonlyusefulshorthandpropertiesare margin , padding and border .
Mainlayout
The content elementisparenttoboth:
side withtheportraitimage
about withthetextcontent
We'regonnauseCSSFlexboxtosetthegloballayoutofthepage.
.content {
display: flex;
position: relative;
min-height: 100vh;
}
.side {
max-height: 20rem;
max-width: 20rem;
}
.about {
max-width: 26rem;
}
WeenableFlexboxonthe .content bysimplyusing display: flex .Thismakesboth .side and
.about Flexboxitems.
The position: relative allows .content toappearabove .wallpaper ,andthe min-height is
heretomakesure .content coversthewholepage.
Theuseof max-width isverypractical:itjustmeansthatatanypointwedon'twantanelementtoby
widerthanacertainvalue.Forreadabilityreasonswewantthe .about sectiontonevergobeyond
26rem inwidth(whichis 26 x 16px = 676px ).Sinceit'sablockelement,itwillusethewholewidth
availableuptoacertainpoint.Dependingonthelengthofyourwrittencontent,youcanplaywiththevalue
here.
Bestpractice
Avoidz-indexwhenpossible
Allpositionedelements( absolute , fixed ,or relative )canhavea z-index valuetostackthem
relativelytoeachother.
ButelementsarealreadystackedbasedontheirlocationwithintheHTMLcode.
Because .wallpaper and .content aresiblings,thesecondone .content willappearabove(onlyifit's
positionedtoo).
Andchildelementswillappearabovetheirparent.
It'sbettertoplacethemasyouwantinyourHTML,otherwiseyou'llhavetokeeptrackofall z-index values
throughoutyourCSS.
Makingthelayoutresponsive
Wewantourlayouttoberesponsive,meaningthatitwillbedifferentonsmallerviewports(below 800px )
thanonwiderones( 800px andabove):
onmobile,we'rehavingacenteredverticallayout
ondesktop,we'rehavingacenteredhorizontallayout
We'regonnawriteamediaquery:anyCSSwritteninsidethatblockwillonlybeactiveifalltheitemsinthe
mediaquerylist( screen and (max-width: 799px) )aretrue.Inthiscase,wearetargettingmobile
deviceswhohaveaviewportnarrowerorequalto 799px .
Luckily,evenonyourdesktopyoucansimplyresizeyourbrowsertoseeitinaction.
/* 4. Responsiveness */
@media screen and (max-width: 799px) {
.content {
flex-direction: column;
justify-content: center;
align-items: center;
padding: 5rem 3rem;
}
.side {
margin-bottom: 3rem;
width: 100%;
}
}
Resizeyourbrowsertoseeitinaction.
We'reusingthefollowingFlexboxproperties:
flex-direction: column makesthelayoutvertical
justify-content: center makesthecontentcenteredonthemainaxis(vertical)
align-items: center makesthecontentcenteredonthecrossaxis(horizontal)
The padding preventsthecontentfromtouchingtheviewportedges,givingitsomespacetobreath.
The .side (whichcomesfirst)hasa margin-bottom toseparateitfromthe .content (whichcomes
second).
Desktopview
Ondesktop,wewantthelayouttobehorizontalinstead:
@media screen and (min-width: 800px) {
.content {
align-items: center;
justify-content: space-around;
justify-content: space-evenly;
padding: 4rem;
}
.side {
flex-grow: 0;
flex-shrink: 0;
height: 20rem;
margin-left: 4rem;
order: 2;
width: 20rem;
}
.about {
flex-grow: 1;
flex-shrink: 1;
}
}
The .content usesthedefaultvalueof flex-direction whichis row ,meaningtheitems( .side
and .about )arespreadouthorizontally. justify-content appearstwicebecausethe space-evenly
valueisnotavailableinallbrowsers,soweuse space-around asareasonablefallback.
The .side element(whichcontainstheimage),hasfixeddimensionsofa 20rem by 20rem square.If
there'smorehorizontalspaceavailable,wedon'twantittogrow,hencethe flex-grow: 0 .Ontheother
hand,wealsodon'twantittoshrinkatall,otherwise,theimagewouldbesquased.That'swhy flex-
shrink: 0 isusedheretoo.Webasicallywantthe .side tobe 20rem by 20rem atalltimes.Wealso
wantittoappearafterthetextcontent,whichiswhyweuse order: 2 .
Forthe .about ,wedowantittousetheremainingspaceavailable,inbothdirections,whichiswhy
flex-grow and flex-shrink havebothavalueof 1 .
Bestpractice
Inmediaqueries,don’tundo,justdo
Withmobile-firstapproaches,it'seasytomakealayoutworkwellonnarrowscreens,andthen"undo"mostof
itondesktop.Butthat'strickybecauseyouhavetokeeptrackofwhathasbeendoneoutsideofmediaqueries,
andresetthosevaluesinsidethedesktopmediaquery.YoualsoendupwritingalotofCSSjusttoreset
values,andyoucanendupleavingCSSlike margin-bottom: 0 youarenotsurewhat.
The margin-bottom setforthe .side elementshouldonlyappearonmobile.
Insteadofapplyingamarginbydefaultonallscreens,andremovingitondesktop,weonlyapplyitonmobile.
5Stylingallelements
Thepicture
Theshadowisseparatedfromtheimagebecausewearegoingtoanimatethemseparatelylateron.
Inthe 2. Shared sectionoftheCSS,updatethelistofselectorsandaddboth .picture-shadow and
.picture-image :
.wallpaper,
.picture-shadow,
.picture-image {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
Attheendofthe 3. Specific sectionoftheCSS,addthefollowingstyles:
.picture {
padding-top: 100%;
position: relative;
width: 100%;
}
.picture-shadow {
border-radius: 290486px;
background-image: radial-gradient(#000 0%, rgba(0, 0, 0, 0) 70%);
position: absolute;
top: 10%;
}
.picture-image {
border-radius: 290486px;
position: absolute;
}
The padding-top: 100% isatechniquethatmakesthe .picture ashighasitiswidemakingitsquare
atalltimes.Italsohasa position: relative sothatitactsasareferencepointforitstwoabsolutely
positionedchildren.
Theshadowusesasemi-transparent radial-gradient() .It'sslightlyoffsettowardsthebottomwith
top: 10% .
The border-radius issettotheveryhighvalueof 290486px toensuretheelementstoberounded.You
canuseanyextremelyhighvalue.Ipersonalyuse 290486px asatrademarkbecauseit'smydateofbirth.
It'squiteinterestingtoseeitshowupinotherpeople'scode!
Thename
Thenameisthemostimportantinformationofthepage.That'swhyitusesthe <h1> HTMLtag,whichhas
thestrongestsemanticvalue.Toreflectthisprominencevisuallyaswell,wearegonnamakeitbigger:
.name {
font-size: 2.25rem;
line-height: 1.125;
margin-bottom: 0.5rem;
}
Thefontsizeusesthe rem unit:it'stherootvalue,equaltothefontsizesetonthe html element,which
wepreviouslysetto 16px .So 2.25rem isessentially 36px .Using rem isusefulbecauseitreferences
acommonvalue,andwecanupdatethe html valuetosetallinstancesof rem values.
The line-height issetto 1.125 It'shardtoseeitspurposeifthetextistooshort(resizeyourbrowser
toreachtwolines),butkeepingthepagevalueof 1.5 makesthetwolinestoospacedout.
Bestpractice
Setline-heightfirst,margin/paddingsecond
Somedevelopersusetheline-heightasawaytogivespacetoanelement.Butasitsnamesuggests,it's
meanttodefinetheheightofasingleline,notthespacebetweeneachline.
Theline-heightvalueshouldbesetforreadabilitypurposesonly.
Ifyouneedtogivemorebreathingspacetoanelement,justuseabitofmargin(orsometimespadding),which
iswhatwe'redoingherewith margin-bottom .
Jobtitle
Wewantthejobtitletostandoutabit.That'swhywearegoingtouseoursecondaryfont:Montserrat.
Thisfontworkswellwhenthelettersareuppercaseandslightlyspacedout.
Inthe 2. Shared section,addthissnippet:
.job,
.button {
font-family: "Montserrat", "Quicksand", sans-serif;
letter-spacing: 0.3em;
text-transform: uppercase;
}
Thisstyleisgoingtobeusedforourbuttonaswell,solet'saddbothselectorsrightnow.
Inthe 3. Specific section,addthefollowing:
.job {
color: #ffe479;
font-size: 0.75rem;
}
Theuppercasestylemakesthetextquite"inyourface",sowe'rereducingthefontsizeabit,andalso
applyingashadeofyellow.
Thehrline
Thehorizontalrule( hr )definesasemanticbreakbetweenblocksoftext.Whilekeepingthissemantic
valueintact,wewanttomakethislinemoresubtle:
.hr {
background-color: #ff470f;
border: none;
content: "";
height: 1px;
margin-bottom: 1.5rem;
margin-top: 1.5rem;
transform-origin: center left;
width: 4rem;
}
Formorecontrol,we'reremovingthe border andusingthe background-color withaheightof 1px to
defineathinshortline.
The transform-origin willbeusedwhenweanimatethewidthlateron.
Description
Thedescriptiononlyneedstobeslightlymoreprominent.Let'sincreasethefontsize:
.description {
font-size: 1.5rem;
}
Contactbutton
.contact {
display: inline-block;
margin-top: 1.5rem;
vertical-align: top;
}
Byusing display: inline-block wecombinetwobehaviors:
inline makessurethewidthisequaltoitscontent(thebutton)
block makessuresurroundingelementswillappearaboveandbelow
italsoallowsustouse margin-top
And vertical-align: top ensurestheelementtoonlyusetheverticalspacerequired,andkeepsthe
spacingtight.
WefirstneedtoaddsomeCSSinthe 2. Shared section:
.button,
.social a {
transform-origin: center;
transition-duration: 100ms;
}
We'resettingsometransformationandtransitionvaluessharedbetweenthebuttonandthesociallinks
(whicharecominglater).
The transition-duration issharedsoweonlyneedtoreplacethevalueinasinglelocationifneeded.
Wecannowfocusonthe 3. Specific sectionforthebuttonitself,whichisthemostelaborateelement
wehave:
.button {
background-color: #fff;
border-radius: 290486px;
box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.2);
color: #9013fe;
display: inline-block;
font-size: 0.875rem;
line-height: 1;
padding: 1.25em 2em;
text-shadow: none;
transition-property: box-shadow, transform;
user-select: none;
vertical-align: top;
white-space: nowrap;
will-change: box-shadow, transform;
}
Thebuttonusesthesame inline-block techniqueasitsparent.
Theheightofthebuttonisproportionaltothefontsize,andequalto 3.5 timesthefontsizevalue:
theunitless line-height isequalto 1 or 0.875rem
theverticalpaddings(topandbottom)aresetto 1.25em each,or 1.25 timesthefontsize
The em unitisequaltothecurrentfontsize.Inthiscase,it'ssimilartotheunitlesslineheightvalue.
Ifyouplayaroundwiththe font-size value,bysetting 2rem forexample,you'llnoticethatthebutton
willresizeproportionally.Thisisveryusefulbecauseweonlyneedtoupdateasinglevalueto
increase/decreasethesizeofthebutton,whilemaintainingaperfectratio.
Wealsoapplysomeotherstyles:
becauseofthecoloredbackgroundandthedarkertextcolor,weremovethetext-shadow
weuse user-select: none sothetextcontentcan'tbeselected,whichcanhappenwhenclicking
repeatedlyonthebutton
tomakesurethetextneverisdisplayedontwolines,weuse white-space: nowrap
The transition-property and will-change valuesareforthebuttonstates.
Buttonstates
Thebuttonisthemaininteractionelementofthepage.Visitorscanhoverthebuttonandclickonit.
.button:hover {
box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.2);
transform: scale(1.02) translateY(-4px);
}
Theboxshadowistransparentsoitcanworkonanybackgroundcolor.Forthetransformation,weincrease
thebutton'ssizeby2%with scale(1.02) andmoveitupwardsbyafewpixelswith
translateY(-4px) .
Whenclickingthebutton,wewanttomakeitlookasifitwaspresseddownwards.
.button:active {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.3);
transform: scale(0.98) translateY(-2px);
}
We'rejustplayingwiththesamepropertiesbutwithdifferentvalues.Theshadowisstrongerandsmaller
becausethebuttonappearsclosertothe"ground".
Playwiththe transition-duration valuesetinthe 2. Shared sectiontoseeitslowerorfaster.
6ImportingFontAwesomeicons
FontAwesomeisaniconlibrarythatallowsyoutoeasilyincludeiconsinyourwebpage.Whatitprovidesis
essentiallyaniconfontwhichsimplyisatextfontwhereallthecharactershavebeenreplacedwithicons.
Soinsteadoftypingshapesoflettersyou'reessentiallytypingshapesoficons.Thisworksbecauseletters
arevectorshapesthemselves.Wejusthappentobeabletoreadthem!
WeareincludingthewholeFontAwesomelibrarydirectlyfromtheCDN.Thebenefitisthatalliconsare
available.Thedisadvantageisthatthefilesloadedaremuchbiggerinsize.Youcanuseaniconfontgenerator
likeIcoMoonorFontellotoonlyincludetheiconsyouactuallyneed.Thiswillreducethesizeofthefontfiles.
OneotheroptionistouseSVGimagesdirectly,butthat'strickier!
ImportingtheFontAwesomelibrary
Justbeforetheclosing </head> tagin index.html ,includethefollowingscript:
<script defer src="https://use.fontawesome.com/releases/v5.0.0/js/all.js"></script>
Rightafterthe <div class="contact"> ,addthesesocialicons:
<ul class="social">
<li>
<a>
<i class="fab fa-twitter"></i>
</a>
</li>
<li>
<a>
<i class="fab fa-github"></i>
</a>
</li>
<li>
<a>
<i class="fab fa-linkedin"></i>
</a>
</li>
</ul>
Iftheiconsdon'tshowup,makesureyouareconnectedtotheinternetandthatyouhaveJavaScriptenabled.
Stylingtheicons
Ifyoureloadthepagerepeatedly,youmightnoticethatthelayout"jumps"forasplitsecond.That'sbecause
atfirst,theiconsarenotloaded,andthepageonlydisplaysthetextandtheimages.Then,whentheicons
finallyload,thepopup,andcausethepagetoberedrawn,hencethejump.
Toavoidthisjump,we'regonnasetasquareareaof 2rem by 2rem foreach <li> listitem:
.social {
display: flex;
margin-top: 1.5rem;
}
.social li {
height: 2rem;
margin-right: 0.5rem;
text-align: center;
width: 2rem;
}
The <ul> listactsasaFlexboxcontainerforeachsquarelistitem.Wecannowstyletheinnerlinks:
.social a {
align-items: center;
display: flex;
font-size: 1.5rem;
height: 2rem;
justify-content: center;
opacity: 0.5;
transition-property: opacity, transform;
width: 2rem;
will-change: opacity, transform;
}
Eachlinkitemisasquareaswell,inwhichtheFontAwesomeiconisbothverticallyandhorizontally
centered.
Becausetheiconsaretext,wecanusethe font-size propertytoincreasetheicon'ssize.Andsince
we'vesetall <a> tagstousethe currentColor ,itpicksupthewhitecolorsetforthepage.
We'realsosettingtheopacitytohalftransparent,whichisconvenientbecauseit'svalidforanycolorwe
woulduse.
Asforthebutton,we'regonnaaddsomehoverandactivestyles:
.social a:hover {
opacity: 1;
transform: scale(1.25);
}
.social a:active {
opacity: 1;
transform: scale(1.1);
}
7CreatingCSSAnimations
AnimatinginCSSisbasicallychangingasetofvaluesovertime.Forexample,fadinginanelementisdone
bysettingthe opacity tozero 0 ,andgraduallyincrementingit( 0.1 , 0.2 , 0.3 …)untilyoufinally
reachthevalueof 1 .
Itwouldtakeawhiletofigurealltheintermediatevalues.LuckilyinCSS,youonlyneedtoset2values:
thestartvalues,withthekeyword from
theendvalues,withthekeyword to
Everythinginbetweenwillbedeterminedby:
the animation-duration :howlongittakestogofromthestarttotheend
the animation-timing-function :howthevaluesinbetweenarecalculated(basedonacurve)
CSSAnimationsaretriggeredwhenthepageloads,orwhenaclassnamechanges.
AddinganewCSSfile
WritingCSSAnimationstakesquitealotofspace,solet'screateanewfileinthe /css folder,andcallit
animations.css .
AddittothelistofCSSincluded.Youshouldnowhave4stylesheets:
<link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/minireset.min.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<link rel="stylesheet" type="text/css" href="css/animations.css">
Keyframes
A @keyframes statementcontainsalistofkeyframes,whicharealltheintermediatestepsofananimation.
We'regonnausethesimpleversionwhereweonlyneedtosettwokeyframes:
from isthekeyframeatthestartoftheanimation
to isthekeyframeattheendoftheanimation
Youcanhavemorethan2keyframes,ifyouusepercentagesinstead.
Here'sthefirstkeyframewe'regonnause.Additto animations.css :
@keyframes bounceIn {
from {
opacity: 0;
transform: scale(0.5);
}
to {
opacity: 1;
transform: scale(1);
}
}
This bounceIn animationcompletestwochangessimultaneously:
fadingin,fromcompletelytransparenttocompletelyopaque
scalingup,fromhalfthesizetotheoriginalsize
We'regonnawrite7keyframestatementsintotal:
zoomOut forthewallpaper
picImage forthepictureimage
picShadow forthepictureshadow
slideDown forthename
slideUp forallothertextelements
fillUp forthehrline
bounceIn forthecontactbutton
Shareddeclarations
LikewithourmainCSS,we'regonnashareafewdeclarationsbetweenmultipleselectors.
.wallpaper,
.picture-shadow,
.picture-image,
.name,
.job,
.hr,
.description,
.contact,
.social li {
animation-duration: 1s;
animation-timing-function: cubic-bezier(0, 0.5, 0, 1);
animation-fill-mode: both;
}
Thedurationissettoonesecond( 1s ).
The animation-fill-mode setto both tellsthebrowsertousethe from valuesbeforetheanimation,
andtokeepthe to valuesaftertheanimationhasended.Otherwise,theelementwouldreverttotheir
non-animatedstyles.
Tomaketheanimationmoreinterestingandsnappier,we'reusingacustomcubicbeziercurve.Seeitin
action!
Animatingthecontactbutton
Forananimationtobetriggeredautomatically,youonlyrequirethedurationandthename.Let'saddthe
name:
.contact {
animation-name: bounceIn;
}
ClicktoseetheButtonBounceininaction
Otherkeyframes
Herearetheother6keyframestatementswe'regonnaneed:
@keyframes fillUp {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
@keyframes picImage {
from {
opacity: 0;
transform: scale(1.2) translateY(-1rem);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes picShadow {
from {
opacity: 0;
transform: scale(1.2) translateY(4rem);
}
to {
opacity: 1;
transform: scale(1.1) translateY(0);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-1rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(1rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes zoomOut {
from {
opacity: 0;
transform: scale(1.05);
}
to {
opacity: 0.2;
transform: scale(1);
}
}
Otheranimations
Boththepicture'sshadowanimageneedaslightlyfasteranimation,andadifferentanimationcurve:
.picture-shadow,
.picture-image {
animation-duration: 750ms;
animation-timing-function: cubic-bezier(0, 0.5, 0.25, 1.25);
}
Wecannowtriggerallanimationsbyusing animation-name forallofthem,whilemakingsomeother
adjustmentstoo:
.wallpaper {
animation-name: zoomOut;
animation-timing-function: ease-out;
}
.picture-shadow {
animation-name: picShadow;
}
.picture-image {
animation-name: picImage;
}
.name {
animation-name: slideDown;
}
.job {
animation-name: slideUp;
}
.hr {
animation-name: fillUp;
}
.description {
animation-name: slideUp;
}
.social li {
animation-duration: 500ms;
animation-name: slideUp;
animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1.5);
}
The .wallpaper doesn'tuseacubicbeziercurve,butratherthe ease-out keyword.
Thesocialitemshaveanevenfasteranimation(500milliseconds,orhalfasecond)anddifferentcurvetoo.
Reloadyourpageandseeallanimationstriggeredatonce!
ClicktoseetheSimultaneousAnimationsinaction
Delayingeachanimation
Becauseallanimationsarehappeningsimultaneously,it'sdifficulttoseetheeffectofeachofthem.What
wesimplyneedtodo,istotriggertheminsequence.
Byusingatriggerdelay,wecanachievealot!
.name {
animation-delay: 100ms;
}
.job {
animation-delay: 200ms;
}
.hr {
animation-delay: 300ms;
}
.description {
animation-delay: 400ms;
}
.picture-image {
animation-delay: 500ms;
}
.picture-shadow {
animation-delay: 500ms;
}
.contact {
animation-delay: 600ms;
}
Forthesocialicons,wewanttodelaythemindividually.Wecanusethe :nth-child pseudoselectorto
selectthem:
.social li:nth-child(1) {
animation-delay: 800ms;
}
.social li:nth-child(2) {
animation-delay: 900ms;
}
.social li:nth-child(3) {
animation-delay: 1s;
}
.social li:nth-child(4) {
animation-delay: 1.1s;
}
.social li:nth-child(5) {
animation-delay: 1.2s;
}
Ifyouhavemorethan5icons,justincrementby 0.1s eachtime.
Reloadyourpageandseeyourwholepageanimated!
ClicktoseetheSequencedAnimationsinaction
8TriggeringanimationswithJavaScript
Sinceyou'vebeendevelopinglocally,bothimages( alex.jpg and austria.jpg )loadinstantly.Butona
productionserver,theseimageswilltakeafewsecondstoload.Sincetheanimationstartsinstantly,and
onlytakes1secondtocomplete,itwillhaveendedbeforetheimagehasloaded.
Toseeitinactiononyourlocalmachine,simulateaslowconnectionusingtheGoogleChromeDevTools:
openthe "Developer Tools" (with Ctrl+Shift+I or Cmd+Opt+I onMac)
gotothe "Network" tab
enablethe "Disable cache" checkbox
inthe "Online" dropdownchoose "Slow 3G"
Reloadyourpageandseehowtheimagestakeawhiletoload.
AddingaJavaScriptfile
Createanewfoldercalled /js ,andinsidecreateafilecalled main.js .
In main.js ,typethefollowing:
alert('Hello JS!');
Inthe <head> ofyourHTML,beforetheFontAwesomescript,includeyourownscript.Younowhave2
scripts:
<script defer type="text/javascript" src="js/main.js"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.0/js/all.js"></script>
Reloadyourpage.Youshouldseeanalertboxappear!
Youcannowremovethe alert() function.
EditingtheHTML
WeneedtoprepareourHTMLtointeractwithourJS,byusing:
idattributes,toselectelementswithinourJScode
dataattributes,topassdatafromtheHTMLtotheJS
Locatethe wallpaper elementandaddthe id and data-image attributes:
<div id="wallpaper" class="wallpaper" data-image="images/austria.jpg"></div>
Addan id tothe picture element:
<figure id="picture" class="picture">
Addanother id tothe picture-image element:
<img id="pictureImage"
class="picture-image"
src="images/alex.jpg"
srcset="images/alex.jpg 1x,
images/[email protected] 2x,
images/[email protected] 3x"
alt="Portrait of Alex Jefferson"
width="320"
height="320">
AppendingaCSSclassonload
We'regonnacreateaJSfunctionthatwill:
getanHTMLelement
gettheimagesourceattachedtothatelement
createanewimagefromthatsource
loadthatimage
whentheimageisloaded,addanewCSSclasstotheelement
function loadImage(id, targetId) {
var el = document.getElementById(id);
var targetEl = targetId ? document.getElementById(targetId) : el;
var imageToLoad;
if (el.dataset.image) {
imageToLoad = el.dataset.image;
} else if (typeof el.currentSrc === 'undefined') {
imageToLoad = el.src;
} else {
imageToLoad = el.currentSrc;
}
if (imageToLoad) {
var img = new Image();
img.src = imageToLoad;
img.onload = function() {
targetEl.classList.add('is-loaded');
};
}
}
Let'sgothroughthisfunctionstepbystep.First,wedefineafunctionthatcantaketwoparameterscalled
id and targetId :
function loadImage(id, targetId) {}
WethenfetchtheHTMLelementbyusingthevalueof id :
var el = document.getElementById(id);
Wesimilarlyfetchatargetelementtoaddaclassto,butonlyifa targetId isprovided.Otherwise,we
reverttotheelementabove:
var targetEl = targetId ? document.getElementById(targetId) : el;
Weinstantiatethe imageToLoad variable:
var imageToLoad;
Thereare3(mutuallyexclusive)casestosetthevalueof imageToLoad :
if data-image isprovided,weusethatvalue
ifthebrowserdoesn'tsupport srcset and currentSrc ,weusethe src valueofthe <img>
otherwisewecansimplyuse currentSrc
if (el.dataset.image) {
imageToLoad = el.dataset.image;
} else if (typeof el.currentSrc === 'undefined') {
imageToLoad = el.src;
} else {
imageToLoad = el.currentSrc;
}
Wecheckif imageToLoad holdsavalue:
if (imageToLoad)
Wethencreateanewimagefromwhichthe src isthevalueofthe imageToLoad :
var img = new Image();
img.src = imageToLoad;
Finally,whentheimageiscompletelyloadedbythebrowser,weaddtheCSSclass is-loaded tothe
targetelement:
img.onload = function() {
targetEl.classList.add('is-loaded');
};
Wenowneedtoaddthose is-loaded styles.
Settingtheloadedstyles
Theanimationsforthe wallpaper andthe picture-* elementsarestilltriggeredautomatically,solet's
removethemfirst.
.wallpaper {
animation-name: zoomOut;
animation-timing-function: ease-out;
}
.picture-shadow {
animation-name: picShadow;
}
.picture-image {
animation-name: picImage;
}
Andreplacethemwiththefollowing:
.wallpaper {
animation-timing-function: ease-out;
}
.wallpaper.is-loaded {
animation-delay: 1s;
animation-name: zoomOut;
}
.picture.is-loaded .picture-shadow {
animation-name: picShadow;
}
.picture.is-loaded .picture-image {
animation-name: picImage;
}
Wealsoneedtosettheinitialstateofthoseelements,byhidingthematthestart.Addthefollowing:
.wallpaper,
.picture-shadow,
.picture-image {
opacity: 0;
}
Ifyounowreloadthepage,thewallpaperandpicturearehidden:
theopacityissettozero 0
theanimationthatfadestheminisnottriggered
Let'snowtriggertheanimationswithJS.
Usingthefunction
WehavesetuptheCSStotriggertheanimationwhenthe is-loaded .Andwehavedefineda
loadImage() function,butwehaven'tcalledityet.Let'stryitout!
Attheendof main.js ,callthefunctiontwice:
document.addEventListener('DOMContentLoaded', function() {
loadImage('wallpaper');
loadImage('pictureImage', 'picture');
});
We'rewaitingforthewholedocumenttobeloadedbeforecallingthe loadImage() twice,withdifferent
parameters.
Yourpageshouldnowworkperfecly!Trytosetthenetworkconnectionto "Slow 3G" again,andnotice
howtheanimationswaitfortheimagestoloadbeforebeingtriggered.
Edgecase:noscript
Ifforsomereasonthevisitordoesn'thaveJSenabled,youstillwanttoshowthemtheimages.The
experiencewillnotbeasgreat,butit'sbetterthanshowingnoimagesatall.
InyourHTML,justbeforethe </body> closingtag,addthis <noscript> tag:
<noscript>
<style type="text/css">
.wallpaper {
animation-name: zoomOut;
}
.picture {
animation-name: dropIn;
}
</style>
</noscript>
IfJSisdisabled,wesimplytriggertheanimations.Younowhavethebestofbothworlds:
ifJSisenabled,thebrowserwaitsfortheimagestobeloadedbeforetriggertheanimations
ifJSisdisabled,thebrowserstillshowstheimagesbytriggeringtheanimations
9Nextsteps
ExploreHTMLandCSS
Whilewe'vecovered90%ofwhatyouwillneedtobuildwebpageswithHTMLandCSS,thereareother
tagsandfeaturesavailable.YoucanfindthemontheMozillaDeveloperNetwork.Ifyouwantasimpler
version,trythefreeresourcesI'vebuilt:HTMLReferenceandCSSReference.
LearnSass
SassisaCSSpreprocessorthatallowsyoutowriteCSSmoreeasily.Itcomeswithlotsoffeatures,but
mostnotablyvariables(forsettingvalueslikecolors,sizes,durations…),mixins(likeJSfunctionsbutforyour
CSS)orextends(sharedeclarationsbyextendinganotherselector).YoucanreadmyfreeMarkSheet
chapteronSassasastart.
LearnJavaScript
Whilewe'vecoveredabitofJS,thereisalotmoretolearn.Therearetonsoffreeresourcesonline,like
EloquentJavaScript,JavaScriptGardenorCodecademy.
Formorecomplexinterfaces,youcanuseaJSframeworklikeReact,AngularJS,Ember.jsorVue.js.
Learnbackenddevelopment
We'veonlycoveredclient-sidedevelopment(or"frontend").Butformorecomplexwebsites,youwillneed
tolearnserver-sidedevelopment(or"backend").Thisrequireslearningaprogramminglanguage(like
JavaScript,Python,Ruby,PHP…).Again,Codecademyisagreatfreeresource.
TryoutBulma
Basedontheknowledgegatheredthrough10yearsofexperience,I'vecreatedanopensourceCSS
frameworkcalledBulma.
YoucanuseitdirectlytobuildinterfacessimplybyusingtheCSSclassesprovided.It'smodular,soyoucan
includeonlywhatyouneed.ButsinceyouprobablywanttowriteyourownCSSafterhavingreadthisbook,
it'salsoagoodstartingpointforanytypeofwork.Ialwaysuseitinmypersonalandprofessionalprojectsin
someway.
It'salsoagoodresourceforlearning.Bygoingthroughthesourcecode,youmightendupimplementing
newfeatures,writingextensions,orsimplyfixingbugs!It'sacodebaselotsofdevelopershavetaken
inspirationfrom.
Thankyouforreading!