bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

Sticky footer #1085

Open webhive opened 8 years ago

webhive commented 8 years ago

Как можно реализовать вот такой прилипающий footer Ryan Fait's HTML5 CSS Sticky Footer на БЭМ?
Проблема в том, что блок должен обернуть содержимое body в тэг-обёртку и кроме того добавить определённые стили в и , что насколько я понимаю противоречит принципу независимости блоков. Можно вроде как добавить в и миксы, но как-то это на мой взгляд не совсем красиво ... да и насчёт миксов не уверен - недостаточно компетентен в БЭМ - методологии.

qfox commented 8 years ago

Например, это можно сделать специальным полем в блоке page. Не отдельный блок, конечно, но главное же результат.

Блок page отвечает за обёртку (html-head-body) и при наличии этого поля может обернуть содержимое в обёртку, добавить определенные стили, и всё остальное.

Если пытаться реализовывать отдельным блоком — то действительно не очень понятно как это делать. Я бы отказался от такого в пользу раскладки с прилипашкой.

qfox commented 8 years ago

Ах да. С миксами беда в том, что имеющиеся шаблонизаторы не запускают шаблоны на миксы. А так — да, можно навешивать, в процессе работы модифицировать содержимое страницы, заворачивать тело body, но без влезания в page это не удастся. Поэтому, такое решение тоже далеко от идеала.

webhive commented 8 years ago

и при наличии этого поля может обернуть содержимое в обёртку, добавить определенные стили, и всё остальное.

Хмм - а как контент тогда в footer запихать? Хотелось бы чтоб всё через bemjson делалось, а это насколько я понимаю подразумевает, что footer должен быть именно как отдельный блок в bemjson.

Нашёл вот что-то такое https://github.com/bem/bem-forum-content-ru/issues/427 но как-то сильно заморочено получается. И footer генерится через bemhtml, т.е. опять же непонятно как в него контент пихать.

qfox commented 8 years ago

На своем уровне добавляете 2 файла для page:

// blocks/page/page.bemhtml.js
block('page').match(function(){ return this.ctx.stickyFooter; }).content()(function(){
    return [
        {
            elem: 'body', // page__body
            content: [
                applyNext(),
                { elem: 'sticky-push' } // page__sticky-push
            ]
        },
        {
            elem: 'sticky-footer', // page__sticky-footer
            content: this.ctx.stickyFooter // нужный контент
        }
    ];
});
// blocks/page/page.deps.js
[{
    shouldDeps: [
        {elem: ['body', 'sticky-push', 'sticky-footer']}
    ]
}];

Ну и css/js для нужных элементов.

Далее используете так:

({
    block: 'page',
    content: [ ... ],
    stickyFooter: [ ... ]
});
qfox commented 8 years ago

Получается, что часть контента и разметки будет в bemjson, а часть в bemhtml?

Не понял. Можно по подробнее?

откуда взялась переменная this.ctx.stickyFooter?

Мы её сами придумали, чтобы положить туда содержимое футера.

Если у страницы такой футер есть, то где-то нам надо будет хранить его содержимое. Почему не в этом параметре?

Предполагаю, что из имени элемента sticky-footer

Нет, просто совпадение. Можно сделать и просто this.ctx.footer — тогда в bemjson надо будет делать ({ block: 'page', footer: [ 'BEMJSON с содержимым футера' ] })

И значит ли это, что если в bemjson у меня будет элемент sticky-footer, то вот в то место которое вы пометили как // нужный контент его содержимое и попадёт?

В это место попадет то, что мы положим в поле stickyFooter (или footer) в bemjson.

webhive commented 8 years ago

Да - вот это уже что-то. Не очень конечно красиво, что вместо обычной схемы block -> content добавляется ещё одна сущность, но в целом на первый взгляд неплохое решение. Завтра попробую на живом примере. Спасибо!

webhive commented 8 years ago

Не понял. Можно по подробнее?

Да у вас ответ не дописан видимо был и уже опубликован - только половина текста была. Я потом страницу обновил, увидел полный ответ, вопросы отпали я я свой ответ удалил. Так что уже неактуально :)

qfox commented 8 years ago

