Перейти к содержимому
Забрать бесплатно
Модификации выключены. Так эта страница выглядит на обычной Тильде.

Аккордеон в Тильде: чем его делают и что он ломает в Zero Block

29 июля 2026 9 МИН КОМАНДА MODKOD

Отдельного блока-аккордеона в разобранном рантайме Тильды нет: слово `accordion` не встречается ни разу на 114 файлах, при том что `t396` в тех же файлах встречается 2561 раз. Раскрывающийся текст в Тильде всё же есть — но он инлайновый, живёт внутри абзаца, и на живой странице разворачивается только в одну сторону. Разберём его код целиком и посчитаем, что происходит с высотой Zero Block, когда текст внутри него становится длиннее.

✓ ПРОВЕРЕНО 29 июля 2026 перепись слова `accordion` по 114 файлам рантайма Тильды — ноль вхождений при контрольном `t396` в 2561 вхождение в тех же файлах; файл `tilda-undercut-1.0.min.js` прочитан целиком, все 5383 байта; 14 вхождений `ql-undercut` в 22 сохранённых страницах, все внутри записи типа 605; список пересчёта высоты выписан из `t_quillUndercut__updateHeight`, и проверено, что `tildaclamp` в `tilda-zero-1.1.min.js` не встречается ни разу; высоты артборда сняты с живой страницы вместе с CSS — рантайм Тильды из 114 файлов и 22 страницы, снятые с живых сайтов на Тильде

Задача звучит просто: список вопросов, каждый раскрывается по нажатию. В интерфейсе Тильды ищется блок с таким названием, а в поиске — «аккордеон в тильде». Дальше начинается расхождение между тем, как задачу называют, и тем, из чего её на Тильде реально собирают. Разберём по разметке и по коду: что для раскрывающегося текста в Тильде уже есть, чем это не аккордеон, и почему внутри Zero Block вопрос из «как оформить» превращается в «что с высотой».

Короткий ответ

Блока-аккордеона в разобранном рантайме Тильды нет. Есть инлайновая подрезка текста — ql-undercut, кнопка «Читать далее» прямо внутри абзаца, — и есть блок табов T817 с готовой ARIA-разметкой. Самодельный аккордеон в Zero Block упирается не в вёрстку, а в высоту артборда: она задана числом на каждый брейкпоинт.

Что в Тильде уже есть: подрезка текста

Первое, что стоит знать: у Тильды под это отведён отдельный файл рантайма, tilda-undercut-1.0.min.js, 5383 байта. Он маленький, поэтому его удалось прочитать целиком, а не по фрагментам, — всё, что ниже, взято из него и из живой разметки, а не из документации.

Выглядит подрезка в готовой странице так (снято с сайта на Тильде, перенос строк мой):

<span class="ql-undercut"
      data-text="Мы точно можем рекомендовать Тильду для создания сайтов…"
      data-show-text="Читать далее"
      data-hide-text=""
      data-color="#000000"
      data-style="solid">
  <span contenteditable="false">Читать далее</span>
</span>

Ключевое здесь — тег. Это <span>, и в стилях, которые скрипт сам вставляет в <head>, у него display: inline. Подрезка не блок и не секция: она живёт внутри абзаца, в потоке текста. Аккордеон из неё не собрать по устройству — у неё нет ни заголовка секции, ни второго уровня, ни группы, внутри которой открыт ровно один элемент.

В 22 сохранённых страницах ql-undercut встретился 14 раз, и все 14 — внутри записи типа 605, блока с отзывами. Ни одного вхождения в Zero Block.

Чем подрезка не аккордеон: четыре подробности из кода

Свернуть обратно нельзя, если поле «Скрыть» пустое. В живой разметке data-hide-text="", и обработчик на это отвечает буквально:

var a = i.getAttribute("data-hide-text") || "";
…
if (!a) return;                // кнопку «Скрыть» не создаём

То есть текст раскрывается один раз и остаётся раскрытым до перезагрузки страницы. Для отзыва это нормально, для аккордеона — нет: аккордеон обязан закрываться.

Надпись по умолчанию — [+]. Не «Читать далее», не «Подробнее»:

u.innerHTML = n || "[+]";

Если поле подписи оставить пустым, посетитель увидит на странице ровно два символа в квадратных скобках.

Многоточие — две точки, а не три. Скрипт дописывает их в предыдущий текстовый узел, а не в свой:

e.textContent = n.slice(0, r + 1) + ".." + n.slice(r + 1);

