Check out a free preview of the full Vanilla JavaScript Projects course:
The "Clock Solution: Random Position & Color" Lesson is part of the full, Vanilla JavaScript Projects course featured in this preview video. Here's what you'd learn in this lesson:

Anjana continues the solution to the Clock exercise. Random values are generated and applied to the displayed time using the top, left and color CSS styles.

Get Unlimited Access Now

Transcript from the "Clock Solution: Random Position & Color" Lesson

[00:00:00]
>> Speaker 1: Now is the fun part of making it look for some definition of pretty, pretty [LAUGH].
>> Speaker 2: So, there's lots of ways we could style this, but same as HTML, we have the power within our JavaScript to change the styles of elements that will be interpreted by the browser's CSS engine, which is a whole other ball of wax, to make things look nice.

[00:00:28]
>> Speaker 1: So what did folks do?
>> Speaker 2: How did we style this?
>> Speaker 1: And this is now starting to be the open-ended question of taste.
>> Speaker 2: But one thing we said is, it would be nice to move it around, right?
>> Speaker 1: So there's a few different ways we could do this, but since these are, if we check the little in page style tags here in this little mini stylesheet.

[00:00:56]
>> Speaker 2: These are positioned relatively, which means we can choose and specify exactly where within their parent element, this p element is going to get placed.
>> Speaker 1: That can be done with top, for example, if I did top 100px and, I don't know, left 50px, I could do that in CSS.

[00:01:33]
>> Speaker 2: And this is, again, not a CSS course by any stretch of the imagination, but we see it moved.
>> Speaker 1: So if I don't necessarily set those in my CSS right here, but if I set them through JavaScript and change it up, I can get a very impressive to a 90s child animated [LAUGH] animated clock.

[00:01:57]
>> Speaker 2: So let us figure out how we can get randomness involved, so that we can, instead of just having topOffset = 100px and leftOffset is, what did I say, 50px or whatever, we don't want these to be hardcoded values, we want them to be random.
>> Speaker 1: So, how did people do this?

[00:02:25]
>> Speaker 2: Yeah, anybody wanna share their solution?
>> Speaker 1: Yeah, go ahead.
>> Speaker 2: Math.random [LAUGH]
>> Speaker 1: Math.random is gonna be our friend here.
>> Speaker 2: For sure, but we still have a couple more steps to go.
>> Speaker 1: So if I call, if I get a new value from Math.random.
>> Speaker 2: This is gonna be a random number, as we said, between 0 and 1, right?

[00:02:49]
>> Speaker 1: Now if I were to, let's say, have the topOffset now, I'm moving it around in VS Code, but whatevs.
>> Speaker 2: If I were to have this be a random number plus px and then, where are we, okay?
>> Speaker 1: And then on my text, we could set an attribute, let's say, of top, sorry, style, to a little mini stylesheet where we have,
>> Speaker 2: Let's say, okay, we have the first part of the CSS rule, top, and then we have a, okay, all right, thank you VS Code, you're so helpful.

[00:03:41]
>> Speaker 1: Top offset.
>> Speaker 2: Then we might get something interesting, let's see what happens.
>> Speaker 1: It looks exactly the same.
>> Speaker 2: Any guess why this is?
>> Speaker 1: Because the random number is a portion of a single pixel.
>> Speaker 2: Exactly.
>> Speaker 1: You need to scale it to the window size.

[00:04:06]
>> Speaker 2: Exactly, so we're essentially moving this like a negligible amount.
>> Speaker 1: So we wanna scale up that value, as you said, and we can use various values to do that.
>> Speaker 2: But one thing that might simplify our lives.
>> Speaker 1: We have access to the whole browser, so we know all kinds of stuff about the window, how big it is.

[00:04:28]
>> Speaker 2: We're getting to a world where we can even get more detailed information about, layout, as it's happening, whatever.
>> Speaker 1: But we could also use the percentage convenience of CSS and make our lives a little bit easier.
>> Speaker 2: So if I add a percentage and maybe multiply, why don't I get my random number times, okay, well, this math equation is not gonna work out, okay.

[00:04:58]
>> Speaker 1: So if I multiply my random number times 100, now I will have something between 0 and 100 instead of 0 and 1, and I can add a percent.
>> Speaker 2: Let's see if that made any difference?
>> Speaker 1: Well, no.
>> Speaker 2: What happened?
>> Speaker 1: Can you see in the inspector what it's setting [CROSSTALK]