Оу. Извиняюсь, возможно ;-(.

Если будут проблемы с этим шаблоном — обращайтесь.

webhive commented 8 years ago

Вчера отходя ко сну меня посетила мысль, что предложенный способ концептуально наиболее правильный, хотя изначально немного не понравилось добавление новой сущности в bemjson.

Например, это можно сделать ... в блоке page. Не отдельный блок, конечно, но главное же результат.

Да - совершенно верно! Если из блока наружу мы вылезти не можем - надо подниматься по дереву наверх до того уровня на котором это всё возможно. В данном случае до самого верха т.е. до page. Т.е. я бы даже сказал не например, а так и надо - это верно с любой точки зрения.

Например, это можно сделать специальным полем в блоке page.

Вот так вот поглумиться над bemjson я бы ни за что не додумался. И вот эта подсказка пожалуй наиболее ценна. В предложенном методе реализации sticky footer-а footer выносится на один уровень (вложенности) с контентом. Ну так в данном случае добавление поля в bemjson как раз это как мне кажется прекрасно отражает.

В общем итого всё отлично - все сомнения окончательно рассеяны. Ещё раз спасибо за помощь.

PS:

Не могу не побрюзжать - вот реально не хватает БЕМ-у какого-то сборника рецептов или how-to или чего-то подобного. Даже вот по форуму пробежаться - много каких-то типовых решений можно насобирать и где-то в отдельном месте оформить и выложить. Тем более, что БЭМ нотация допускает неоднозначности, которые сложно понять неопытному человеку (что блок, а что элемент и т.п.).

qfox commented 8 years ago

Не могу не побрюзжать - вот реально не хватает БЕМ-у какого-то сборника рецептов или how-to или чего-то подобного. Даже вот по форуму пробежаться - много каких-то типовых решений можно насобирать и где-то в отдельном месте оформить и выложить.

Да, это правда. Одно время пытались собирать FAQ, но это несколько другое. cc @tadatuta

tadatuta commented 8 years ago

На самом деле мы стараемся так сделать. Например ответ на

что блок, а что элемент и т.п.

у нас действительно записан: https://ru.bem.info/methodology/faq/#В-каком-случае-создавать-блок-в-каком--элемент

А вот является ли, скажем, текущий кейс частым и нужно ли его добавлять в рецепы — уже и вопрос.

webhive commented 8 years ago

Да я на этот конкретный кейс не претендую, но я вообще не видал рецептов как таковых. Но кстати этот кейс хорош как демонстрация как можно выйти из ситуации когда блок должен влиять на вышестоящие блоки.

Собственно основной и наиболее развёрнутый туториал на данный момент это https://habrahabr.ru/company/yandex/blog/251473/. Но он один единственный и его главный недостаток, что он реально сложный.

FAQ я бы сказал написан человеком, который уже все понимает для таких же людей. "Критикуешь - предлагай", поэтому рискну показать на мой взгляд пример хорошей и понятной документации (кстати по БЭМ) - http://nicothin.github.io/idiomatic-pre-CSS/ - это даже не документация, а скорее cheet sheet, но тем не менее позволяет быстро понять что к чему. Четко понятно - вот так можно, а вот так - нет и пояснение в чем тут проблема.

webhive commented 8 years ago

@zxqfox

Чорт побери - оно работает! Остался небольшой нюанс. Надо задать тегу высоту 100%. Без этого - никак. Пока запихал это в CSS к блоку page, но мне кажется это неправильно. Как быть? Каким образом наиболее правильно это сделать?

qfox commented 8 years ago

Создать файлик page/__elem/page__elem.css с селектором .page__elem { height: 100% } ну или как надо. Вместо elem подставить нужный.

webhive commented 8 years ago

Не уверен, что понял. Элемент же должен быть внутри страницы, а тэг уровнем ещё выше. Требуется

html { height: 100% }
tadatuta commented 8 years ago

https://habrahabr.ru/company/yandex/blog/251473/

Да, он сложный (и изрядно устарел), в планах есть его упрощение и обновление.

http://nicothin.github.io/idiomatic-pre-CSS/

Этот документ был одним из источников вдохновения для https://github.com/bem/bem-method/blob/bem-info-data/method/bem-for-css/bem-for-css.ru.md (скоро на bem.info). Что скажешь про эту доку?

webhive commented 8 years ago

... в планах есть его упрощение и обновление.

Я бы вообще посоветовал разбить его на части. От простого к сложному. Чтоб можно было каждый кусок отдельно усвоить и переварить.

Что скажешь про эту доку?

По содержанию это абсолютно то, что нужно. Но я же не могу обойтись без критики :) поэтому лови:

  1. Язык очень сухой, академический. Просто навскидку случайная фраза "Изменение реализации блока путем добавления ему новых особенностей на другом уровне." В этой фразе 2 термина являются ссылками (кстати проверил куда они ведут и обе ссылки ведут на текст который во первых просто переключает контекст и сам по себе является отдельной большой темой). Если пойти по ссылкам очень скоро вообще забудешь с чего ты начал. Ну и это вот "... путём добавления ..." - это как блин диссертация какая-то. Это не плохо само по себе и не скажу, что это не понятно, но заходит очень тяжело. Источник вдохновения в этом плане лаконичен и при этом понятен - в нём всё описано простым языком - так как у вас люди говорят на конференциях и митапах.
  2. Это уже более важно. Я считаю обязательно должны быть примеры как не надо делать. И обязательно почему так делать не надо. В источнике вдохновения этот момент присутствует. Нужно это потому, что методология БЭМ довольно сложна и допускает разночтения (классическая проблема что есть блок, а что элемент и почему - тут можно копья ломать бесконечно если нет авторитетного мнения или чёткого указания).
  3. Вот эта Определения дока она тоже практически то, что нужно. На понятном и главное реальном примере описано, что к чему. Вот тут https://github.com/bem/bem-method/blob/bem-info-data/method/key-concepts/key-concepts.ru.md#Элемент например чётка написано почему именно в данном случае это не блок, а элемент. Всё по делу, но блин оно выглядит заброшено и по моему так оно и есть, хотя вроде бы инфа там актуальная.

