Skip to content
themeforge
EN
Start free
Menu
  1. Home
  2. Section recipes
  3. Comments and reviews
Recipe 6 steps

Comments and reviews in your own design

Comments usually reach a site as WordPress markup, and there is nothing in your mockup to style it with. Here you draw one card and the form with your own blocks, and WordPress repeats the card for every comment. Replies, moderation and spam protection stay with WordPress.

What you get

Markup single.html · single-product.html
<!-- single.html: under the post -->
<section class="comments" wp="comment-list">
  <h2 class="comments__title">Comments</h2>
  <div class="comment">
    <img class="comment__avatar" src="images/avatar.png" alt="" wp="comment-avatar">
    <p class="comment__author" wp="comment-author">Anna</p>
    <p class="comment__date" wp="comment-date">October 2</p>
    <div class="comment__text" wp="comment-text">Is the pumpkin latte vegan?</div>
    <a class="comment__reply" href="#" wp="comment-reply">Reply</a>
  </div>
  <form class="comment-form" wp="comment-form">
    <div class="field" wp="comment-input-author">
      <label for="name">Name</label>
      <input type="text" id="name" class="input">
    </div>
    <div class="field" wp="comment-input-email">
      <label for="email">Email</label>
      <input type="email" id="email" class="input">
    </div>
    <div class="field" wp="comment-input-text">
      <label for="comment">Comment</label>
      <textarea id="comment" class="input"></textarea>
    </div>
    <button type="submit" class="button" wp="comment-submit">Post comment</button>
  </form>
</section>

<!-- single-product.html: reviews of a product (WooCommerce) -->
<section class="reviews" wp="review-list">
  <div class="review">
    <p class="review__author" wp="comment-author">Anna</p>
    <div class="review__stars" wp="review-rating"><div class="review__stars-fill"></div></div>
    <span class="review__badge" wp="review-verified">Verified buyer</span>
    <div class="review__text" wp="comment-text">Fruity and bright, great as a filter.</div>
  </div>
  <form class="review-form" wp="review-form">
    <div class="field" wp="review-input-rating">
      <label for="rating">Rating</label>
      <select id="rating" class="input"></select>
    </div>
    <div class="field" wp="comment-input-text">
      <label for="review">Review</label>
      <textarea id="review" class="input"></textarea>
    </div>
    <button type="submit" class="button" wp="comment-submit">Leave a review</button>
  </form>
</section>
In the admin Comments
Comments
  • Anna — Is the pumpkin latte vegan?
  • Tom — Yes, with oat milk. (reply)
  • Mia — Pending approval
Settings → Discussion
  • Allow people to submit comments on new posts
  • Comment must be manually approved
On the site post page
Comments
Anna Oct 2

Is the pumpkin latte vegan?

↳ Tom Oct 2

Yes, with oat milk.

Post comment

The reply is indented, and a comment awaiting moderation is hidden from visitors.

Step by step

  1. The comments block

    wp="comment-list" goes on the block under the post text in single.html. Everything inside becomes the comments template: the heading, the card, the form.

    <section class="comments" wp="comment-list">
  2. One card

    Draw exactly one card and mark its parts: avatar comment-avatar, name comment-author, date comment-date, text comment-text, link comment-reply. WordPress repeats it for every comment.

    <div class="comment">
      <img class="comment__avatar" src="images/avatar.png" alt="" wp="comment-avatar">
      <p class="comment__author" wp="comment-author">Anna</p>
      <p class="comment__date" wp="comment-date">October 2</p>
      <div class="comment__text" wp="comment-text">Is the pumpkin latte vegan?</div>
      <a class="comment__reply" href="#" wp="comment-reply">Reply</a>
    </div>
  3. The form

    wp="comment-form" on the form, the field marks on the wrappers: comment-input-author, comment-input-email, comment-input-text. The label and the field inside a wrapper travel to the theme together.

    <form class="comment-form" wp="comment-form">
      <div class="field" wp="comment-input-author">
        <label for="name">Name</label>
        <input type="text" id="name" class="input">
      </div>
  4. The button

    wp="comment-submit" on the button: the look is yours, WordPress does the sending.

    <button type="submit" class="button" wp="comment-submit">Post comment</button>
  5. Product reviews

    The same approach in single-product.html: a wp="review-list" block, the same comment marks in the card, plus the rating review-rating and the badge review-verified.

    <div class="review__stars" wp="review-rating"><div class="review__stars-fill"></div></div>
    <span class="review__badge" wp="review-verified">Verified buyer</span>
  6. The review form

    wp="review-form" goes inside the reviews block, always. The rating field is review-input-rating: an empty <select> gets the options 1 to 5 by itself.

    <form class="review-form" wp="review-form">
      <div class="field" wp="review-input-rating">
        <label for="rating">Rating</label>
        <select id="rating" class="input"></select>
      </div>

What matters

  • Allowing comments and turning on moderation is done in Settings → Discussion.
  • Replies get the classes tf-comment-depth-2, tf-comment-depth-3. Set the indent with your own CSS. In Webflow, put it in Project settings → Custom code: a class that is on no element is dropped on publishing, rule and all.
  • The rating has a --tf-rating variable: the width of the colored star strip is calc(var(--tf-rating) / 5 * 100%). An empty rating element shows the number.
  • The review-verified badge shows only on a review from someone who bought the product.

Common mistakes

The build log is the “Logs” tab of your project on themeforge.pro; the free markup check shows the same notes.

Not like this
<section class="comments" wp="comment-list">
  <div class="comment">
    <p class="comment__author">Anna</p>
    <div class="comment__text">Is the pumpkin latte vegan?</div>
  </div>
</section>

The card has no marks at all: no template is found, and the list falls back to the standard WordPress markup. The build notes this in the log.

Like this
<section class="comments" wp="comment-list">
  <div class="comment">
    <p class="comment__author" wp="comment-author">Anna</p>
    <div class="comment__text" wp="comment-text">Is the pumpkin latte vegan?</div>
  </div>
</section>

The card’s parts are marked.

Not like this
<form class="comment-form" wp="comment-form">
  <label for="name">Name</label>
  <input type="text" id="name" wp="comment-input-author">
  <button type="submit" wp="comment-submit">Post comment</button>
</form>

The mark is on the field itself: the label stays outside and does not reach the theme. The log stays silent.

Like this
<form class="comment-form" wp="comment-form">
  <div class="field" wp="comment-input-author">
    <label for="name">Name</label>
    <input type="text" id="name">
  </div>
  <button type="submit" wp="comment-submit">Post comment</button>
</form>

The mark is on the wrapper with the label and the field.

Not like this
<section class="comments" wp="comment-list">
  <div class="comment">
    <p wp="comment-author">Anna</p>
  </div>
  <div class="comment">
    <p wp="comment-author">Tom</p>
  </div>
</section>

Two cards “for the preview”: the second one stays on the page as an extra block under the list. The log stays silent.

Like this
<section class="comments" wp="comment-list">
  <div class="comment">
    <p wp="comment-author">Anna</p>
  </div>
</section>

One card; WordPress draws the rest.

Attributes in this recipe

Ready when you are

See your site’s WordPress admin before you pay.