[00:05:21]
>> Speaker 2: We sure can, and that's exactly what we're gonna do, and it's entirely possible that something silly is going on.
>> Speaker 1: All right, yeah, okay.
>> Speaker 2: What happened?
>> Speaker 1: Why is this staying put?
>> Speaker 2: This was an intentional mistake because we're learning things.
>> Speaker 1: Is it cuz it's never changing?

[00:05:44]
>> Speaker 2: Did you set it outside of the setInterval?
>> Speaker 1: So this is interesting, right?
>> Speaker 2: I'm giving it this random value every time, and we see something's happening every three seconds, the time is actually changing.
>> Speaker 1: Does it change if you reload?
>> Speaker 2: Go back to your code.

[00:06:01]
>> Speaker 1: Does it change if I reload?
>> Speaker 2: Let's find out.
>> Speaker 1: Well, it's a little hard to tell, but what's happening is we chose a random number once and for all, yeah?
>> Speaker 2: You've got const for your offset.
>> Speaker 1: We are using a const, and that,
>> Speaker 2: Adds a little layer of complication, so we can talk about that later.

[00:06:33]
>> Speaker 1: But most importantly, the call to Math.random is not happening within the callback function that I'm passing to the interval.
>> Speaker 2: So that means this call to Math.random only runs once when I'm defining this variable.
>> Speaker 1: And then every three seconds, I keep setting it to the same value.

[00:06:58]
>> Speaker 2: Even though, for example, the date is changing because we notice the date is being newly reborn every time this updateTime function runs.
>> Speaker 1: And the setInterval here schedules this updateTime function to run every three seconds.
>> Speaker 2: It does not schedule this entire script to run every three seconds.

[00:07:22]
>> Speaker 1: It does not schedule JavaScript to time travel back 3,000 milliseconds ago to find out and rerun.
>> Speaker 2: No, it only knows what we have in here.
>> Speaker 1: And this is getting at something very interesting, which we're gonna talk about a bit later, related to how scope works in JavaScript, so we'll have a little refresher on scope there.

[00:07:46]
>> Speaker 2: But for now, if I were to take this calculation here, and move it in to the body of the function.
>> Speaker 1: That I want to call.
>> Speaker 2: We might have a little bit better of an experience, it moved a tiny bit, but it still moved.
>> Speaker 1: Okay, now, it's moving around, and sometimes it's moving up and sometimes it's moving down, but this feels better.

[00:08:13]
>> Speaker 2: This is more in the direction of what we wanted, but it's still always on this left side of the screen.
>> Speaker 1: So what I could do is we could even get a, we could change this.
>> Speaker 2: So let's say I'm gonna just get the top offset by calling math.random and multiplying it by 100.

[00:08:32]
>> Speaker 1: And then I could get a left offset by making a new call to math.random.
>> Speaker 2: Because if I use that same math.random value, it's just gonna be always on the diagonal, I guess.
>> Speaker 1: So if I now, what else can kind of make our life easier here is a fancier way of doing this little plus operation of concatenating strings.

[00:08:58]
>> Speaker 2: What if I had a way to just write the string once, and then fill in the values I needed, that would be a, anybody know what they're called?
>> Speaker 1: A string template literal.
>> Speaker 2: A string template literal in JavaScript, exactly, which I can make with my good friend, the backtick.

[00:09:13]
>> Speaker 1: So, in general, what I want CSS to see is something like top blah blah percent, left blah blah percent.
>> Speaker 2: And I can tell JavaScript to inject or interpolate the values of these blah blahs by using a dollar sign and curly braces.
>> Speaker 1: Which is saying, okay, leave the string land and reenter JavaScript land and evaluates what's between the braces.

[00:09:43]
>> Speaker 2: So this is all a little bit of review here if some syntax, so I can do topOffset% and similarly, leftOffset%.
>> Speaker 1: The other thing I could do is event just put this whole operation in here since I'm not really using this offset value anywhere else.
>> Speaker 2: So ideally this should work pretty much the same as it did before, and now it is moving in both dimensions.

