It’snowbeenmorethantwoyearssincetheSamsungGalaxyFoldandSurfaceDuowereintroducedtotheworld.Sincethen,theSurfaceDuo2,SamsungGalaxyZFold3andGalaxyZFlip3haveallhitthemarket.Foldabledevicesareavailabletopurchase,andarecurrentlybeingusedbyconsumerstoday,andwithitcomesanopportunitywherewe,asdevelopers,canstarttoexplorethisnewclassofdeviceandthenextevolutioninresponsivedesign.
TheAPIsthatwereinitiallydesignedtosolveforbuildinglayoutsondual-screendeviceshavegonethroughsomerevisionsafterfeedbackfromdeveloperswhousedtheAPIsinbrowserorigintrials.ThebeautifulthingabouttheseAPIsisthattheyintegratewithexistingconcepts,sodesignersanddevelopersdon’thavetospendtimelearningnewconcepts,butcanthinkabouthowtobuildenhancedexperiencesforusersondual-screendevices.
Dualscreenandfoldabledevicesarejustthenextstepinresponsivedesign,sothey’reviewedasanotherresponsivedesigntargetthatwecanstyleforwithmediafeatures.Wealreadyusemediafeaturesandqueriestotargetdesktops,tablets,andmobilephonestoday,andnowwehavetheCSSViewportSegmentsmediafeaturetotargetourfoldableanddual-screendevices.
Theviewportsegmentsmediaquerycanhavetwovalues.Thefirstoneishorizontal-viewport-segments,andthisrepresentsthestateofthedevicewhenthedevicehingeisverticalandtheviewportsaresplitbythehardwarehingeorfoldintocolumns.
Toservestylesspecificallyforafoldabledeviceinthisorientationwewouldwritethefollowing:
@media(horizontal-viewport-segments:2){//Stylesspecifictothedeviceinthisorientation}Theintegerrepresentsthenumberofviewportspresentinthedeviceorientation.Whenthedeviceisintheverticalfoldposturelikeabook,wehavetwodistinctviewportsinthehorizontaldirectionandonlyoneviewportintheverticaldirection.
Wecanalsocombineourmediaqueriestotargetdualscreendevicesandcertainviewportwidthstoserveupspecificstyles:
@media(horizontal-viewport-segments:2)and(min-width:540px){body{background:yellow;}}vertical-viewport-segmentsOursecondvaluefortheviewportsegmentsmediafeatureisvertical-viewport-segments,andthisisthestateofthedevicewhenthedevicehingeishorizontal,andthehardwarehingesplitsourviewportsintorows.
Totargetdevicesthatarerotatedinthisdirectionwewouldusethefollowingcode:
Viewportsegmentsrepresenttheregionsofthewindowthatresideonseparatedisplaysthatareadjacenttoeachother.Todetectadual-screendeviceyouwouldquerythesegmentspropertywiththefollowingcode:
constsegments=window.visualViewport.segments;ThevaluereturnedfromthisquerywillbeanarrayofDOMRectsthatindicatehowmanyviewportsthereare.Ifthereisonlyoneviewportsegment,thequerywillreturnnull,andisimplementedthiswaytopreventfuturecompatibilityissues,sothatdevelopersdon’tstartusingvisualViewport.segments[0]totargetsingle-screendevices.
Ondual-screendevices,thequerywillreturn2DOMRects,representingthe2viewportsavailablewhenthebrowserwindowisspanningacrossthefold.
Thisvaluewehavestoredinthesegmentsconstantisanimmutablesnapshotofthedevicestatewhentheattributewasqueried,andifthebrowserwindowisresizedorthedeviceisrotated,theviewportsegmentspreviouslyretrievedarenolongervalidandneedtobequeriedagainthrougharesizeororientationevent(orboth).
Ifyouresizethebrowserwindowtospanacrossonlyonedisplayregion,we’llfiretheresizeevent.
Ifyourotatethedevice,thiswillfireboththeresizeandorientationevent,andyoucanusetheeventstoquerytheattributeagaintogetthecurrentstateofthebrowserdisplayregions.
InadditiontotheCSSmediafeatures,sixnewCSSenvironmentvariableshavebeenintroducedtohelpdeveloperscalculatethegeometryofthedisplayregions,calculatethegeometryofthehingeareawhenit’sbeingobscuredbyaphysicalhardwarefeaturelikeontheSurfaceDuo,andtheycanalsobeusedtohelpplacecontentwiththeboundsofeachdisplayregion.
Thesixnewenvironmentvariablesareasfollows:
Thexandypositionsrepresentthetwo-dimensionalgridcreatedbyhardwarefeaturesthatseparateeachviewportsegment,withthecoordinates0,0startingatthetop-leftsegment.
Whenyouhaveadevicethatisintheverticalfoldposturewiththeviewportssidebyside,theviewportsegmentontheleftwouldberepresentedbyenv(viewport-segment-width00),andtheoneontherightwouldberepresentedbyenv(viewport-segment-width10).Ifyouturnedthedeviceintothehorizontalfoldposturewiththeviewportsstacked,thetopwouldberepresentedbyenv(viewport-segment-height00),andthebottomviewportbyenv(viewport-segment-height01).
Whenusingenv(viewport-segment-width)andenv(viewport-segment-width),inadditiontotheindices,wecansetafallbackvaluelikethefollowing:
env(viewport-segment-width00,100%);Butthisadditionalfallbackvalueisoptionalanduptothediscretionoftheauthor,ifthey’dliketoincludeit.
Whenyouhaveadevicethathasahingeobscuredbyhardwarefeatures,you’reabletocalculateitusingtheenvironmentvariablesprovided.
Inourexample,wehaveadeviceintheverticalpostureandwanttofindthehingewidth,sothatnocontentisobscured.We’llsubtracttheleftviewportsegmentoftherightdisplayfromtherightviewportsegmentoftheleftdisplay:
calc(env(viewport-segment-left10)-env(viewport-segment-right00));PlacingContentWithTheCSSenv()VariablesWecanusetheCSSenvironmentvariablestoplacecontentwithinthedisplayregionboundaries,andtheseareespeciallyhelpfulifyouwanttoplacecontentdirectlyagainstthehingeorfold.
Inourexamplebelow,we’regoingtoplaceanimagedirectlyagainstthehingeinthefirstdisplayregionontheleft.Thisareaistherightsegmentoftheviewport,sowe’lluseviewport-segment-righttoplaceitwiththefollowingcode:
img{max-width:400px;}@media(horizontal-viewport-segments:2){img{position:absolute;left:env(viewport-segment-right00);}}IfweemulateourscreenintheEdgeDeveloperToolsinSurfaceDuomode,we’llgetthefollowinglayout:
Thisisn’twhatwewanted.Theimageshouldbeinthedisplayregionontheleftside.
Becausetheimageisabsolutelypositionedwiththeleftproperty,theleftedgeoftheimageendsupalignedtotheviewport-segment-rightdisplayarea.
Wethenneedtosubtractthewidthoftheimagefromourenvironmentvariabletogettheimagealignedtothecorrecthingeedge:
Assomeonewhoconstantlyusesherphonewhilecooking,arecipesitethatwouldadaptwhenI’monmydual-screendevicewouldbesohelpful.Let’swalkthroughhowtothinkaboutadaptinganindividualrecipepageforit.
IwanttothinkabouthowI’mgoingtochunkoutmymaincontent.Typically,atminimum,Iseearecipetitle,howmanyservingsitmakes,howlongit’sgoingtotaketocook,animageormultipleimages,theingredients,andthestepstomakethedish.
WhenIsketchoutmywireframe,Igetthefollowing:
Iwantmytitleandtherecipedetailsattheverytop,followedbyanimagethat’sgoingtotakeupthewholecontentwidth,thentheingredientslist,andtherecipesteps.Idon’twanttostackthelattertwocontentgroups,becausetheingredientlistwillhavealotofwhitespacetotherightofitifIstackthem,soIwantthestepstositnexttotheingredients,givingmetwocolumnsbelowtheimage.
IknowhowIwanttolaythisrecipeoutonanormaldesktopscreen,andtherearemultiplewaysIcangoaboutcodingthislayoutandgroupingcontent,buthowIgroupit,andwhatlayoutIwanttoachieveonadual-screendevicewillneedtobeconsideredbeforeIcode.BasedonthesketchIdidforadesktopview,IcoulduseacombinationofflexboxandCSSGridtoachievethelayoutIwant,whereIgrouptheingredientsandstepsinaflexcontainer.ButletmesketchouthowIwantmypagetodisplayonadualscreen.
IfIwantmoreflexibilityinlayout,thenIcan’tgroupmyingredientsandstepsinaflexcontainer,otherwise,there’sgoingtobeabiggapofwhitespaceinwhichevercolumntheimagedoesn’tgointo.
I’mgoingtousenothingbutCSSGridforthedesktopanddual-screenlayouts.So,let’sbuildoutourcontent.