Well done!
You have completed Build an Interactive Settings Panel - Treehouse Live!
You have completed Build an Interactive Settings Panel - Treehouse Live!
Want to code out a real-world project with Dustin? Follow along with our Treehouse Live replay as he builds a settings panel UI from scratch with just HTML and CSS. Then, he refactors the app with JavaScript to render parts of the UI dynamically. Stick around to the end to find out how he implements a dark mode toggle for the settings panel itself with an event listener!
Resources
Related Content
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up[MUSIC] 0:00 Okay, so let's get started. 0:09 The first thing I'll do is I'll go to github.com/treehouse/settings-panel 0:12 And this is the repository that is associated with this project. 0:21 Zoom in a little bit. 0:26 So in here, we will have our primary color, which is orange (#EEA15A), 0:28 and then we will have these light themed, CSS variables, and 0:34 we'll override them with a dark theme, which are also in the README. 0:39 And then, our data file is also in here, and 0:46 I'll show you how to use all this whenever we get to that point. 0:49 First thing's first. let's just clone down this project, so 0:53 I'll hit the big green code button, and then hit this copy to clipboard button. 0:56 You can use GitHub Desktop if you'd like, I'm gonna use my terminal. 1:02 So I will change directories to desktop, then I'll write git clone and 1:05 then paste in that link. 1:10 And then, I will drag that project to VSCode. 1:14 So at any point, if you get stuck or 1:21 when you're finished, if it's just not looking the way mine is, 1:23 you can find all the finished code in this master folder right here. 1:27 But we will be working in this starter folder. 1:32 So let's go over what we have in here so far. 1:36 In our HTML file, it is just a bit of standard HTML boilerplate code. 1:40 We do have a settings panel for our title, and 1:45 we have our CSS style sheet linked up. 1:49 We will be using SCSS for this project. 1:53 We won't be doing anything complex with it, we'll just be using it for nesting. 1:57 So inside of our styles folder, we have an app.scss file, 2:01 which we will write all of our styles for, and it will automatically 2:06 be compiled to CSS for us with the SASS compiler extension. 2:11 If you don't have that, all you need to do is click on extensions and type in SASS. 2:17 And then, you'll find this live SASS compiler extension. 2:23 All you need to do is click on that and click Install, and 2:28 you should be good to go. 2:32 Once you are working inside of this starter folder right here, 2:34 you just need to click this watch SASS button, and 2:38 it will compile everything for you and you'll be able to follow along with me. 2:42 In this folder, we also have our scripts file, 2:48 which is an app.js file, and it's empty. 2:51 And then our images folder and in here, we have our mockup, so 2:54 this is what we'll be building out. 2:58 And then we have our treehouse logo, which will be this logo down here. 3:01 So let's go over the mockup a little bit. 3:05 We have a settings panel with three separate settings. 3:07 Each of them have a title, a description, and a toggle switch. 3:12 And none of these will actually do anything except this last one, 3:18 the dark mode. 3:21 We will actually make this toggle a dark theme for our settings panel. 3:22 So let's get started with the markup. 3:28 I will open up the mockup on the right just so 3:31 that we can start building out our UI a little bit. 3:35 So I will put everything inside of a settings panel container. 3:40 I'll create a div with the class of settings-panel, and 3:46 that'll be this big white settings panel that we have here. 3:50 In here, I want to have just two children, our header that has a h1 for settings, 3:55 and then our settings container, which will hold all of our settings. 4:00 So let's create that now. 4:05 All right, header and inside of that, I will give it a h1 and write Settings. 4:07 And then underneath that, I will write a div with the class of settings. 4:14 And we'll need to use this with JavaScript later on, so 4:19 I'll give this an ID as well of settings. 4:23 And also our entire UI is gonna be inside of the settings-panel div that we created, 4:26 that will also need to use with JavaScript later. 4:32 So I'll go ahead and give that an ID also, and I'll just call it settingsPanel. 4:36 Sweet, so I'll hit save. 4:43 And now, let's start creating each individual setting. 4:45 So each one of these will look exactly the same, just have different content. 4:50 So I'll do a div with the class of setting, and 4:54 the only things that I want in this container are the label and the checkbox. 4:58 So this label will have a title and a description, and 5:05 then our checkbox will write some styles to style it like a toggle switch. 5:09 So let's give our setting container a label element. 5:16 And we'll leave the for attribute empty for now. 5:22 And in here, we'll have a span that we'll use for our title, 5:26 and I'll copy that again so that we have another span for our description. 5:29 Outside of our label, we can write an input with the type of checkbox. 5:34 We can go ahead and delete the name attribute because we won't need that, 5:43 and that is it for our individual setting markup. 5:48 So let's copy that a few times, and 5:51 I'll put some comments on top to know which one is which. 5:55 So this one will be for auto saving photos. 6:01 The second one will be for location services, and 6:05 the last one will be for our dark mode theme. 6:09 So now, let's start adding in the content that we'll need in here. 6:14 You can go back to our GitHub and read the README file for 6:20 this, or you can just go directly into the README file. 6:24 I'll open this up on the side, and if you scroll down to the bottom, 6:28 you'll see a bunch of objects, and these objects have all of our data in them. 6:33 We'll use this in the JavaScript later, but for now, 6:38 we can just copy what we need from this. 6:40 So inside of our label, we have this for attribute, 6:43 and we also have an ID attribute on our input. 6:47 These need to be the same so that when we click on our label, 6:51 it will also toggle this checkbox. 6:54 So this is where the UID comes in, 6:57 which is over here on the right, so It stands for Unique ID. 6:59 And I'll copy the first one for auto save photos, and 7:05 I'll use it as our for attribute on our label, and then our ID for our input. 7:08 And then, for the title, I'll copy this and paste it in our first span and 7:14 then our description, I'll copy and paste into our second span. 7:19 And now, I will repeat this for the other settings as well. 7:26 So let's grab our title for 7:32 location services and then our 7:36 description and now our unique ID. 7:41 Copy, and also paste that as the ID for our checkbox input. 7:46 And now, the last one, which is for dark mode, so let's copy the title, 7:51 paste it in the first span, copy the description, paste it in the second span. 7:56 And lastly, we'll do our unique ID of dark mode, and 8:03 that will be for our for attribute for our label, 8:07 as well as the input type checkbox, we'll use the ID and hit Save. 8:11 So I'm using live server to view this live. 8:17 So down here, I can just go ahead and click, go live, and 8:21 it should spin up a browser. 8:24 So this is what it looks like so far, it's very un-styled, but this is all we need. 8:26 And checking that we can click on our label to toggle the checkbox and 8:33 it works, so that's great. 8:38 I'll go ahead and push this to the side of my screen, and 8:40 then I'll use the other side for the code, and now we can begin styling. 8:45 So let's go ahead and open up our style sheet. 8:52 Everything will be inside of the app.scss file. 9:00 So first things first, let's go back to our GitHub or you can do the README, 9:05 it doesn't matter, and let's grab these variables. 9:09 So by default, our UI will have this first set of variables for our light theme. 9:12 So let's go ahead and set up a rule for 9:18 our settings-panel and paste those in there. 9:21 Oops, backspace that. 9:26 And now, let's do the same thing, but for 9:31 settings-panel, when it has the class of dark, and 9:34 what we can do is paste in the second set of variables. 9:39 The second set of variables is the exact same as the ones that we just pasted but 9:44 they're different colors. 9:49 So they have all the same names, just different colors, which means when 9:51 our settings panel gets a class of dark, these colors will override these colors. 9:55 And we'll go into detail more about that whenever we get to that point. 10:01 But all we're doing right now is initializing these variables, 10:05 we'll need to add them to our UI. 10:08 And we can get started with that now. 10:09 So our main UI is gonna have a big orange background. 10:12 So we'll use this --primary-bg CSS variable. 10:16 And to use a CSS variable, if you're not familiar with it is pretty simple. 10:21 For our body we'll just write background color. 10:25 And to use that --primary-bg CSS variable we just write var() 10:28 and then the CSS variable name. 10:33 So if I hit save, we should see the changes in the browser. 10:39 So I do need to run my Sass compiler. 10:44 So as mentioned earlier, if you're joining late, 10:47 this is just an extension called Live Sass compiler. 10:50 Just install this and then you'll have this Watch Sass button at the bottom. 10:53 When you click that, it'll automatically convert your Sass code to CSS. 10:58 I'll go ahead and move this to the bottom so that we can still see what we're doing. 11:04 So we set the background color for 11:10 our body to the --primary-bg CSS variable, which is this orange color. 11:12 Next, let's go ahead and add in our background-image. 11:18 So we'll write background image and we'll write url(); and 11:22 then we'll navigate to images and then our thlogo.png. 11:27 Sweet, it worked but now we see it all over the place and 11:32 in the mockup it shows that it's kinda just in the bottom left corner. 11:36 So let's adjust that, we can do background-repeat: ;. 11:41 And we'll do no-repeat. 11:47 I personally don't like to use the shorthand property for background, so 11:49 I'll put everything on its own line. 11:53 We'll set the background repeat to no-repeat. 11:56 We'll do background-position: bottom left; 11:58 And we'll hit save. 12:03 And it's still all the way at the top and 12:05 this is because the body is only as high as the content that we have set. 12:07 So we can do a height of 100vh and now it's at the bottom left. 12:10 But it's a little big, so let's do background-size and 12:16 we could do 250px. 12:19 There we go, it's a little bit better, it's a little smaller. 12:21 So the only item that we have in our body, is this div with the class 12:26 of settings panel so I wanna center this in the middle of our page so 12:32 the easiest way to do that would be to use flex so 12:37 we can set the body's display to flex or justify-content: center; 12:41 And we'll align-items: center; as well and there we go. 12:48 Now we have our content center which is perfect. 12:54 So with that out of the way, 12:58 let's start styling our only child of the body which is the settings-panel. 12:59 So we can write settings-panel {} 13:05 And the first thing I wanna do is give it a background-color. 13:07 And we have a background-color in our CSS variables, which is --panel-bg. 13:11 So I'll go here, click copy, and 13:16 I will set it up by writing var() and then the variable name. 13:19 And now you can see that we have our white background. 13:25 I'll give it a bit of padding. 13:28 I'll do padding 2rem and I will give it a width of 13:29 80% which looks great when the window is this size, but 13:33 if we made our app full screen it would stretch so 13:38 let's give it a max width as well. 13:43 We can set our max width, To 550 px. 13:46 Let's see how that looks, I think that looks pretty good. 13:51 All right, now let's add some border-radius. 13:58 We can do border-radius: 1rem. 14:01 And let's give it some box-shadow. 14:05 We can do 0 12px 12px rgba(black, 0.15); 14:08 So I think that looks pretty good. 14:16 So now let's start by targeting the header and 14:18 I am nesting this with SCSS. 14:23 In our header we have just our h1, so we can do color, 14:28 and we do have a --heading-color right here. 14:33 So I'll copy that variable name and I'll write var, 14:37 oops, and I'll paste that in. 14:42 Oops, I need to add the opening parenthesis. 14:47 Sweet and it made our settings h1 just a little bit lighter in color. 14:53 I'll give it a margin-bottom of 2rem to give us some spacing and 14:57 is pretty much going to be it for our header. 15:04 So now we have our other child of our settings panel, 15:08 which is the settings container. 15:12 There's really nothing that we'll do in here, so let's just start styling setting. 15:16 Which is each individual setting inside of our panel. 15:22 So in here what we can write is, 15:27 first off let's give them a margin of 1rem and 15:31 auto for the left and right. 15:36 That's not a lot let's maybe do 2rem. 15:41 There we go, looks pretty good. 15:45 So we also have a color set up for our info. 15:47 And that is called --settings-info-color, which is a lighter gray. 15:53 So I'll copy that and I'll paste that inside of our, 15:57 Setting rule and there we go. 16:01 Now one thing that you'll notice in the mockup is that while two things 16:05 that you'll notice about the label is that our title is bold and 16:09 our description is not as bold. 16:13 And they're also each on their own line. 16:16 So let's see if we can tackle that first. 16:18 So, let's target the span or I should say the label, 16:21 And then we'll target the span inside of the label and what we'll do here is, 16:28 we'll set each span display to block to put them each on their own line. 16:33 That worked out perfectly, so now let's target the last-child, or 16:38 last-of-type for the span and set the font weight to 300. 16:45 Sweet, now the only other thing that we'll need to do is make 16:50 sure our toggle switch or our checkbox is all the way to the right. 16:55 And actually because our setting has only two children, 17:01 which is the label and the checkbox this will be perfect for flex. 17:05 So let's give our setting a display of flex, 17:11 we'll justify-content: space-between; 17:15 And just to make sure it stays centered will align-items center. 17:19 Awesome, now our checkbox is all the way to the right. 17:26 But let's give it a little bit of space by setting our 17:29 labels with to 80%, there we go. 17:33 I think that looks pretty good. 17:37 So now the only thing that we have left to do for 17:39 our UI is to turn our checkboxes into toggle switches. 17:42 Which is pretty simple and we can do that with just CSS. 17:47 So let's target our input that's inside of our setting container. 17:50 And we'll give it appearance: none; and just to make sure it's 17:55 compatible with all browsers, we'll do -webkit-appearance: none; as well. 17:59 And this should erase it from the UI or 18:06 set its appearance: none; 18:09 So now what we can do is we can give it a width of, 18:15 let's say 50 px and a height of 25 px. 18:19 And we'll give it a border radius of 25 px for that pill shape. 18:24 And we can't see anything yet because it doesn't have a background color. 18:30 So let's go ahead and add background-color: ; 18:33 And what we'll do is we'll grab --checkbox-bg-unchecked 18:37 variable. We'll paste that in, 18:42 hit Save and now we should see the background of our toggle switches. 18:49 Now we'll want to have a actual switch on the inside of this and 18:55 the easiest way to do that is by using the ::after pseudo-element on our Input. 18:59 So let's go ahead and do that now. 19:06 We can write ::after and we'll wanna position this absolutely, so 19:08 its parent, which is the input, needs to be positioned relative. 19:13 So we'll write position: relative; on the input itself and 19:19 then back into our ::after pseudo-element, we can do position absolute. 19:23 And we'll do a top 50% left of 50% and transform, 19:29 translate negative 50% on both the x and y axis. 19:34 Now we won't see anything yet, 19:41 so what we need to do is give it a height, a width and an a background color. 19:43 So let's do height of 23 px and a width of 23 px. 19:48 And a background-color, of course we have this one set up in a variable too. 19:54 So this is our switch color (--checkbox-switch-color) we'll copy this variable name and 20:00 we'll paste it back into our variable. 20:05 And we're still not seeing anything on here. 20:10 So why is that? 20:16 Okay, so our ::after pseudo-element needs content, 20:18 so set it to content: ''; and there we go, now we see it. 20:22 So, let's give it a border-radius 50 px, I'm sorry 50% so 20:27 that we get that nice circular shape. 20:32 And let's actually make it 22 pixels and height and width or maybe even 21. 20:36 I think 21 looks good. 20:44 We'll adjust the left property to 30% to push it all the way to the left. 20:46 Maybe we'll do the height 20px and width 20px as well, there we go, 20:52 this looks a little bit better. 20:56 And now we have our toggle switches, they don't actually do anything yet 21:00 because we need to adjust the way this looks when the checkbox is in a check 21:04 state, which is pretty easy to do. 21:09 So, let's close our code block for our after pseudo-element and 21:11 let's write our :checked pseudo-class. 21:16 So basically what do we want this to look like when our element is :checked or 21:20 has that checked pseudo-class? 21:26 Well, we'll wanna update the background-color and 21:28 we have a variable for that too, which is --checkbox-bg-checked when it is checked. 21:32 So I'll paste that in and 21:38 the next thing we'll wanna do is target the switch on the inside, 21:40 because when this is checked, we want this to be on the right side. 21:46 Okay so we can write ::after to target our ::after pseudo-element and 21:51 we'll change the left to 70%, there we go. 21:57 So our second item is checked and now it's unchecked and 22:01 you see that our checkbox appears like a actual toggle switch. 22:06 But let's give this some transitions so that it can animate pretty smoothly. 22:13 And the way that we can do that is by giving a transition 22:20 of background-color on the input element itself of .3 22:25 seconds ease (transition: background-color, .3s ease); and then we'll wanna also transition, 22:30 the left property on our ::after pseudo-element. 22:36 So, we'll do .3 seconds ease for that as well. (transition: left .3s ease) 22:41 And now, when we click, we have a nice subtle animation, 22:45 whenever we click our check box. 22:50 Sweet, only thing I'm not liking is the width of our input, 22:55 so let's maybe put this to 45px. 23:02 There we go, this looks a little bit nicer, I like that. 23:07 So that's it, our UI is complete. 23:12 And we were able to do this with just HTML. 23:14 So what I wanna do now is render these settings in the JavaScript dynamically, 23:18 which is actually pretty simple to do. 23:23 So the first thing I'll do is I'll go back to our GitHub and 23:27 I'm gonna' copy our list of objects that holds all this data. 23:30 And in our text editor I'm gonna go to our scripts and 23:37 open up app.js and I will create an array I'll call 23:42 this const settingsData and I'll set it equal to an empty array. 23:47 And then inside this array I will paste our list 23:53 of objects, so now we have an array of objects. 23:58 Now that we have this, let's go ahead and comment out our 24:03 individual settings, so that there's nothing in our UI. 24:08 Awesome, so now our UI looks pretty empty. 24:22 Let's see if we can dynamically render this content. 24:25 So, because this is an array, what we can do is loop over this and do something with 24:29 each item in the array and the best way to do that is by using the forEach method. 24:34 So we'll write our settings array name, 24:40 which is the settingsData, we'll do settingsData.forEach. 24:42 And for each setting in the array, what do we wanna do? 24:47 Well, we wanna create the setting UI. 24:50 So this sounds like a really good job for a function. 24:54 So let's write createSetting as a function. 24:56 And as a parameter we'll use each setting that's being processed through the loop. 25:01 So let's go ahead and create this function down below. 25:08 You can write function createSetting(data) {}, and we wanna use data as an argument. 25:13 And what we wanna do is basically render the HTML that we made earlier. 25:18 So let's come in here and copy this and we can paste that, 25:24 well, let's not pasted it in here yet. 25:29 Let's see, we want to create this markup inside of this container. 25:34 So this settings id we'll need this. 25:42 Let's do const settings = document.getElementById('settings') and 25:45 we'll wanna do settings.innerHTML += and 25:53 we'll do backticks so that we can interpolate some data. 25:58 So now let's paste in that markup. 26:05 And let's fix the indentation a little bit, there we go. 26:09 So what we'll wanna do is interpolate this for 26:15 attribute for our label, the id for 26:19 the checkbox, the title and the description. 26:23 So each time this settingsData.forEach() runs, 26:28 it will give us the current item being processed. 26:32 So setting the first time this goes through the loop this setting variable 26:37 right here will equal this first item which is our first object being processed 26:42 and in our function, we're using the data argument to represent that. 26:48 So what we can do is interpolate these values. 26:54 And we can do that by writing a $ and then two opening and closing curly braces. 27:01 So let's go ahead and do that and now what we can do is we can take whatever 27:10 data we're getting passed into this function when we're calling it and 27:15 do data.uid because uid will be our unique id that we're using. 27:21 And then for the title, we'll do data.title, because we have a title property. 27:27 And then we also have a description property, so let's copy that. 27:34 We can do data.description and 27:37 then also we'll need that uid again for our id for our check box. 27:40 Sweet, and there we go I hit save and 27:45 now we still have our settings panel. 27:50 And this time the data is being rendered dynamically. 27:56 So that is it for rendering the data dynamically with JavaScript, 28:00 so our markup, we can delete all of this. 28:05 And I like to put in a comment that says dynamic. 28:09 dynamically rendered. 28:14 Okay, so let's hit Save and 28:21 now let's see if we can't get this dark mode toggle to work. 28:23 So what we'll want to do is when this is checked, this is still a checkbox. 28:28 So we have access to the change event listener on this. 28:33 So we'll wanna listen for that. 28:38 And when this is checked, we wanna add a class of dark to our settings panel, 28:40 which is this big white settings panel, it holds everything in there. 28:44 So let's see how we can do that. 28:50 Let's write an if statement to see if dark mode exists, we have this setup as an id. 28:53 So if we inspect the page, let's make this a little bit bigger so that we can see. 29:00 If I click on this checkbox in here, 29:08 it has an id of dark mode which you can see right there. 29:11 And what we wanna do is if the page has that, we want to set an eventListener on it, 29:17 so if, let's do document.getElementById('darkMode') 29:23 And we'll need that again, so let's just copy this. 29:30 So if this exists, we wanna add an event listener to it. 29:33 And this would be a change event, because this is a checkbox. 29:38 So when we detect a change, we want to see if it's checked or not. 29:45 So we can do that by using the event parameter. 29:49 So if event.target.checked, 29:52 we want to add the class of dark. 29:56 So basically we're saying if this checkbox here is checked 30:00 if it's in a checked state we want to add the dark class to our settings-panel, so 30:05 we should probably set up a variable for our settings-panel 30:12 we'll do const settingsPanel = document.getElementById('settingsPanel); 30:17 And if you remember, we set this up with settingsPanel earlier. 30:23 Let's take a look in the markup. 30:27 So our div that holds the entire UI is in this id settingsPanel. 30:30 So now that we have this setup in an id, I mean a variable that we can use, 30:38 we'll do settingsPanel.classlist.add('dark'). 30:44 And if it's not checked, we can write else settingsPanel.classlist.remove('dark'). 30:49 So let's hit save and see if this worked. 30:57 Sweet, we now have our variables overriding. 31:03 And this is happening because when we come up to our style sheet, the settings panel, 31:07 when it has a class of dark, we'll have these variables versus these, 31:13 and these are the variables that we're using to build out and style our UI. 31:19 So the only other thing that I'd like to do is make the transition for 31:25 these a little bit better. 31:30 So let's go and take a look at the settings panel. 31:32 It has a background color so we'll wanna transition that as well so 31:36 we can do transition background-color. 31:40 And we'll do transition: background-color .3 seconds ease; and 31:43 I'll copy this .3 seconds ease because we'll use this a ton. 31:45 Our header has a color so 31:52 we'll want to transition that will do transition: color .3 ease; 31:53 Each setting has a color as well so we'll transition that, 32:00 will do transition: color .3s ease; 32:04 Let's see what else that might be it let's hit Save actually I wanna say 32:09 our ::after pseudo-element has a background-color as well so we can add that. 32:16 So one way to add multiple transitions is to just separate it by a comma. 32:23 So we can do transition: background-color .3s ease; 32:30 So I'll hit Save and now let's check out our UI. 32:35 Sweet, it all has a very subtle change from its light theme to its dark theme. 32:39 Let's make this a little bit bigger. 32:46 Sweet, this looks really, really good. 32:50 And this didn't take a whole lot of code. 32:53 We did a lot of it through just CSS and that about covers it for building out this 32:54 awesome interactive settings panel with just HTML, CSS, and JavaScript. 32:59
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up