Back to Freecodecamp

Build a Book Inventory App

curriculum/challenges/english/blocks/lab-book-inventory-app/66a207974c806a19d6607073.md

latest27.5 KB
Original Source

--description--

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

User Stories:

  1. You should have an h1 element with the text Book Inventory.
  2. You should have a table element with columns named Title, Author, Category, Status, and Rate.
  3. Your table should have at least four rows, the first for the column headings and the rest filled with book information.
  4. Each table row inside the table body should have either the class read, to-read, or in-progress.
  5. td elements of the Status column should contain a span element with the class of status surrounding the text Read, To Read, or In Progress, depending on the class of that row.
  6. td elements of the Rate column should contain a span element with the class of rate wrapping three empty span elements.
  7. .rate elements placed inside .read rows should have an additional class with the value of either one, two, or three, depending on the personal rate. This value should come after rate.
  8. You should create three attribute selectors to target the elements with the class of read, to-read, and in-progress, and set their background-image property to use a linear-gradient of your choice.
  9. You should set the display property of each span element to inline-block.
  10. You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of to-read and set their border and background-image properties.
  11. You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of read and set their border and background-image properties.
  12. You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of in-progress and set their border and background-image properties.
  13. You should use an attribute selector to target the span elements with the class of status and the span elements with the class value starting with rate and set their height, width, and padding properties.
  14. You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their border, border-radius, margin, height, width, and background-color properties.
  15. You should use an attribute selector to target the first descendant of span elements that have the word one as a part of their class value and set its background-image property to use a linear-gradient.
  16. You should use an attribute selector to target the first two descendants of span elements that have the word two as a part of their class value and set their background-image property to use a linear-gradient.
  17. You should use an attribute selector to target the three span elements that are descendants of span elements that have the word three as a part of their class value and set their background-image property to use a linear-gradient.

--hints--

You should have an h1 element with the text Book Inventory.

js
assert.equal(document.querySelector('h1')?.innerText.trim(), 'Book Inventory');

You should have only one h1 element.

js
assert.lengthOf(document.querySelectorAll('h1'), 1);

You should have a table element.

js
assert.lengthOf(document.querySelectorAll('table'), 1);

You should have one thead element and one tbody element inside table.

js
assert.lengthOf(document.querySelectorAll("table > thead"), 1);
assert.lengthOf(document.querySelectorAll("table > tbody"), 1);

Inside the thead there should be one tr with 5 th elements.

js
assert.lengthOf(document.querySelectorAll("table > thead > tr"), 1);
assert.lengthOf(document.querySelectorAll("table > thead > tr > th"), 5);

Your first column should have the text Title as the heading.

js
assert.equal(document.querySelectorAll('th')[0]?.textContent.trim(), 'Title');

Your second column should have the text Author as the heading.

js
assert.equal(document.querySelectorAll('th')[1]?.textContent.trim(), 'Author');

Your third column should have the text Category as the heading.

js
assert.equal(document.querySelectorAll('th')[2]?.textContent.trim(), 'Category');

Your fourth column should have the text Status as the heading.

js
assert.equal(document.querySelectorAll('th')[3]?.textContent.trim(), 'Status');

Your fifth column should have the text Rate as the heading.

js
assert.equal(document.querySelectorAll('th')[4]?.textContent.trim(), 'Rate');

Your table should have at least four rows.

js
const rows = document.querySelectorAll('tr');
assert.isAtLeast(rows.length, 4);

Each row should always have 5 columns.

js
const rows = document.querySelectorAll('tbody tr');
assert.isNotEmpty(rows);
for (const row of rows) {
  assert.lengthOf(row.children, 5);
}

Each table row except the heading row should have either the class read, to-read, or in-progress.

js
const rows = document.querySelectorAll('tr');
assert.isNotEmpty(rows);
for (let i = 1; i < rows.length; i++) {
  const classList = [...rows[i].classList];
  const currentProgress = classList[0]; 
  assert.oneOf(currentProgress, ['read', 'to-read', "in-progress"]); 
}

td elements of the Status column should contain a span element.

js
const statusColumnData = document.querySelectorAll('td:nth-child(4)');
assert.isNotEmpty(statusColumnData);
for (let e of statusColumnData) {
  assert.equal(e?.children[0]?.tagName, 'SPAN');
}

Each span element of the Status column should have the class of status.

