Lab 5 - CSS: Layout
Due: .
Categories:
7 minute read
Layout
In this lab, you will use CSS and JavaScript to make a reactive page that changes layout dynamically. You will use a combination of fixed and flex-box display properties, then use buttons to change what classes are controlling the layout.
All code must validate cleanly (no errors or warnings) through the standard validation tools listed below. You must resolve all errors and warnings before submission. For individual CSS properties, please refer to the MDN reference list.
Starting Code
Start by extracting provided source code and opening the files in your preferred text editor:
For this lab, you will need to modify all three files and submit them to Gradescope.
Semantic structure and fixed navbar
- Start with the
index.html
file. Create anav
element containing an unordered list. Each item will contain abutton
with anid
attributed as specified in the file. No classes or other attributes should be added to any of these elements, as all presentation and dynamic features will be added using CSS and JavaScript. - Inside the
main
, add 2 randomly selected SQUAREimg
elements (200x200). Use picsum.photos to get the URLs for these images. Make sure to addalt
text.- At this point, you should see a list with three bullet points with some ugly buttons next to them. Below that you should see two random images with a little bit of spacing around them.
- Add a
link
element to thehead
to referencestyles.css
and reload the page. What changed?
- In the
styles.css
file, start by getting theheader
andmain
into position. To do this, specify the appropriate properties to theheader
andmain
rules (includingdisplay
andposition
) according to the comments. Set the color variables in the:root
rule and give theheader
a background so you can see it.- Reload the page to check your progress.
- Wow, those buttons look bad! Let’s fix them.
- Use descendant selectors to update the
nav
list and list items. Get rid of the bullet points, add a right margin, and switch the list items to be in a row rather than a column (i.e., switch them from block to inline). - They’re still kind of ugly. Use a descendant selector to update the
button
style properties. Add some padding and increase the font size. Give them no border but useborder-radius
to curve the corners. Use those spiffy color variables you defined up in:root
. - OK, now we’re making progress.
- Use descendant selectors to update the
Dynamic buttons
- Buttons look and feel so much better when they appear to react when we move the mouse
over them or click on them. Let’s take care of that.
- Add a new rule for the
button
when it is in the:hover
state. When this happens, give the button anoutline
that is at least 3px in size and matches the text color of the button. - We won’t be able to use it yet, but add another rule based on the
button
also having a class calledactive
. In this class, switch the text and background colors of the button. - That’s starting to look nice. In this image, the “Spread Out” button
has the
active
class while the mouse is hovering over “Rotate Direction”.
- Add a new rule for the
- The
:hover
pseudoclass is automatically built into the web browser, but we need to do some work for theactive
class. It’s JavaScript time!- Add a
script
element toindex.html
to referenceflex.js
then open this file. - The default implementation shows a pop-up box when you click the “Spread Out”
button. Get rid of that and replace it with code that adds or removes the
active
class we created a bit ago. To do this, we’re going to manipulate thespreadButton.classList
. Rather than keeping all the classes in a string (which you would do in HTML), the DOM maintains them as a list. - If you write more than one line of code here, you’re doing it wrong. Yes, you can
add some logic this:
But really? Why? Just use
if (spreadButton.classList.contains('active') { // Button has class="active" so remove it spreadButton.classList.remove('active'); } else { // Button doesn't have the class so add it spreadButton.classList.add('active'); }
toggle
, which does that work for you. - If you click on the “Spread Out” button, it should turn dark. Click it again and
it goes back to the original coloring. If it works, add some more code to do the
same thing for the “Rotate Direction” button. You’ll need to add a new variable
at the top of the file, then add code similar to what was provided for the
spreadButton
toward the bottom of the file.
- Add a
Flex
- Toggling button colors is cool, but it’d be even better if the buttons…actually
did something? Let’s start with spreading things out.
- Head back to
styles.css
. Create a new rule that only applies to themain
element when it has the “spread” class. This rule will use thespace-around
value to add spacing to elements along the main axis. - Give it a try to make sure you’ve got the flex-box set up properly. If you load
page, the images should be centered vertically and pushed all the way to the
left edge of the window. But if you add the
class="spread"
to themain
element in the HTML and reload the page, they should be spaced out horizontally. Good? Good. Now, removeclass="spread"
from your HTML. We’re controlling that in other ways. - Back to
flex.js
. We need to add a newmainElement
global variable and usedocument.querySelector
to grab themain
. (Note that we are NOT adding an event listener tomain
, so don’t copy that line of code.) - Just like the buttons have a
classList
,main
does, too. Add another line of code to yourspacing
function so that it toggles the “spread” class. - Click the “Spread Out” button a few times. The images should switch back and forth from the default positioning on the left to spaced out horizontally. And the button should still be inverting colors each time.
- Head back to
- Now let’s add some rotation.
- Add some more CSS to switch the flex-box to a column when the “vert” class is
present for the
main
element. Just like spreading things out, add some JavaScript code to toggle this class. - Notice what happens if you click both buttons to activate both classes. Can you explain why? Does it matter which class you turn on/off first?
- Add some more CSS to switch the flex-box to a column when the “vert” class is
present for the
DOM manipulation
- We’ve still got one more button hanging around, so let’s do something with it.
- Add a new global variable and the associated initialization code at the bottom
of the
flex.js
file to reference the button. - In
addImg
, usedocument.createElement
to create a newimg
element. Set thesrc
andalt
attributes to grab another random square image. HINT: HTML attributes just become object fields in the DOM; soimgElement.src
can be used to view or change the<img src="...">
field. - Reload the page and click the “Add Image” button. Nothing happens. Huh. Oh,
that’s right, we created the
img
element, but we didn’t tell the browser where we wanted the image to be added. UseappendChild
to add it as a new child of themain
element.
- Add a new global variable and the associated initialization code at the bottom
of the
Going further
- The original
index.html
file may have looked a bit odd. It was missing closing tags forhead
,body
, andhtml
. It turns out, that’s perfectly fine and valid. The HTML5 spec indicates that certain tags, including closing tags, are optional. - If you add enough images and make the flex-box into a column, notice that the
header
bar covers up the images. What CSS rule could you add to fix this? - What if we don’t like one of the random images? Let’s find a way to delete it.
In the initialization code, use
document.querySelectorAll
to get all of the images. This function returns an array, so you can doimages.forEach
to loop through them. Use this to add an event listener to callremoveImg
for each one. In this function, callremove
on the passed parameter. This won’t work. Use the console to print out the element that gets passed and try to figure out the problem. You can then read the textbook chapter on events to try to fix it.