Thinking on ways to solve TABS
Aug 15, 2023
Thinking on ways to solve TABS
In today’s GUI challenge, we’re building a tabs component with some really cool features that you may not have thought about. Our tabs component is responsive, supports multiple device inputs, works across browsers, and let’s you mimic some of the buttery features you love on apps. @AdamArgyleInk will be responding to your comments for the first 30 minutes after the episode releases. Connect with us here, ask questions, or submit your own code! Chapters: 0:00 - Introduction 0:42 - Features overview 3:03 - HTML 4:14 - Scrolling 5:04 - Inspect Layouts 7:35 - Layout Styles 12:10 - prefers-reduced-motion 13:10 - JavaScript \u0026 Animation 14:37 - Conclusion Resources: Read along → https://goo.gle/37jHOen Try a demo → http://goo.gle/3prCpb2 Get the source → http://goo.gle/2NsK7EK @ScrollTimeline Polyfill → http://goo.gle/2NfUhZs Watch more GUI Challenges → https://goo.gle/GUIchallenges Subscribe to Google Chrome Developers → http://goo.gl/LLLNvf #GUIchallenges #CSS #ChromeDeveloper
Content
0.4 -> welcome to gooey challenges where i
2.639 -> create interfaces my way and then i
4.4 -> challenge you to do it your way and with
6.319 -> our creative minds combined we're gonna
7.919 -> find multiple ways to solve these
9.44 -> interfaces and expand the diversity of
11.519 -> our skills
15.31 -> [Music]
20.32 -> in today's gui challenge we are building
22.08 -> a tabs component and i know you've used
23.92 -> one of these but have you built one
25.279 -> before they can kind of be full of lots
27.84 -> of features that you might not think of
29.279 -> at first and we're gonna go over a lot
30.8 -> of those features today and you're gonna
32.239 -> notice that we are building upon the
33.92 -> side nav and the stories components that
35.92 -> we have previously covered in these
37.44 -> episodes i hope you're all caught up
39.12 -> because here goes another great one
40.64 -> let's check it out
44.64 -> let's head over to the debugging corner
46.399 -> and i want to show you some of the
47.44 -> features of my tabs component so tabs
49.52 -> come in all sorts of flavors this one
51.12 -> has a lot of obvious style one of them
53.36 -> is i have a scrollable area is sort of
55.44 -> like the first class citizen of
57.199 -> interaction patterns
58.96 -> that's a very mobile-centric thing to do
60.64 -> like on mobile it's really normal for
62.239 -> you to sort of pan instead of click to
64.08 -> get your way um although i wanted to
66.4 -> support both so of course you can also
68.56 -> use the keyboard so if i just click over
70.799 -> here into my component i hit tab i'm
72.799 -> going through the different content
74.159 -> sections here you can see that they're
75.439 -> focused and i hit continue to hit shift
77.52 -> tab i'll find my way up into a nav item
80.24 -> and if i hit enter on a nav item and
82.24 -> click the link it automatically scrolls
84.799 -> so this is the browser scrolling to the
86.64 -> content that matches the href of that
89.36 -> and then setting focus on it so that i
90.96 -> can just hit up and down on my arrow
92.88 -> keys to scroll the content and then i
95.2 -> can hit left and right to navigate
97.04 -> between the different scroll snap
98.4 -> articles that i'm in i just have a lot
100.32 -> of really bi-directional scrolling power
102.56 -> with the keyboard with touch and with my
104.88 -> mouse with this solution
106.479 -> it also has some light amounts of
108.24 -> progressive enhancement and some user
110.479 -> preferences that are really nice so if
112.64 -> you have javascript disabled which i've
114.479 -> simulated here in firefox by turning it
117.119 -> off in the settings the links still
119.2 -> point to in-page elements and the
121.04 -> browser still knows how to scroll to
122.799 -> something automatically that's really
125.04 -> nice now the smooth scroll nature of
127.36 -> what we see there is not present in
128.959 -> safari
130.64 -> that's a scroll behavior smooth this is
132.48 -> css property that they do seek to
134.8 -> have in their browser it'll be out soon
136.239 -> but it just doesn't have it yet
138.16 -> and we'll get to why that's just sort of
139.84 -> a nice little upgrade to have for
141.2 -> someone because down here where the user
142.64 -> prefers reduced motion look at how we
144.959 -> instantly transition here even though
146.8 -> this browser opera is capable of smooth
149.44 -> scroll i've disabled it explicitly if
151.84 -> the user wants reduced motion now i
154.239 -> still have animations as i scroll
157.36 -> see how the color highlights in the new
159.84 -> item and then we fade in the underline
163.04 -> we've actually swapped from an indicator
164.959 -> that's being transitioned in 3d its
166.879 -> width and its x position into a border
169.519 -> bottom solution so we transition those
171.599 -> all in css and we still have scroll
173.68 -> linked animations and we still get this
175.599 -> nice buttery effect i feel like this was
177.519 -> just a combination of a lot of wins and
179.76 -> i want to cover them really bad with you
181.599 -> so let's check out the html this is sort
183.36 -> of where it all starts
184.48 -> let's go there
185.68 -> now hopefully what you see here isn't
187.12 -> that surprising we have a device frame
188.879 -> which has been in a lot of previous
190.319 -> demos it's not part of the snap tab so
192.4 -> let's skip it and jump right into snap
194.239 -> tabs as a custom element this is kind of
196.239 -> where it all starts to get fun and
197.68 -> interesting the breakdown of the
199.519 -> component hopefully starts to read like
201.12 -> a book we have a header of a navigation
203.04 -> so this header is for the section right
205.44 -> we have many articles to go through so
207.28 -> here's a header to introduce all the
209.04 -> different articles there's a navigation
211.04 -> in this header that represents a bunch
212.48 -> of links and these links each represent
214.799 -> a particular article in the content down
216.799 -> below we can expand some of these just
218.48 -> to see what they look like inside of
219.599 -> here my my more element had some svg
222 -> that was just kind of fun as like a
223.2 -> mobile little icon and each article is
225.12 -> full of a bunch of lorem and some of
227.12 -> them are scrollable and some of them
228.56 -> aren't because i wanted that to sort of
230 -> be a feature of this tabs sometimes the
232.4 -> content that you scroll to is even
234.159 -> scrollable itself right if we look at
236 -> this breakdown in terms of layout this
237.92 -> header is horizontally scrollable and
239.599 -> we've got a utility class here
241.36 -> indicating that that we'll go over soon
243.04 -> this section is also horizontally
244.64 -> scrollable and each article is
246.879 -> vertically scrollable that's three
249.04 -> different scroll zones and you know what
251.28 -> grid and flex they make it kind of a
253.2 -> walk in the park let's check out those
254.879 -> layouts because i think this markup is
256.959 -> it's pretty clear let's build upon it
259.04 -> but first we must preview in chromium
261.04 -> canary so over here i'm scrolling our
263.6 -> top nav down here i can scroll our
265.68 -> article content and then i can also pan
267.68 -> back and forth inside of our scrollable
270.08 -> articles list okay so those are our
271.759 -> scrollable zones we can also preview i
274.08 -> want to show this if you go to system
275.52 -> preferences and go to general and show
277.6 -> scroll bars you can set this to always
279.6 -> and here if i reload look at our nice
281.6 -> little scroll zones so we have these
283.199 -> permanent scroll bars now it's almost
284.72 -> like if we're on windows or something
286.24 -> and we can see how they all sort of save
288.16 -> state too look at that i think one of my
290 -> favorite things about this preview is is
291.759 -> grabbing this thumbnail down here it's
293.199 -> just so rewarding
294.72 -> i love that okay so let me go back to my
297.04 -> settings and set these to automatic
298.4 -> that's my preference but other users
299.84 -> have other one and i'm going to bump
301.12 -> this size up i'm going to zoom it up i'm
303.52 -> going to open chrome dev tools with
304.8 -> command option i and i'm using chrome
306.88 -> canary because there are some new
308.32 -> experiments in here that i'm super
309.84 -> excited about here's our device don't
311.84 -> care about that very much i care about
313.36 -> snap tabs and we can see that there's a
315.12 -> flex badge here and a flex and a grid
317.6 -> badge and let's just expand these also
319.199 -> we can see how many different badges we
320.72 -> have okay it looks like that and if that
323.199 -> looks like an overwhelming amount of
324.639 -> badges and it's hard to follow that's
326.4 -> why we made this layout tab and you can
328.72 -> visit here to see all of the grid
330.08 -> overlays and all the flex overlays and
332.08 -> that's where i'm going to start because
333.12 -> i'm going to go over our layouts really
334.4 -> quick and i'm going to do it right from
335.84 -> here our top layout is snap tabs and if
338.88 -> we click it
339.919 -> it sort of toggles that feature on for
341.6 -> us we can see it highlight over there
342.96 -> and i'm going to change its color to
344.479 -> something cooler like pink
346.4 -> aha so we can see that we have two boxes
348.479 -> one on top and one below and that's
350.16 -> because we have a flex direction set to
351.759 -> column so it just kind of creates a
353.039 -> stack and that's the same thing for this
354.4 -> layout here well here i clicked it but
356 -> we can uncheck our layout there we can
357.6 -> go to this header and toggle it on here
359.759 -> and that one's just another one it has
360.88 -> the one indicator element and then a nav
362.96 -> with a list of links now the nav has
364.8 -> some cool overlay style so let's go
366.319 -> ahead and toggle this one off and toggle
367.759 -> this one on and i'm going to change its
368.96 -> color actually lime green is pretty cool
371.84 -> i can't really see it though let's
373.039 -> change it to something
375.039 -> more visible awesome okay so here's our
376.639 -> blue this is our nav overflow and we can
378.88 -> see that this is a scrollable area and
380.56 -> it's hashing out the items that aren't
382 -> currently in view which is super neat
384.16 -> and if we toggle that one off and toggle
385.919 -> on our links and if i click this button
388.72 -> it'll take me to the node in the dom
390.56 -> which means i can go to the styles and i
392.319 -> want to show you this if you hover over
394.319 -> the alignment like align items or
395.84 -> justify items it will overlay the
398.16 -> pressures like the directions that these
399.759 -> are trying to align to
401.36 -> and these tabs are align item center
404.639 -> because they want any icons or any other
406.479 -> items that are with them in that link to
408.479 -> all be vertically centered so right
410.4 -> isn't that cool well we had one more
412.16 -> layout to go over and that was a grid
414.08 -> layout here on this section so if i
416 -> toggle that on i'm going to also change
417.759 -> its color to black yes something rad
421.039 -> okay and this layout i click the element
424 -> go to styles should look pretty familiar
426.319 -> here it is display grid grid auto flow
428.479 -> column grid auto columns 100
430.639 -> we used that on the stories component so
433.199 -> this just says any number of children
435.199 -> that are coming in i'm going in a
436.56 -> direction of columns so they're all
437.759 -> coming over here to the right and each
439.36 -> column is a hundred percent of my width
441.039 -> and that's what we get this box box box
444 -> they're all just side by side and no gap
446.479 -> okay so that is the high level of our
449.199 -> layouts but let's go look at the styles
451.039 -> that that represent all this stuff and
452.96 -> how did i author and what's it look like
454.4 -> there okay so if we come over here to
456.24 -> tabs.css i have snap tabs open we've got
459.44 -> some colors some spacing here's our
461.44 -> display flex and flat and flex direction
463.599 -> column are just play flex in flex
465.28 -> direction column i feel like if i say
466.72 -> that in more of like an announcer voice
468.24 -> maybe i'll uh enunciate these better
469.84 -> they're kind of tricky well anyway then
471.68 -> we have overflow hidden and position
473.199 -> relative and what these are doing is
474.8 -> they're anchoring our element it needs
476.479 -> to have three child scroll views and
479.039 -> some things might need position kind of
480.639 -> interesting in layer so we give them
482.4 -> this sort of containment here with
483.759 -> overflow hidden and position relative
485.599 -> and this and matches could also be and
487.52 -> is but i don't think my highlighter
488.72 -> likes it yeah
490.16 -> this and matches uh is looking for child
492.72 -> elements header nav section article a
494.479 -> these are all like interactive elements
496.08 -> that come from your keyboard that you
497.44 -> can interact with and so i set their
498.96 -> outline color to match our you know hue
501.36 -> and accent that's coming from this
502.479 -> component and give them an outline
503.919 -> offset
505.36 -> if we look at our scroll snap x so these
507.199 -> are our two horizontally scrolling
509.36 -> elements we set their overflow their
511.36 -> overflow behavior and we set them as a
512.959 -> snap element so it's a snap container we
515.2 -> also say hey if the user is okay with
516.959 -> motion they have no motion preferences
518.88 -> let's scroll all of their in-page links
521.039 -> smoothly so we'll
522.88 -> enhance that interaction which is when
524.56 -> you click a link and it tries to bring
526.08 -> in the element that matches
527.76 -> it will do that smoothly instead of
529.2 -> instantly
530.32 -> and down here we hide the scroll bar
532.08 -> thumbs with an older selector and then
534.64 -> new in the spec way here if the user
536.8 -> can't hover so if they can't hover on
538.399 -> these horizontal scrolling you know
540.24 -> areas we're just going to hide the
541.44 -> thumbs entirely and that was something i
542.959 -> like to do on native native usually does
544.72 -> that where like the vertical scroll bars
546.16 -> are present but the horizontal ones are
547.44 -> missing anyway i thought that was a cool
549.279 -> tip
550.16 -> and let's look at the snap tabs headers
551.68 -> so we'll come back over here let's get
553.6 -> rid of our grid so we'll come back to
555.04 -> our layout panel or turn off the grid
557.2 -> and turn on the header because that's
558.959 -> what we're looking at right now
560.8 -> okay and then here we've got a flex
562.88 -> string zero and a min block size of fit
565.04 -> content these are kind of tricky they're
567.12 -> in here because we have some pressures
568.72 -> coming from the uh section here this
571.04 -> section has a style of block size 100
574.48 -> and the header needs to basically defend
576.72 -> itself against that pushy sibling and it
578.88 -> does that by saying i don't shrink and
580.959 -> since i'm also an overflowing x you know
583.6 -> scrolling container and that's giving me
585.2 -> some cross browser issues i'm going to
586.64 -> go ahead and write my min height my min
588.56 -> block size is fit content and that makes
590.64 -> that work across browsers so that's kind
592.56 -> of some funky styles that came in here
594 -> but they're due to the pressures and the
595.519 -> amount of nesting of flex and grid that
597.279 -> we're doing in here it's just a little
599.2 -> complex for the browsers
600.8 -> and that helped equalize everything this
602.88 -> header is also a flex
604.399 -> uh container which has the directional
606.399 -> column that's why we see the indicator
608.16 -> is underneath the list of like the nav
610.88 -> link here or the nav element that has a
612.959 -> list of links right okay so that's why
614.64 -> that's a stack
615.839 -> and the nav itself is just to display
618.16 -> flex look at that that's all it has and
620.64 -> the reason though that the elements are
622.24 -> pushing out to the right instead of
623.6 -> being squished because normally flex
625.519 -> would try to like fit them and not wrap
627.519 -> right like we don't have any wrapping
628.8 -> styles here but if we go to either like
631.68 -> of these elements and we look at their
632.959 -> white space set to no wrap that's what's
635.12 -> causing these to explode out of the
636.64 -> parent
637.6 -> is these are saying no no no i will
639.279 -> never wrap my width is my width and i
641.68 -> have some padding so you better respect
643.279 -> that and the nav says well i'm a flex
645.44 -> and they're currently going in this
646.8 -> direction
648 -> of row and there's too many of them so
649.92 -> i'm just bigger than my parent and
651.2 -> parents like hey that's cool i'm ready
652.88 -> to overflow my content so don't worry
654.72 -> about it so that's how we set that up is
656.88 -> we set these elements as being kind of
659.44 -> demanding in their width and then we
661.92 -> allow that to be a directionality in the
664.24 -> container and then the container of that
666 -> container is the one that allows
667.12 -> scrolling so scrolling always has two uh
669.92 -> elements that have to play in here
671.2 -> something has to be really big something
672.959 -> has to be bigger than its parent and
674.48 -> then the parent must be ready to be a
676.24 -> scrolling window i go over a lot of this
678.959 -> stuff in the article where i kind of
680.399 -> talk about these oversized children and
682.24 -> this window concept so go look at that
684.56 -> if you are wondering what it is i'm
686.079 -> talking about anyway each link has
688.079 -> scroll snap line set to start and that's
690.399 -> why as we scroll this top nav they'll
692.48 -> snap right here and we always get that
694.24 -> nice left alignment which is really
696 -> important i think okay and then we have
697.839 -> some things about focus and some styles
700.079 -> in there let's go on to the snap tab
702.48 -> section so we talked about this display
704.64 -> already this is from the stories
706 -> component we talked about block size 100
708.079 -> this is like the dominant section right
710.16 -> this needed to fill this area
712.64 -> and then each article each article is
714.72 -> snapping as a scroll snap target right
716.88 -> here it is snapping
718.32 -> and we set the overflow to wire to auto
720.16 -> and that's why we can vertically scroll
721.44 -> these and we contain that over scroll
724.32 -> behavior i just like anytime something's
726 -> scrolling and it's scrolling in one
727.36 -> direction contain that it's just nice
729.6 -> all right we'll close that back up and
730.959 -> look at our custom media queries here
732.72 -> for when the user is preferring reduced
734.399 -> motion so let me go to rendering scroll
736.399 -> down to
737.6 -> prefers reduce motion i'll set the
739.36 -> motion to preference reduced and i'm
740.8 -> also going to go turn off some of my
742 -> layouts let's just go uncheck those okay
744.24 -> go back to rendering so what we've done
746.32 -> is we've switched it at runtime to now
748.8 -> the user prefers reduce motion and as i
750.72 -> click between sections
752.639 -> look at that we get to see our
754.16 -> transition now of a border bottom
756.88 -> uh crossfading instead of being scrolled
760.079 -> live and that just happens right here in
762.56 -> this css where we look to see hey is the
764.8 -> user in a state where they want to you
766.72 -> know reduce motion let's hide the
769.2 -> visibility of the snap indicator and
771.44 -> instead go put in a border block n so
774 -> border bottom and you know use the same
776.24 -> dimensions that we used for the snap
777.6 -> indicator and transition some of those
779.44 -> items and then in the javascript we're
781.36 -> still watching those we're just going to
782.88 -> apply a different transformation based
784.56 -> on this preference so that's it for the
787.04 -> styles and let's go look at some of the
788.56 -> javascript but i feel like this video is
790 -> getting kind of long so i'm going to
790.959 -> kind of go quick i'll pull open the
792.56 -> index.js file from the second column and
795.04 -> first thing i'm doing is i'm importing
796.32 -> the scroll timeline polyfill this lets
798.24 -> us use it today there's css and
800.16 -> javascript we'll link to this in the
801.68 -> show notes it's a really great spec i'm
803.6 -> excited about it then we look from
805.44 -> javascript to see if motion is okay we
807.44 -> look for the same media query that we do
809.279 -> in our css but we stash the result of it
811.92 -> into a destructured variable called
813.44 -> motion okay so motion okay is
814.959 -> representing the matches boolean here
817.2 -> then we grab and stash a bunch of
818.56 -> elements so that we can use them in all
820.8 -> of our functions we're going to create a
822.56 -> new scroll timeline that's focused on
824.56 -> the
825.44 -> horizontal scroller of the articles and
827.36 -> now we'll tick the animation of color
829.279 -> and the underscore position as we go
831.04 -> through in some of these later ones
833.12 -> we go through each of the tab nav items
834.88 -> and we create keyframes for them if
836.959 -> motion is okay we animate the underscore
840.48 -> you know that goes underneath the tabs
842 -> and the rest of this is kind of helping
843.36 -> us maintain state we watch scroll to see
846.079 -> when scroll ends because when scroll
847.839 -> ends we're going to determine the
849.199 -> currently active tab like article and
851.68 -> then set that active tab and that's all
854.32 -> that happens there we're also looking
855.68 -> for clicks on the tabs and we're
856.959 -> synchronizing things there and the last
859.199 -> thing that we do which is kind of neat
860.56 -> is window load we look to see if there's
862.72 -> a hash and we find the appropriate tab
864.959 -> that matches that article so here check
866.56 -> it out i'm over here i'm at the more
868.72 -> section if i just hit reload
870.48 -> see how the page loaded looked at more
872.399 -> and synchronized that both of these go
874.16 -> to that state that's right here in that
875.92 -> window on load there is so much more to
877.839 -> get into but we have run out of time
880.48 -> i had a blast building these tabs and
882.079 -> i've tried to pack the rest of the deets
883.44 -> into the blog post so if you're hungry
884.959 -> for more don't miss that post on web.dev
887.36 -> and like always hopefully this is making
889.36 -> you really itchy to bring your own tab
891.279 -> style to the table do us all a favor and
893.36 -> share that to me on twitter or youtube
894.72 -> because you never know maybe i'll give
896 -> it a shout out thanks for tuning in time
898 -> to do it your way see y'all
Source: https://www.youtube.com/watch?v=mMBcHcvxuuA