js
const statusSpans = document.querySelectorAll('tr td:nth-child(4) :first-child');
assert.isNotEmpty(statusSpans);
for (let e of statusSpans) {
    assert.isTrue(e.classList.contains('status'));
}

Each .status element should have the text Read, To Read, or In Progress, depending on the class of its row.

js
const statusSpans = document.querySelectorAll('tr td:nth-child(4) :first-child');
const rows = Array.from(document.querySelectorAll('tr')).slice(1);
assert.isNotEmpty(statusSpans);
for (let i = 0; i < rows.length; i++) {
  switch (statusSpans[i]?.innerText.trim()) {
        case 'Read':
            assert.isTrue(rows[i].classList.contains('read'));
            break;
        case 'To Read':
            assert.isTrue(rows[i].classList.contains('to-read'));
            break;
        case 'In Progress':
            assert.isTrue(rows[i].classList.contains('in-progress'));
            break;
        default:
            assert.fail(); 
    }
}

td elements of the Rate column should contain a span element.

js
const rateColumnData = document.querySelectorAll('tr td:last-child');
assert.isNotEmpty(rateColumnData);
for (let e of rateColumnData) {
    assert.equal(e.children[0]?.tagName, 'SPAN')
}

Each span element which is a direct child of a td element of the Rate column should have the class of rate as the first class.

js
const rateSpans = document.querySelectorAll('tr td:last-child > span:first-child');
assert.isNotEmpty(rateSpans);
for (let e of rateSpans) {
    assert.equal(e.classList[0], 'rate');
}

Each .rate element should contain three empty span elements.

js
const rateSpans = document.getElementsByClassName('rate');
assert.isNotEmpty(rateSpans);
for (let e of rateSpans) {
    assert.equal(e.children.length, 3);
    for (let child of e.children) {
        assert.equal(child.tagName, 'SPAN');
        assert.equal(child.innerText.length, 0);
    }
}

.rate elements placed inside .read rows should have an additional class after the rate class with the value of either one, two, or three, depending on the personal rate.

js
const readBooksRates = document.querySelectorAll('.read .rate');
assert.isNotEmpty(readBooksRates);
for (let e of readBooksRates) {
    assert.oneOf(e.classList[1], ['one', 'two', 'three']);
}

You should have an attribute selector to target rows that have the class of read.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="read"]'));

You should use an attribute selector to target rows that have the class of read and set their background-image property to a linear gradient of your choice.

js
assert.include(new __helpers.CSSHelp(document).getStyle('tr[class="read"]')?.backgroundImage, 'linear-gradient(');

You should have an attribute selector to target rows that have the class of to-read.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="to-read"]'));

You should use an attribute selector to target rows that have the class of to-read and set their background-image property to a linear gradient of your choice.

js
assert.include(new __helpers.CSSHelp(document).getStyle('tr[class="to-read"]')?.backgroundImage, 'linear-gradient(');

You should have an attribute selector to target rows that have the class of in-progress.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="in-progress"]'));

You should use an attribute selector to target rows that have the class of in-progress and set their background-image property to a linear gradient of your choice.

js
assert.include(new __helpers.CSSHelp(document).getStyle('tr[class="in-progress"]')?.backgroundImage, 'linear-gradient(');

You should set the display property of each span element to inline-block.

js
assert.equal(new __helpers.CSSHelp(document).getStyle('span')?.getPropVal('display'), 'inline-block');

You should have an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of to-read.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="to-read"] span[class="status"]'));

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of to-read and set their border property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="to-read"] span[class="status"]')?.border);

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of to-read and set their background-image property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="to-read"] span[class="status"]')?.backgroundImage);

You should have an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of read.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="read"] span[class="status"]'));

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of read and set their border property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="read"] span[class="status"]')?.border);

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of read and set their background-image property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="read"] span[class="status"]')?.backgroundImage);

You should have an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of in-progress.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('tr[class="in-progress"] span[class="status"]'));

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of in-progress and set their border property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="in-progress"] span[class="status"]')?.border);

You should use an attribute selector to target the span elements with the class of status that are descendants of tr elements with the class of in-progress and set their background-image property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('tr[class="in-progress"] span[class="status"]')?.backgroundImage);

You should have an attribute selector to target the span elements with the class of status and the span elements with the class value starting with rate.

js
const selector1 = new __helpers.CSSHelp(document).getStyle('span[class="status"], span[class^="rate"]');
const selector2 = new __helpers.CSSHelp(document).getStyle('span[class^="rate"], span[class="status"]');
assert.exists(selector1 || selector2);

