Back to Freecodecamp

Build a Stylized To-Do list

curriculum/challenges/english/blocks/lab-stylized-to-do-list/66c051d13a6a20255a963695.md

latest8.9 KB
Original Source

--description--

In this lab, you will practice the different styles that can be applied to links when they are hovered over, focused, clicked, and visited.

Objective: Fulfill the user stories below and get all the tests to pass to complete the lab.

User Stories:

  1. You should have one unordered list with the class todo-list.

  2. Inside the unordered list, you should have four list items.

  3. Inside each list item, there should be:

    • An input element with the type checkbox and id set to a unique value.
    • A label element with the for attribute set to the corresponding input element's id.
    • An unordered list with the class sub-item.
    • A list item with an anchor element in it. The anchor should have the class sub-item-link, a valid href value, and a target value that makes the link open in a new tab.
  4. Your a elements should not have any text decorations.

  5. You should set the text color of unvisited links to a color of your choice.

  6. When your links are visited, the color should change to another color of your choice.

  7. When your links are hovered over, the color should change to another color of your choice.

  8. When your links are focused, there should be a colored outline around the link.

  9. When your links are clicked, the color should change to another color of your choice.

Note: Be sure to link your stylesheet in your HTML and apply your CSS.

--hints--

You should have one unordered list with the class todo-list.

js
assert.exists(document.querySelector('ul.todo-list'));
assert.lengthOf(document.querySelectorAll('ul.todo-list'), 1);

You should have four list items inside the unordered list.

js
const li = document.querySelectorAll('ul.todo-list > li');
assert.lengthOf(li, 4);

The li inside the ul with the class todo-list should contain an input element with the type of checkbox.

js
const checkboxes = document.querySelectorAll(
  'ul.todo-list li input[type="checkbox"]'
);
assert.lengthOf(checkboxes, 4);

The li inside the ul with the class todo-list should contain a label element.

js
const labels = document.querySelectorAll(
  'ul.todo-list li label'
);
assert.lengthOf(labels, 4);

All input elements should have an id.

js
const inputs = document.querySelectorAll('input');
assert.isAbove(inputs.length, 0);
for (let input of inputs) {
  assert.isAbove(input?.id.length, 0);
}

All label elements should have a for attribute.

js
const labels = document.querySelectorAll('label');
assert.isAbove(labels.length, 0);
for (let label of labels) {
  assert.isAbove(label.htmlFor.length, 0);
}

All label elements should have some text.

js
const labels = document.querySelectorAll('label');
assert.isAbove(labels.length, 0);
for (let label of labels) {
  assert.isAbove(label.innerText.length, 0);
}

The id and for attributes of the input and label elements pairs, should have corresponding values.

js
const labels = document.querySelectorAll("label");
assert.isNotEmpty(labels);

document.querySelectorAll("input").forEach((input, index) => {
  assert.equal(input.id, labels[index].htmlFor);
});

After the label elements, there should be an unordered list with the class sub-item.

js
const labelSbItems = document.querySelectorAll('ul.todo-list li label + ul.sub-item');
assert.lengthOf(labelSbItems, 4);

The li inside the ul with the class sub-item should have an anchor element with the class sub-item-link.

js
const allItems = document.querySelectorAll(
  'ul.todo-list li label + ul.sub-item li a.sub-item-link'
);
assert.lengthOf(allItems, 4);

All anchor elements should have a valid href attribute.

js
const links = document.querySelectorAll('a');
assert.isAbove(links.length, 0);
for (let link of links) {
  assert.isAbove(link.href.length, 0);
}

All anchor elements should have text.

js
const links = document.querySelectorAll('a');
assert.isAbove(links.length, 0);
for (let link of links) {
  assert.isAbove(link.innerText.length, 0);
}

Each a element should have a target attribute with the value of _blank.

js
const anchors = document.querySelectorAll('a');
assert.isAbove(anchors.length, 0);
for (let anchor of anchors) {
  assert.equal(anchor.target, '_blank');
}

Your a elements should not have any text decorations.

js
assert.isTrue(
  new __helpers.CSSHelp(document).getStyle('a.sub-item-link')
    ?.textDecoration === 'none' ||
    new __helpers.CSSHelp(document).getStyle('a')?.textDecoration === 'none' ||
    new __helpers.CSSHelp(document).getStyle('.sub-item-link')
      ?.textDecoration === 'none'
);