PS:

Вот это просто убило https://github.com/bem/bem-method/blob/bem-info-data/method/bem-for-css/bem-for-css.ru.md#Совмещение-тега-и-класса-в-селекторе

Тут заставляют считать пункты приоритетов вручную, только чтобы показать как переопределить селектор (почему-то я думаю это довольно очевидно ну или можно это дать как факт или ссылку подкинуть - зачем так усложнять с этими вычислениями), а потом вывод "элементы потребуют четыре разные декларации для каждого случая." даётся уже просто так без всяких доказательств, хотя это момент важный.

Самое печальное, что тут такая ситуация когда словами всё объяснить крайне трудно. Я бы вместо этого словоблудия воткнул чего-нибудь типа jsfiddle с хорошим примером, чтоб можно было всё продемонстрировать живьём и дать возможность поиграться с кодом. Это тот случай когда "лучше один раз увидеть".

В общем всё это сугубо мое ИМХО

tadatuta commented 8 years ago

@webhive, спасибо за подробный разбор! Со всеми пунктами согласен.

@godfreyd Серега, принимай фидбек по доке.

webhive commented 8 years ago

Хмм ну раз согласен то лови ещё немножко - так сказать взгляд со стороны.

По БЭМ-у был просто отличный заход - статься если не ошибаюсь на хабре (копия вот этой) После неё осталось чувство - да блин в этом что-то есть, по крайне мере интересный способ победить бардак с CSS.

Потом была попытка применить, но очень скоро понимаешь, что руками эти именования классов поддерживать просто нереально. И тут оказывается, что всё уже изобретено и автоматизировано и есть bem-tools, bemjson - ого! Вообще отлично! И вот тут начинается полная ж...а. Как в стену упираешься. Я раз 4-5 пытался осилить как это всё вместе заставить работать. Дока унылая и с ошибками, сто-пятьсот способов сделать одно и то-же (навскидку - enb vs bem-tools vs gulp, bemhtml vs bemtree), мало живых проектов откуда можно подглядеть "как правильно". В результате остаётся какой-то осадок - да ну его нафиг - геморрой какой-то.

А дальше для меня лично вот таким поворотным моментом когда что-то в голове сложилось стало вот это видео

Вебинар по БЭМ: Трехзвенная архитектура веб-сервисов на bem-xjst

Вот этот вебинар в разы лучше и понятнее всей остальной документации. Простым русским языком рассказывается (и показывается код!!!) что нам надо вот это - берём и делаем вот так, а тут хоп и надо переделать - а мы хоп и вот так. И возникает понимание, что проблема которую без БЭМ решали бы многократными правками в нескольких местах в данной технологии решается быстро и элегантно. Да вот просто этот вебинар в текст перегнать и уже дока будет супер. У вас (команды яндекса) есть еще отличные вебинары по БЭМ. Так вот они гораздо более информативны и понятны - возьмите их что ли за основу.