You should use an attribute selector to target the span elements with the class of status and the span elements with the class value starting with rate and set their height property.

js
const selector1 = new __helpers.CSSHelp(document).getStyle('span[class="status"], span[class^="rate"]');
const selector2 = new __helpers.CSSHelp(document).getStyle('span[class^="rate"], span[class="status"]');
assert.isNotEmpty(selector1?.height || selector2?.height);

You should use an attribute selector to target the span elements with the class of status and the span elements with the class value starting with rate and set their width property.

js
const selector1 = new __helpers.CSSHelp(document).getStyle('span[class="status"], span[class^="rate"]');
const selector2 = new __helpers.CSSHelp(document).getStyle('span[class^="rate"], span[class="status"]');
assert.isNotEmpty(selector1?.width || selector2?.width);

You should use an attribute selector to target the span elements with the class of status and the span elements with the class value starting with rate and set their padding property.

js
const selector1 = new __helpers.CSSHelp(document).getStyle('span[class="status"], span[class^="rate"]');
const selector2 = new __helpers.CSSHelp(document).getStyle('span[class^="rate"], span[class="status"]');
assert.isNotEmpty(selector1?.padding || selector2?.padding);

You should have an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate.

js
assert.exists(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their border property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('border'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their border-radius property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('border-radius'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their margin property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('margin'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their height property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('height'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their width property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('width'));

You should use an attribute selector to target the span elements which are direct children of span elements with the class value starting with rate and set their background-color property.

js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('span[class^="rate"] > span')?.getPropVal('background-color'));

You should have an attribute selector to target the first descendant of span elements that have the word one as a part of their class value.

js
const selectors = [
  'span[class~="one"] :first-child',
  'span[class~="one"] :nth-child(1)',
  'span[class~="one"] :first-of-type',
  'span[class~="one"] span:first-child',
  'span[class~="one"] span:nth-child(1)',
  'span[class~="one"] span:first-of-type',
  'span[class~="one"] > :first-child',
  'span[class~="one"] > :nth-child(1)',
  'span[class~="one"] > :first-of-type',
  'span[class~="one"] > span:first-child',
  'span[class~="one"] > span:nth-child(1)',
  'span[class~="one"] > span:first-of-type'
]
assert.isNotNull(new __helpers.CSSHelp(document).getStyleAny(selectors));

You should use an attribute selector to target the first descendant of span elements that have the word one as a part of their class value and set its background-image property to use a linear-gradient.

js
const selectors = [
  'span[class~="one"] :first-child',
  'span[class~="one"] :nth-child(1)',
  'span[class~="one"] :first-of-type',
  'span[class~="one"] span:first-child',
  'span[class~="one"] span:nth-child(1)',
  'span[class~="one"] span:first-of-type',
  'span[class~="one"] > :first-child',
  'span[class~="one"] > :nth-child(1)',
  'span[class~="one"] > :first-of-type',
  'span[class~="one"] > span:first-child',
  'span[class~="one"] > span:nth-child(1)',
  'span[class~="one"] > span:first-of-type'
]
assert.isTrue(new __helpers.CSSHelp(document).getStyleAny(selectors)?.getPropVal('background-image').includes('linear-gradient('));

You should have an attribute selector to target the first two descendants of span elements that have the word two as a part of their class value.

js

const selectors = [
  'span[class~="two"] :nth-child(1), span[class~="two"] :nth-child(2)',
  'span[class~="two"] :nth-child(2), span[class~="two"] :nth-child(1)',
  'span[class~="two"] :first-child, span[class~="two"] :nth-child(2)',
  'span[class~="two"] :nth-child(2), span[class~="two"] :first-child',
  'span[class~="two"] :nth-of-type(-n+2)',
  'span[class~="two"] :nth-child(-n+2)',
  'span[class~="two"] span:nth-child(1), span[class~="two"] span:nth-child(2)',
  'span[class~="two"] span:nth-child(2), span[class~="two"] span:nth-child(1)',
  'span[class~="two"] span:first-child, span[class~="two"] span:nth-child(2)',
  'span[class~="two"] span:nth-child(2), span[class~="two"] span:first-child',
  'span[class~="two"] span:nth-of-type(-n+2)',
  'span[class~="two"] span:nth-child(-n+2)',
  'span[class~="two"] > :nth-child(1), span[class~="two"] > :nth-child(2)',
  'span[class~="two"] > :nth-child(2), span[class~="two"] > :nth-child(1)',
  'span[class~="two"] > :first-child, span[class~="two"] > :nth-child(2)',
  'span[class~="two"] > :nth-child(2), span[class~="two"] > :first-child',
  'span[class~="two"] > :nth-of-type(-n+2)',
  'span[class~="two"] > :first-child, span[class~="two"] > :nth-of-type(2)',
  'span[class~="two"] > :nth-of-type(2), span[class~="two"] > :first-child',
  'span[class~="two"] > :nth-child(-n+2)',
  'span[class~="two"] > span:nth-child(1), span[class~="two"] > span:nth-child(2)',
  'span[class~="two"] > span:nth-child(2), span[class~="two"] > span:nth-child(1)',
  'span[class~="two"] > span:first-child, span[class~="two"] > span:nth-child(2)',
  'span[class~="two"] > span:nth-child(2), span[class~="two"] > span:first-child',
  'span[class~="two"] > span:nth-of-type(-n+2)',
  'span[class~="two"] > span:nth-child(-n+2)'
  ]
assert.isNotNull(new __helpers.CSSHelp(document).getStyleAny(selectors));

You should use an attribute selector to target the first two descendants of span elements that have the word two as a part of their class value and set their background-image property to use a linear-gradient.

js
const selectors = [
  'span[class~="two"] :nth-child(1), span[class~="two"] :nth-child(2)',
  'span[class~="two"] :nth-child(2), span[class~="two"] :nth-child(1)',
  'span[class~="two"] :first-child, span[class~="two"] :nth-child(2)',
  'span[class~="two"] :nth-child(2), span[class~="two"] :first-child',
  'span[class~="two"] :nth-of-type(-n+2)',
  'span[class~="two"] :nth-child(-n+2)',
  'span[class~="two"] span:nth-child(1), span[class~="two"] span:nth-child(2)',
  'span[class~="two"] span:nth-child(2), span[class~="two"] span:nth-child(1)',
  'span[class~="two"] span:first-child, span[class~="two"] span:nth-child(2)',
  'span[class~="two"] span:nth-child(2), span[class~="two"] span:first-child',
  'span[class~="two"] span:nth-of-type(-n+2)',
  'span[class~="two"] span:nth-child(-n+2)',
  'span[class~="two"] > :nth-child(1), span[class~="two"] > :nth-child(2)',
  'span[class~="two"] > :nth-child(2), span[class~="two"] > :nth-child(1)',
  'span[class~="two"] > :first-child, span[class~="two"] > :nth-child(2)',
  'span[class~="two"] > :nth-child(2), span[class~="two"] > :first-child',
  'span[class~="two"] > :first-child, span[class~="two"] > :nth-of-type(2)',
  'span[class~="two"] > :nth-of-type(2), span[class~="two"] > :first-child',
  'span[class~="two"] > :nth-of-type(-n+2)',
  'span[class~="two"] > :nth-child(-n+2)',
  'span[class~="two"] > span:nth-child(1), span[class~="two"] > span:nth-child(2)',
  'span[class~="two"] > span:nth-child(2), span[class~="two"] > span:nth-child(1)',
  'span[class~="two"] > span:first-child, span[class~="two"] > span:nth-child(2)',
  'span[class~="two"] > span:nth-child(2), span[class~="two"] > span:first-child',
  'span[class~="two"] > span:nth-of-type(-n+2)',
  'span[class~="two"] > span:nth-child(-n+2)'
  ]

assert.isTrue(new __helpers.CSSHelp(document).getStyleAny(selectors)?.backgroundImage.includes('linear-gradient(')) 

You should have an attribute selector to target the span elements that are descendants of span elements that have the word three as a part of their class value.

js
const selectors = [
  'span[class~="three"] span',
  'span[class~="three"] > span'
]
assert.exists(new __helpers.CSSHelp(document).getStyleAny(selectors));

You should use an attribute selector to target the span elements that are descendants of span elements that have the word three as a part of their class value and set their background-image property to use a linear-gradient.

js
const selectors = [
  'span[class~="three"] span',
  'span[class~="three"] > span'
]
assert.include(new __helpers.CSSHelp(document).getStyleAny(selectors)?.getPropVal('background-image'), 'linear-gradient(');

--seed--

--seed-contents--

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

<head>
  <meta charset="utf-8">
  <title>Book Inventory</title>
  <link rel="stylesheet" href="styles.css">
</head>

<body>

</body>

</html>
css

--solutions--

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

<head>
  <meta charset="utf-8">
  <title>Book Inventory</title>
  <link rel="stylesheet" href="styles.css">
</head>

<body>
  <main>
    <h1>Book Inventory</h1>
    <div class="table-container">
      <table>
        <thead>
          <tr>
            <th>Title</th>
            <th>Author</th>
            <th>Category</th>
            <th>Status</th>
            <th>Rate</th>
          </tr>
        </thead>
        <tbody>
          <tr class="read">
            <td>The Three Musketeers</td>
            <td>Alexandre Dumas</td>
            <td>Historical Novel</td>
            <td><span class="status">Read</span></td>
            <td>
              <span class="rate three">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
          <tr class="to-read">
            <td>The Plague</td>
            <td>Albert Camus</td>
            <td>Philosophical Novel</td>
            <td><span class="status">To Read</span></td>
            <td>
              <span class="rate">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
          <tr class="read">
            <td>The Metamorphosis</td>
            <td>Franz Kafka</td>
            <td>Novella</td>
            <td><span class="status">Read</span></td>
            <td>
              <span class="rate one">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
          <tr class="read">
            <td>Dead Souls</td>
            <td>Nikolai Gogol</td>
            <td>Picaresque</td>
            <td><span class="status">Read</span></td>
            <td>
              <span class="rate two">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
          <tr class="in-progress">
            <td>Lord of the Flies</td>
            <td>William Golding</td>
            <td>Allegorical Novel</td>
            <td><span class="status">In Progress</span></td>
            <td>
              <span class="rate">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
          <tr class="read">
            <td>Do Androids Dream of Electric Sheep?</td>
            <td>Philip K. Dick</td>
            <td>Science Fiction</td>
            <td><span class="status">Read</span></td>
            <td>
              <span class="rate two">
                <span></span><span></span><span></span>
              </span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </main>
</body>

</html>
css
* {
    box-sizing: border-box;
    font-family: Arial, sans-serif;
}

.table-container {
  overflow-x: auto;
}

table {
    border-collapse: collapse;
    width: 100vw;
}

thead {
    background-image: linear-gradient(hsl(197, 92%, 77%, 0.60), hsl(197, 92%, 50%, 0.60));
}

th {
    padding: 0.4em;
}

td {
    text-align: center;
    padding: 0.3em;
}

tr[class="read"] {
    background-image: linear-gradient(hsl(120, 100%, 85%, 0.6), hsl(120, 100%, 65%, 0.6));
}

tr[class="to-read"] {
    background-image: linear-gradient(hsl(120, 20%, 95%, 0.6), hsl(120, 20%, 75%, 0.6));
}

tr[class="in-progress"] {
    background-image: linear-gradient(hsl(40, 100%, 85%, 0.60), hsl(40, 100%, 65%, 0.6));
}

span {
    display: inline-block;
}

span[class="status"] {
    border-radius: 20%/60%;
}

span[class="status"],
span[class^="rate"] {
    height: 1.85em;
    width: 7em;
    padding: 0.3em;
}

tr[class="to-read"] span[class="status"] {
    border: 0.1em solid hsl(5, 100%, 45%);
    background-image: linear-gradient(hsl(5, 100%, 75%), hsl(5, 100%, 50%));
}

tr[class="read"] span[class="status"] {
    border: 0.1em solid hsl(120, 75%, 45%);
    background-image: linear-gradient(hsl(120, 75%, 75%), hsl(120, 75%, 50%));
}

tr[class="in-progress"] span[class="status"] {
    border: 0.1em solid hsl(40, 90%, 40%);
    background-image: linear-gradient(hsl(40, 90%, 75%), hsl(40, 90%, 50%));
}

span[class^="rate"] > span {
    border: 0.1em solid hsl(0, 0%, 50%);
    border-radius: 50%;
    background-color: hsl(0, 15%, 95%);
    height: 100%;
    width: 20%;
    margin: 0.1em;
}

span[class~="three"] span {
    background-image: linear-gradient(hsl(50, 100%, 70%), hsl(50, 100%, 50%));
}

span[class~="two"] :nth-child(1),
span[class~="two"] :nth-child(2) {
    background-image: linear-gradient(hsl(50, 100%, 70%), hsl(50, 100%, 50%));
}

span[class~="one"] :first-child {
    background-image: linear-gradient(hsl(50, 100%, 70%), hsl(50, 100%, 50%));
}