Unvisited links should have a text color set to a color of your choice.

js
assert.exists(
  new __helpers.CSSHelp(document).getStyle('.sub-item-link:link')?.color ||
    new __helpers.CSSHelp(document).getStyle('a:link')?.color ||
    new __helpers.CSSHelp(document).getStyle('a.sub-item-link:link')?.color
);

The links should change color when hovered over.

js
assert.exists(
  new __helpers.CSSHelp(document).getStyle('.sub-item-link:hover')?.color ||
    new __helpers.CSSHelp(document).getStyle('a:hover')?.color ||
    new __helpers.CSSHelp(document).getStyle('a.sub-item-link:hover')?.color
);

The links should change color when they are being clicked.

js
assert.exists(
  new __helpers.CSSHelp(document).getStyle('.sub-item-link:active')?.color ||
    new __helpers.CSSHelp(document).getStyle('a:active')?.color ||
    new __helpers.CSSHelp(document).getStyle('a.sub-item-link:active')?.color
);

The links should have an outline when focused.

js
const css = new __helpers.CSSHelp(document);
assert.exists(
  css.getStyle('.sub-item-link:focus')?.outline ||
    css.getStyle('a:focus')?.outline ||
    css.getStyle('a.sub-item-link:focus')?.outline ||
    css.getStyle('.sub-item-link:focus')?.border ||
    css.getStyle('a:focus')?.border ||
    css.getStyle('a.sub-item-link:focus')?.border
);

The links should change color once visited.

js
assert.exists(
  new __helpers.CSSHelp(document).getStyle('.sub-item-link:visited')?.color ||
    new __helpers.CSSHelp(document).getStyle('a:visited')?.color ||
    new __helpers.CSSHelp(document).getStyle('a.sub-item-link:visited')?.color
);

--seed--

--seed-contents--

html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Styled To-Do List</title>
</head>

<body>

</body>

</html>
css

--solutions--

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Styled To-Do List</title>
    <link rel="stylesheet" href="styles.css" />
  </head>

  <body>
    <div class="container">
      <h1>My To-Do List</h1>
      <ul class="todo-list">
        <li>
          <input type="checkbox" id="task1" />
          <label for="task1">Explore gaming keyboards</label>
          <ul class="sub-item">
            <li>
              <a href="#" target="_blank" class="sub-item-link">Store link</a>
            </li>
          </ul>
        </li>

        <li>
          <input type="checkbox" id="task2" />
          <label for="task2">Finish the report</label>
          <ul class="sub-item">
            <li>
              <a href="#" target="_blank" class="sub-item-link"
                >Request Access</a
              >
            </li>
          </ul>
        </li>

        <li>
          <input type="checkbox" id="task3" />
          <label for="task3">View Phone's Warranty</label>
          <ul class="sub-item">
            <li>
              <a href="#" target="_blank" class="sub-item-link"
                >View Receipts</a
              >
            </li>
          </ul>
        </li>

        <li>
          <input type="checkbox" id="task4" />
          <label for="task4">Check Processor Specs</label>
          <ul class="sub-item">
            <li>
              <a href="#" target="_blank" class="sub-item-link"
                >View Model Number</a
              >
            </li>
          </ul>
        </li>
      </ul>
    </div>
</body>
</html>
css
body {
  font-family: Arial, sans-serif;
  background-color: #f0f0f0;
  margin: 0;
  padding: 20px;
}

.container {
  max-width: 400px;
  margin: 0 auto;
  background-color: #fff;
  padding: 20px;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

h1 {
  text-align: center;
  color: #333;
}

.todo-list {
  list-style-type: none;
  padding: 0;
}

.todo-list li {
  margin-bottom: 15px;
  line-height: 1.6;
  padding: 10px;
  background-color: #e5f1e5;
  border-radius: 10px;
  position: relative;
}

a.sub-item-link {
  margin-left: 10px;
  text-decoration: none;
}

.sub-item-link:link {
  color: blue;
}

.sub-item-link:visited {
  color: purple;
}

.sub-item-link:hover {
  color: red;
}

.sub-item-link:focus {
  outline: 2px solid blue;
  outline-offset: 2px;
}

.sub-item-link:active {
  color: green;
}

.sub-item {
  list-style-type: square;
}