Вот проблема - вот традиционное решение (сложно), а вот так это делаем мы (просто). Все!

Ладно - на оригинальный вопрос ответа не получил, так хоть пофлудил :)

qfox commented 8 years ago

Элемент же должен быть внутри страницы, а тэг уровнем ещё выше.

@webhive Ну тогда надо повесить класс на html? Вопрос в том, какой класс повесить? Ну, так-то html у нас только одна, и будет ли там висеть какой-то элемент page (да, элемент вне блока) или отдельный блок помощник — разницы никакой. Дело ваше, что там будет.

webhive commented 8 years ago

Ну хорошо, а класс тогда как повесить? У нас же в bemjson дереве page является самым верхним элементом. А чтобы класс добавить придется добавлять блок html и уже в него заворачивать page. С одной стороны - да - это по БЭМ, но с другой - ради одного свойства в тэге <html> добавлять блок и заворачивать в этот блок всё bemjson дерево.

Я тут подглядел в bem-core https://ru.bem.info/libs/bem-core/v2.8.0/desktop/ua/

Блок подключает инлайновый скрипт, добавляющий тегу CSS-классы,

Т.е. даже стандартные компоненты, которые вроде бы как должны представлять из себя образцово-показательный БЭМ код нарушают принцип независимости блоков и напрямую модифицируют DOM за своими пределами.

Вообще если смотреть шире раз уж у нас page задуман как компонент верхнего уровня - может в него бы стоило добавить возможность модифицировать head?

qfox commented 8 years ago

Ну хорошо, а класс тогда как повесить?

В шаблоне page, в месте, где мы генерируем тэг html.

https://github.com/bem/bem-core/blob/v3/common.blocks/page/page.bemhtml.js#L10-L11

Т.е. даже стандартные компоненты

ua это миксующийся блок и он синглтон, а синглтоны они всегда такие.

webhive commented 8 years ago

В шаблоне page, в месте, где мы генерируем тэг html.

Отлично! Спасибо!

webhive commented 8 years ago

Кстати ещё вопросик - я пробовал удалять deps файл и всё-равно всё работает. Как-то не совсем понятно насколько он нужен и нужен-ли вообще?

qfox commented 8 years ago

В deps.js файле надо указывать то, что используется непосредственно в файлах технологий.

Например, если в js есть использование modules.define('block-name', ['zavisimost'], ..., то явно надо прописать 'zavisimost' в deps.js. Или, если в js есть BEMHTML.apply({block: 'olala'}) — надо прописать depsByTech зависимость: [{tech: 'js', shouldDeps: {block: 'olala', tech: 'bemhtml'}}] — технология javascript текущего блока хочет bemhtml блока olala (шаблоны блока olala). Чаще всего, конечно, нужны будут не только шаблоны, поэтому в обычные зависимости блок olala тоже надо будет прописать (чтобы в итоговый css приехал код из блока olala: olala.css, а в js — соотв. olala.js).

webhive commented 8 years ago

Нее - это-то понятно. Вопрос в том, что я удалили этот файл (ну так вышло :)), а оно всё равно работает. Стало интересно - я всё с нуля пересобрал без этого файла, а всё равно работает. Вот и стало интересно - может как-то автоматом все зависимости разрулились. Тогда выходит, что не особо-то этот файл и нужен. Собственно меньше ручных файлов оно как бы даже и лучше, но вот какие-то сомнения гложут - всё ли верно.

tadatuta commented 8 years ago

@webhive Все равно работать оно может по нескольким причинам:

  1. Нужные зависимости присутствуют в декларации (например, в project-stub файл ?.bemdecl.js генерируется на основе ?.bemjson.js и все сущности из BEMJSON автоматически попадают в декларацию).
  2. Нужные зависимости предоставлены deps.js-файлами других блоков (и стало быть сломаются, если соседних блоков в какой-то момент не окажется рядом).
  3. Зависимости в принципе не нужны (например, стили для элемента написаны в файле блока).

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

qfox commented 8 years ago

может как-то автоматом все зависимости разрулились

Само чтоли? Нее, кашка сама себя не съест. Это же верно и про зависимости.

webhive commented 8 years ago

Все равно работать оно может по нескольким причинам ...

Спасибо! Изучу вопрос.