Hoot Front-End Style the Hoot Details Component

Learning objective: By the end of this lesson, students will be able to style a details component with CSS modules.

Add the module

Run the following command in your terminal:

touch src/components/HootDetails/HootDetails.module.css

Add the following to this new file :

/* src/components/HootDetails/HootDetails.module.css */

/* Details and comments */

.container {
  height: 100%;
  display: flex;
  overflow: scroll;
  align-items: center;
  flex-direction: column;
  background-color: var(--card-background);
}

.container > section {
  width: 100%;
  padding: 21px;
  display: flex;
  max-width: 700px;
  flex-direction: column;
}

.container section article {
  padding: 0;
  width: 100%;
  min-height: 140px;
  margin: 4px 0px 14px;
}

.container header div {
  width: 100%;
  display: flex;
  margin-top: 10px;
  align-items: center;
}

.container header {
  display: flex;
  margin-bottom: 21px;
  flex-direction: column;
  align-items: flex-start;
}

.container h1 {
  margin: 0 0 7px 0;
}

.container header > p {
  margin: 0;
  opacity: 1;
  font-weight: 600;
  color: var(--primary);
  margin: 7px 0px 14px 0px;
}

.container header button,
.container header a {
  width: 30px;
  height: 30px;

  font-size: 14px;
  font-weight: 500;

  background: none;
  border-radius: 50%;
  border: 1px solid var(--border);

  display: flex;
  align-items: center;
  justify-content: center;

  padding: 5px;
  margin: 0 0 0 7px;
}

/* Button icon styling */
/* This styling will be used when we add in our reusable icon component */

.container header button img,
.container header a img {
  width: 24px;
  height: 24px;
  opacity: 0.25;
}

.container header button:hover,
.container header a:hover {
  background-color: var(--border);
}

.container header button:hover img,
.container header a:hover img {
  filter: invert(1);
  opacity: 1;
}

.container header button:active {
  background-color: rgb(190, 190, 190);
}

/* Comment form styling */

.container form {
  padding: 0;
  display: flex;
  border: none;
  max-width: 100%;
  box-shadow: none;
  flex-direction: row;
  align-items: center;
  -moz-box-shadow: none;
  -webkit-box-shadow: none;
}

.container form input,
.container form textarea {
  width: 100%;
  padding: 14px;
  font-size: 14px;
  resize: vertical;
  border-radius: 5px;
  margin: 14px 0px 14px 0px;
  border: 1px solid var(--border);
}

.container form textarea {
  min-height: 50px;
}

.container form button {
  color: white;
  font-weight: 600;
  background: #00a0df;
  width: 40px;
  height: 40px;
  margin: 0 0 0 14px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container form button img {
  width: 25px;
  height: 25px;
}

The HootDetails component is rather complex, as it features several subsections and subcomponents. As a result, we have quite a bit of styling in here.

First, note how we utilize descendant and child selectors in our CSS. This approach helps us to reduce the number of className and id attributes in our JSX by selecting elements based on their relationship to the parent container. This makes our code cleaner and more maintainable. If you need a refresher on how these selectors work, take a look at the MDN documentation on CSS Selectors.

Some other interesting details include:

Let’s add the styles object to our component.

Add the following import to the top of the HootDetails component:

// src/components/HootDetails/HootDetails.jsx

import styles from './HootDetails.module.css';

And add apply styles.container to the className of the outermost element(<main>):

// src/components/HootDetails/HootDetails.jsx

<main className={styles.container}>

Next, we’ll need to make a small change to authorship and interactive elements of our hoot details. For our layout, we’ll need to wrap these elements in a <div>.

Apply the following changes to the HootDetails component:

// src/components/HootDetails/HootDetails.jsx

      <section>
        <header>
          <p>{hoot.category.toUpperCase()}</p>
          <h1>{hoot.title}</h1>
          {/* Add this div */}
          <div>
            <p>
              {`${hoot.author.username} posted on
              ${new Date(hoot.createdAt).toLocaleDateString()}`}
            </p>
            {hoot.author._id === user._id && (
              <>
                <Link to={`/hoots/${hootId}/edit`}>Edit</Link>
                <button onClick={() => props.handleDeleteHoot(hootId)}>
                  Delete
                </button>
              </>
            )}
          {/* Don't forget to close it */}
          </div>

        </header>
        <p>{hoot.text}</p>
      </section>

And now do the same to the <article> tag in your comments section like so:

// src/components/HootDetails/HootDetails.jsx

          <article key={comment._id}>
            <header>
              {/* Add this div */}
              <div>
                <p>
                  {`${comment.author.username} posted on
                  ${new Date(comment.createdAt).toLocaleDateString()}`}
                </p>
                {comment.author._id === user._id && (
                  <>
                    <Link to={`/hoots/${hootId}/comments/${comment._id}/edit`}>Edit</Link>
                    <button onClick={() => handleDeleteComment(comment._id)}>
                      Delete
                    </button>
                  </>
                )}
              {/* Don't forget to close it */}
              </div>
            </header>
            <p>{comment.text}</p>
          </article>

Take a look at the newly styled HootDetails component in your browser.