BuildingWebLayoutsForDual

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.