[00:10:17]
>> Speaker 1: Huzzah!
>> Speaker 2: And so we can do something similar with color values, for example, to add a little pizzazz, and for that, I would recommend.
>> Speaker 1: Well, did folks manage to change the color of it, yeah, okay.
>> Speaker 2: What did you use?
>> Speaker 1: Well, to be perfectly transparent, copilot told me to do this [LAUGH].

[00:10:42]
>> Speaker 2: Okay, so Github's copilot, AKA the AI developer that makes us all feel things about ourselves [LAUGH].
>> Speaker 1: You certainly have to, you certainly need to check it.
>> Speaker 2: Exactly, so yes, so copilot.
>> Speaker 1: Still got to know what you're doing.
>> Speaker 2: Copilot can be very useful, but it, for example, does not know JavaScript.

[00:11:06]
>> Speaker 1: It knows the internet, and the internet kinda knows JavaScript, but it also has been knowing JavaScript for many years now.
>> Speaker 2: And JavaScript has changed a lot, and all kinds of blog posts are just plain wrong, so word of warning.
>> Speaker 1: All right, what did we learn from Copilot?

[00:11:22]
>> Speaker 2: What myself and Copilot came up with was randomizing RGB between 0 and 255.
>> Speaker 1: Okay, great.
>> Speaker 2: So, in CSS, I could do something like color RGB, I don't know, 100 and get a beautiful muddy color.
>> Speaker 1: That's not gonna help, let's do 255.
>> Speaker 2: Okay, now I got a bright green, because this is the red, green, blue side, up to the green, we got a fancy thing.

[00:11:57]
>> Speaker 1: So, same logic as before, we can scale our random value to a value in the domain of RGB.
>> Speaker 2: So for example, I could do R is like math.random times 255 and so on and so forth for g and b.
>> Speaker 1: And then I can add into my handy dandy little template here, color rgb.

[00:12:43]
>> Speaker 2: And then do my r, my g, and my b, now let's see what happens.
>> Speaker 1: Well, all right, we allowed the thing to be positioned all the way near 100%, so that's why it's sticking over the sides.
>> Speaker 2: But we are indeed getting different colors now, so that's exciting.

[00:13:07]
>> Speaker 1: Another thing that could make our life easier and make math.random have to do a little bit less work.
>> Speaker 2: Is there's also a color space function HSL, have folks worked with this before.
>> Speaker 1: So, HSL stands for Hue Saturation Luminance, let's double check.
>> Speaker 2: All right, so, if I type in HSL into our friend MDN, we see that in CSS world, HLSL takes a hue.

[00:13:45]
>> Speaker 1: A saturation and a lightness instead of analogous to the R, the G, and the B that RGB takes red, green blue.
>> Speaker 2: And so this is a little bit strange to wrap your head around at first.
>> Speaker 1: But what it means is that instead of with RGB all of the values affect what the color is gonna be all of the different ways.

[00:14:06]
>> Speaker 2: And it's hard to kind of predict what a combination of those three at least if you're me.
>> Speaker 1: It's hard to predict what a combination of those three is gonna look like.
>> Speaker 2: So HSL is a fun thing where basically saturation, the second value is very much similar to saturation like on your TV settings or whatever.

[00:14:27]
>> Speaker 1: So it sort of dials up the intensity, luminance is sort of like brightness or how kind of white and shiny the color looks.
>> Speaker 2: And then the hue is gonna be something from the color wheel, where we basically have all of the colors in one space.
>> Speaker 1: Instead of having separate spaces for R and G and B.

[00:14:47]
>> Speaker 2: And so what we could do is pick kind of a, okay, let's, so I could do a S and an L.
>> Speaker 1: I'm doing a little destructuring here to only have one line of code.
>> Speaker 2: Not necessary, but, we're trying to sprinkle in our fancy syntax, so why not.

[00:15:15]
>> Speaker 1: So I can just, I could actually set these to something that doesn't change between different calls.
>> Speaker 2: Which means I could even move this out of the body of the callback function.
>> Speaker 1: And I could have this be something like I don't know what's a good value like, 75%.

[00:15:32]
>> Speaker 2: We can tweak it later and now I can get my H inside the body of my callback.
>> Speaker 1: And in this case the wheel is measured in degrees, so we actually kind of, we measure it in degrees around a circle like an angle.
>> Speaker 2: And so you'll see here that like often we can put just like D, E G.