Обход идёт по previousSibling, а если не нашлось — вверх, на parentNode.previousSibling. Из-за этого снятие многоточия при закрытии сложнее установки: функция ищет lastIndexOf("..") и умеет заходить только в разрешённый список инлайновых тегов — SPAN, EM, STRONG, S, U, SUP, SUB, A, I, B, Q. Вставили внутрь подрезки что-то не из этого списка — точки при закрытии останутся.

Скрытый текст не спрятан. Он лежит в data-text в открытом виде, в том же HTML. При нажатии скрипт достаёт его оттуда и разэкранирует:

var o = t_quillUndercut_unEscapeHtml(i.getAttribute("data-text") || "");

Практический вывод в две стороны. Подрезкой нельзя убрать текст из индекса — он в исходнике страницы. Зато и бояться за индексацию не нужно: и поисковик, и языковая модель прочитают скрытую часть, не нажимая кнопку.

Табы T817: то, что ближе всего по смыслу

Если задача формулируется как «одна секция открыта, остальные закрыты», то в Тильде это уже есть — блоком табов. Разметка из живой страницы, запись типа 817:

<ul class="t817__wrapper" role="tablist" data-tab-current="1">
  <li class="t817__tab" role="presentation" data-tab-number="1">
    <button type="button" class="t817__tab-name"
            id="tab1_750744168" role="tab"
            aria-selected="false"
            aria-controls="content-tab1_750744168"
            tabindex="-1">Годовой доступ</button>
  </li>
  …
</ul>

Здесь стоит отметить то, что в самодельных аккордеонах обычно забывают: роли расставлены полностью — tablist на списке, presentation на <li>, tab на настоящей кнопке, есть aria-selected, есть aria-controls, есть управление tabindex. На узких экранах тот же блок печатает второй вариант интерфейса:

<select class="t817__select" data-tab-mobile-number="1">

Две оговорки. Первая: в статическом исходнике у всех кнопок aria-selected="false" и tabindex="-1" — активную выбирает скрипт, поэтому без JavaScript ни один таб не открыт. Вторая: определения t817_init в разобранных 114 файлах нет — оно приходит постраничным бандлом. Значит про разметку T817 можно говорить уверенно, а про внутренности его скрипта — нет.

Аккордеон в Zero Block: спор не с вёрсткой, а с высотой

Здесь самое важное. Высота артборда в Zero Block — это записанное число, причём на каждый брейкпоинт своё. С живой страницы:

<div class="t396__artboard"
     data-artboard-height="1310"
     data-artboard-height-res-320="726"
     data-artboard-height-res-480="799"
     data-artboard-height-res-640="1220"
     data-artboard-height-res-960="1274">

И те же числа продублированы в CSS страницы:

.t396__artboard { height: 1310px; … }

Элемент, который стал выше, этих чисел не меняет. Он либо вылезает за край артборда, либо перекрывает соседей — оба симптома описывают одну причину.

Дальше вопрос: а сама Тильда как пересчитывает высоту, когда текст раскрывается? Ответ выписан из подрезки — она вызывает свой t_quillUndercut__updateHeight(recId), и вот полный список того, что он трогает:

Что нашлось в записиЧто вызывается
.t-sldst_slds_UpdateSliderHeight
.t-covert_cover__recalcContentHeight
.t-quizt_quiz__adjustStepToHeight
тип записи 1068, 1069, 1070, 1071, 1072, 822t<тип>_init(recId) заново
тип записи 517t517_unifyHeights
в конце — всемсобытие tildaclamp:update

Типа 396 в этом списке нет. И событие до Zero Block тоже не доходит: слово tildaclamp в tilda-zero-1.1.min.js не встречается ни разу — при том, что t396 в этом же файле встречается 498 раз. Слушают tildaclamp:update только слайдер и обрезка текста по строкам.

То есть путь пересчёта у Zero Block есть, он просто подключён к другому событию — к переключению табов:

"yes" === e.getAttribute("data-connect-with-tab") &&
  i.addEventListener("displayChanged", function () {
    t396_allelems__renderView(r);
    t396_allgroups__renderView(r);
    t396_doResize(t, !0);
  });

Исключение, о котором стоит знать: режим hug

Не всякий артборд живёт с фиксированным числом. У одного из разобранных стоит data-artboard-heightmode="hug", и в коде это включает пересчёт:

var u = "hug" === r.getAttribute("data-artboard-heightmode");
if (u) { /* дроссель на t396__updateAutoHeight */ }

t396__updateAutoHeight не просто меняет стиль — он записывает новую высоту обратно в атрибут и рассылает по блоку своё событие:

