JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;500;700&display=swap">
<title>Заголовок статьи - Название сайта</title>
</head>
<body>
<div class="main-wrapper">
<div class="content-comments">
<h4 class="section-title">Оставить комментарий</h4>
<div class="comments-wrapper">
<div class="comments-item">
<form class="form-comment">
<div class="component-input">
<div class="input-wrapper half-width">
<input type="text" placeholder="Ваше имя">
<label>Ваше имя</label>
</div>
<div class="input-wrapper half-width">
<input type="email" placeholder="Ваш email">
<label>Ваш email</label>
</div>
</div>
<div class="input-wrapper full-width">
<textarea placeholder="Ваш комментарий"></textarea>
<label>Ваш комментарий</label>
</div>
<button type="submit">Отправить</button>
</form>
</div>
<div class="comments-item">
<ul class="comments-list">
<!-- Комментарий 1 с 3 ответами -->
<li class="comments-item">
<div class="comment">
<div class="comment-icon">M</div>
<div class="comment-meta">
<span><i class="fa-regular...
CSS
body {
font-family: "Roboto", sans-serif;
font-size: var(--font-base);
font-weight: var(--weight-base);
line-height: var(--line-height-base);
background: var(--bg-secondary);
color: var(--text-color);
min-height: 100vh;
}
.main-wrapper {
margin: 0 auto;
padding: 0;
display: flex;
flex-direction: column;
max-width: var(--container-xl);
min-width: 240px;
min-height: 100vh;
background: var(--bg-primary);
}
.wrapper {
background: var(--bg-primary);
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.content-main {
margin: var(--spacing-md) 0;
padding: 0;
width: 100%;
background: var(--bg-primary);
}
/* Typography */
h1,
h2,
h3,
h4,
h5,
h6 {
margin: var(--spacing-sm) 0;
font-weight: var(--weight-bold);
color: var(--text-color);
}
a {
text-decoration: none;
transition: all var(--transition-slow);
color: var(--text-color);
}
a:hover,
a:focus {
text-decoration: none;
color: var(--primary-color);
}
p {
margin: 0;
margin-bottom: var(--spacing-sm);
padding: 0;
font-size: var(--font-base);
font-weight: var(--weight-base);
line-height: var(--line-height-base);
color: var(--text-color);
cursor: default;
}
h1 {
font-size: var(--font-3xl);
}
h2 {
font-size: var(--font-2xl);
}
h3 {
font-size: var(--font-xl);
}
h4 {
font-size: var(--font-2lg);
}
h5 {
font-size: var(--font-lg);
}
h6 {
font-size: var(--font-mg);
}
ul,
ol {
margin: var(--spacing-sm) 0;
padding: 0;
list-style: inside;
}
ul {
list-style-type: disc;
}
ol {
list-style-type: decimal;
}
ul li,
ol li {
margin: var(--spacing-xs) 0;
padding: 0;
font-size: var(--font-base);
font-weight: var(--weight-base);
line-height: var(--line-height-base);
color: var(--text-color);
cursor: default;
}
blockquote {
margin: var(--spacing-xl) 0;
padding: var(--spacing-lg);
border-left: 4px solid var(--primary-color);
background-color: var(--bg-secondary);
border-radius: var(--radius-sm);
}
blockquote footer {
...
JavaScript
document.addEventListener('DOMContentLoaded', function() {
const toggleButtons = document.querySelectorAll('.toggle-replies-btn');
toggleButtons.forEach(button => {
const repliesContainer = button.closest('.comment').querySelector('.comment-replies');
if (repliesContainer && repliesContainer.children.length > 0) {
button.style.display = 'flex';
button.addEventListener('click', function() {
const comment = this.closest('.comment');
const replies = comment.querySelector('.comment-replies');
this.classList.toggle('active');
replies.classList.toggle('active');
});
} else {
button.style.display = 'none';
}
});
function initCommentExpansion() {
const comments = document.querySelectorAll('.comment');
comments.forEach(comment => {
const commentBody = comment.querySelector('.comment-body');
const content = commentBody.querySelector('p');
if (!content) return;
const checkNeedsExpansion = () => {
const words = content.textContent.trim().split(/\s+/);
return words.length > 60 || commentBody.scrollHeight > 80;
};
if (checkNeedsExpansion()) {
commentBody.classList.add('needs-expansion');
const readMoreBtn = document.createElement('button');
readMoreBtn.className = 'read-more-btn';
readMoreBtn.textContent = 'читать полностью';
commentBody.after(readMoreBtn);
...