[00:15:59]
>> Speaker 1: For degrees, to this value instead of percent or whatever.
>> Speaker 2: And so since the wheel has 360 of those degrees, we can choose our scaling value to be 360 and now, we can do hsl, hsl with our s and l don't change because we can have all the same brightness or whatever, but our hue will change.

[00:16:29]
>> Speaker 1: So, just a fun other color space.
>> Speaker 2: Let's see if this worked or if I got something problematic going on.
>> Speaker 1: I mean, it's changing color.
>> Speaker 2: I think this is a good lesson in co-pilot because this is a better solution because this is accessible, mine every once in a while I do a really dark color, and then you can't read it.

[00:16:55]
>> Speaker 1: Versus this, you can control the brightness.
>> Speaker 2: Exactly.
>> Speaker 1: Or you can do some scaling thing on the RGB values to keep it up above.
>> Speaker 2: You'd have to do some work on the RGB side to make sure that the colors are bright enough.
>> Speaker 1: You didn't put it unit specifier in the string.

[00:17:14]
>> Speaker 2: Good call.
>> Speaker 1: So, I'm just wondering if that used the default unit?
>> Speaker 2: I think it might be defaulting to degrees, but you know where we could go to check.
>> Speaker 1: Yeah.
>> Speaker 2: All right, so,
>> Speaker 1: The function also accepts a legacy syntax used by Anjana, [LAUGH] in which all values are separated with commas.

[00:17:35]
>> Speaker 2: You don't actually need the commas, but they were already there from our cheapy thing.
>> Speaker 1: And so, yes, so what value can h be?
>> Speaker 2: It can be a number, an angle, or none, which represents the hue angle.
>> Speaker 1: What does that mean?
>> Speaker 2: I don't know, let's go find out, but not right now.

[00:17:52]
>> Speaker 1: So, yes, and then we'll find all kinds of different examples of like, okay, yes, if I can just pass in a degree value as a number and it'll interpret it as a degree value.
>> Speaker 2: But excellent point that I wanna be careful when swapping out my template strings.

[00:18:08]
>> Speaker 1: Cuz as I seem to be finding out over and over again today, hard coding stuff in any kind of string is a risky business.
>> Speaker 2: All right, so [LAUGH] yes, okay, so we have now successfully with a lot of JavaScript reproduced what my old DOS, well no, not the DOS one, but the first color computer I had, I think could do.

[00:18:35]
>> Speaker 1: Windows 95.
>> Speaker 2: There we go.
>> Speaker 1: Your CRT won't get burned in now.
>> Speaker 2: Exactly, exactly.
>> Speaker 1: [LAUGH]
>> Speaker 2: [INAUDIBLE] 286.
>> Speaker 1: And another good point about the, so not only is it convenient that we only had to set one random value here for HSL, but another advantage is because that RGB randomness sometimes turns up really dark values and this is in dark mode.

[00:18:58]
>> Speaker 2: Or vice versa if we were in light mode, could turn up really light value sometimes that is not good for all of us.
>> Speaker 1: Because if we have in any way any kind of difficulty with vision or things like that, we have a problem differentiating the text from the background, and that means some of the text could essentially be non-existent to us.

[00:19:27]
>> Speaker 2: So this is an accessibility issue and there are recommendations for what amount of contrast you should have between your text or whatever, and background.
>> Speaker 1: And I'm not an expert in all of that, but you know who is?
>> Speaker 2: MDN.
>> Speaker 1: So, and there's links in there to the accessibility guidelines for web content, so we want to generally be trying to be mindful of that.

[00:19:53]
>> Speaker 2: Not just with color, also with all kinds of stuff, like putting alt tags on images, for example.
>> Speaker 1: So that when your path value is wrong and the image doesn't load, you at least get some kind of string, and everybody else who's using a screen reader gets some useful information.

[00:20:07]
>> Speaker 2: As opposed to just thinking there's a blank page because someone injected a bunch of JavaScript without updating things in an accessible way.
>> Speaker 1: Sidebar, accessibility is important.
>> Speaker 2: Okay, I think we have had a win and we can take it, we'll take the W.
>> Speaker 1: And for our reward, we get a random color changer that somebody made for a very fancy music video with Drake in it, where he could do his little dance.