t.setAttribute("data-artboard-height", r);      // или -res-<брейкпоинт>
t396_ab__renderView(t);
t.closest(".t396").dispatchEvent(new CustomEvent("zero:height-changed"));

Две подробности, которые пригодятся. Первая: измеряет он только прямых детей артборда — :scope > .tn-group, :scope > .tn-elem, — так что выросший элемент внутри группы внутри группы в расчёт может не попасть. Вторая: zero:height-changed в разобранном корпусе слушает ровно один файл, tilda-animation-ext-1.0.min.js, — то есть на это событие рассчитывать как на общий сигнал «высота поменялась, пересчитайте себя» нельзя.

Что из этого следует делать

Три варианта, по возрастанию цены:

Один длинный текст, который надо укоротить. Штатная подрезка, и заполните поле «Скрыть» — иначе развернётся один раз и навсегда. Аккордеоном это не станет, но задачу «много текста на маленьком экране» решает без кода.

Несколько разделов, открыт один. Табы T817. Роли и клавиатура уже расставлены, на мобильных сам превратится в список выбора. Если внутри таба стоит Zero Block — включите ему связь с табом, иначе он не пересчитает себя при показе.

Настоящий аккордеон внутри Zero Block. Здесь придётся писать код, и главная работа не в раскрытии, а в высоте: артборд надо либо перевести в hug, либо пересчитывать высоту самому после каждого раскрытия. Про соседние элементы помните: они позиционированы абсолютно, и «подвинуть всё, что ниже» само не произойдёт.

Доступность: две вещи, которые Тильда не доделала

Обе видны прямо в коде подрезки, и обе стоит починить, если делаете своё.

aria-expanded до первого клика нет. Кнопка, которую скрипт создаёт при разборе страницы, получает aria-label и aria-controls, но не aria-expanded. Атрибут появляется только у кнопок, созданных позже, при нажатии. То есть в исходном состоянии скринридер не знает, свёрнуто это или развёрнуто.

Перевод есть, но не там, где видно. В скрипте лежит словарь на 13 языков — для русского «Показать» и «Скрыть», — и язык он определяет аккуратно: сначала data-tilda-project-lang у #allrecords, потом navigator.language, иначе EN. Но используется этот перевод только в aria-label. Видимая надпись всегда берётся из поля или превращается в [+]. Получается расхождение: глаз видит [+], скринридер произносит «Показать».

Откуда числа

Слово accordion искалось по 114 файлам рантайма Тильды: 0 вхождений. Контроль замера в том же проходе — t396 в тех же файлах даёт 2561 вхождение, значит файлы читались и ноль настоящий. Вхождения считались не построчно: файлы рантайма минифицированы в одну строку, и grep -c вернул бы 1 независимо от их числа.

tilda-undercut-1.0.min.js прочитан целиком. ql-undercut и data-show-text — по 14 вхождений в 22 страницах, контроль на тех же страницах: data-record-type — 995 вхождений. Высоты артборда и разметка табов сняты с двух разных живых страниц.

И оговорка, без которой перепись врёт. Отсутствие в этом корпусе не равно отсутствию в Тильде: у Тильды отложенная привязка через t_onFuncLoad, поэтому функция может вызываться в файле, который у нас есть, а определяться в постраничном бандле, которого нет. Именно так вышло с t817_init — вызов виден, определения в корпусе нет. Поэтому про механику подрезки и про высоту артборда здесь сказано утвердительно, а про «блока-аккордеона не существует» — только то, что его нет в разобранном.

Где проходит граница MOD-184

MOD-184 не заменяет штатный T817 и обычные аккордеонные блоки. Он предназначен для более узкого случая: дизайнер собрал пары заголовок-панель внутри flex Zero Block, на странице нужно несколько независимых групп, а hug-артборд должен вырасти после раскрытия.

Мод не двигает элементы через top и left, связывает пары внутри каждой группы, использует hidden и aria-expanded, а после изменения вызывает t396__updateAutoHeight на hug-артборде и посылает zero:height-changed. Сниппет, параметры и разметка ролей опубликованы на карточке MOD-184.

Вопросы по этой статье 3

В разобранных 114 файлах рантайма слово `accordion` не встречается ни разу, и ни в одной из 22 страниц нет разметки, которую можно было бы назвать аккордеоном. Ближе всего два штатных механизма, и оба не аккордеон: инлайновая подрезка текста `ql-undercut` («Читать далее» внутри абзаца) и блок табов T817. Оговорка честная: набор файлов — снимок, а не гарантия. Но механику того, что в снимке есть, можно описать точно, и она ниже.