klierik

Администратор
  • Публикации

    4470
  • Зарегистрирован

  • Посещение

  • Дней в лидерах

    76

Все публикации пользователя klierik

  1. klierik

    помогите с выравниванием текста

    Здравствуйте. Для решения этой задачи ознакомьтесь, пожалуйста, со статьёй https://webref.ru/course/css-text/text-properties
  2. Всем привет. А что если обсуждение работ будет проходить онлайн? С рекомендациями как улучшить свою работу, как предвидеть ошибки и писать качественный читабельный код. Предыстория Так сложилось, что я часто получаю письма с просьбой оценить вёрстку, подсказать что сделанно хорошо, что плохо, что можно было бы улучшить, какие ошибки были допущенны и как их избегать и так далее. А ещё чаще спрашивают как решить ту или иную задачу, над которой разработчик бётся последние пару дней, хотя решение заключено в паре строках кода. За последние несколько лет такой разбор полётов для меня стал как хобби. Я заметил что ошибки у начинающих повторяются. Приходится объяснять одно и тоже разным людям. Зачем это надо? Сообщество htmlforum.io существует ради того, что бы посетители имели возможность совершенствоваться, повышать свой профессиональный уровень, развиватся и помогать в этом другим. С этой же идеей мне пришла в голову мысль — вести раз в неделю скринкаст, в котором я буду делится своим мнением по поводу вёрстки, которая будет предоставленна на обсуждение. Как добавить вёрстку для оценки? Для того что бы иметь возможность оценить проделанную Вами работы, мне понадобится: Исходный код, выложенный на github, butbucket или любой другой вариант (пожалуйста, не выкладывайте код в архиве, пользуйтесь общедоступными ресурсами) Помимо исходного кода требуется доступ к итоговому результату через браузер. Для этого идеально подойдёт pages.github.com В комментарие к данному посту отпишитесь и предоставьте вышеуказанные данные Что будет в итоге? Вы получите анализ по следующим критериям: вёрстка: какие ошибки допущены, каким блокам не достаточно универсальности, какие проблемы могут возникнуть в будущем, как оптимизировать структуру и поднять гибкость разметки стили: буду обращать внимание на пользование пре-процессорами, предлагать решения которые помогут поддерживать код годами структура проекта: дам рекомендации по организации файловой системы и кода в целом, буду обращать внимание на пользование современными инструментами разработчика В итоге Вы получите анализ по своей работы с точки зрения построения долгосрочных проектов, которые поддерживаются годами, поделюсь своим виденьем какие изменения требуется изменить что бы код не превратился в боль разработчика в ближайшее время. Кстати, не лишним для Вас будет заглянуть в блок Пособие верстальщика и ознакомится предоставленными по теме статьями. Я буду опиратся на описанные в пособие основы в изучении Вашей работы. Когда и где будет обзор? Обзоры будут выкладыватся на канале YouTuBe, каждый вторник в 19.00. Первый обзор будет опубликован 7 августа 2018 г. Первый обзор отложен из-за непредвиденной высокой нагрузки. Как только материал будет готов — отпишусь комментарием в текущем посте. Я тоже хочу делать обзоры Предложение отрыто для всех. Если Вы считаете себя достаточно опытным что бы уметь анализировать работу других разработчиков, — напишите мне в личку @klierik. Стоимость Анализ вёрстки бесплатен. Я понимаю ценность данной информации для начинающих и предлагаю Вам то, чего у меня не было, когда мне доводилось делать первые шаги в веб-разработке. Но если случится так, что мой обзор Вашёй вёрстки помог Вам стать лучше, и есть неуталимое 🙂 желание проявить благодарность, — используйте донейшн. Таким образом у нас с вами будет взаимообмен. Вы получаете консультацию по своей работе, а в обмен поможете существовать данному сообществу.
  3. klierik

    Помогите вставить url. Не вставляется картинка

    я имел ввиду — к картинке. и посмотрите что показывает devtool
  4. klierik

    Помогите вставить url. Не вставляется картинка

    Здравствуйте. Проверьте путь к файлу.
  5. klierik

    Как поставить 3 блока в ряд

    Как вариант вот так:
  6. klierik

    Взаимодействие элементов из разных дивов

    В таком случае я искренне вам сочувствую. От вас требуется "собрать автомобиль", пригодный для эксплуатации, но запрещено устанавливать колёса.
  7. klierik

    Взаимодействие элементов из разных дивов

    В таком случае используйте PHP — после выбора категории сервер вернёт страницу с уже выбранными породами.
  8. klierik

    Взаимодействие элементов из разных дивов

    Здравствуйте. Проще всего это реализовать на JS
  9. Классы следует использовать по умолчанию везде, а "id", как правило, используются для js-скриптов. Такое разделение только на пользу
  10. По этому поводу почитайте статью Атрибут id
  11. klierik

    Создание таблицы в HTML

    Там очень простой интерфейс. Откройте и попробуйте.
  12. klierik

    Скачат много jpg филeов одним kликом

    В таком случае напишите свой парсер на nodejs на базе cheeriojs
  13. klierik

    Скачат много jpg филeов одним kликом

    Можно попробовать https://www.downthemall.net/ в паре со старой версией браузера.
  14. klierik

    Создание таблицы в HTML

    Ошибка в логике построения таблицы. Попробуйте воспользоватся генератором — https://www.tablesgenerator.com/html_tables
  15. klierik

    Проблема со слайдером slick

    Похоже на то что в момент инициализации slick — <div>на странице не найден.
  16. ℹ️ Статья не завершена, дополняется по мере реализации проекта. 0. Предисловие И так, когда у нас готова основа проекта (сборщик и организована структура) можно приступать к вёрстке. ℹ️ Вообще, как правило, и сборщик и структура проекта организовываются во время его разработки. Особенно это касается тех ситуаций, когда разработчику впервые ставят задачу на реализацию большого кол-ва вёрстки (от 100 и более часов на вёрстку макетов). Тогда и появляется надобность в использовании инструментом по сборке проекта. А количество стилей настолько велико, что хранить в одном файле крайне затруднительно. В статье расказывается как структурировать эти данные таким образом, что бы и разработчик, и другие участники команды, могли с лёгкостью читать, поддерживать и развивать изначально написанный "костяк". Спустя несколько лет грамотно организованная структура под конкретную задачу сильно упрощает поддержку кода и минимизирет затраты на рефакторинг кода (тем самым понижает стоимость разработки). Рабочая ветка: $ git checkout 2.0-html-assets Макет: Assets/Atoms.png Как правило, такой макет создаётся на протяжении создания дизайна дизайнером. Этот макет содержит как простые так и сложные элементы. Когда я выполнял работу по данному проекту этого макета ещё не было, — он появился лишь к концу выполнения Ну что же — ближе к делу! 1. Создание Assets И так, на "первых порах" мы начнём разработку с создания вайла с типовыми элементами. Но, мы не будем создавать сразу все, а лишь только основные простые (текст, кнопки, прочее). И по мере разработки данный файл будет дополнятся недостающими элементами проекта. В конце концов этот шаблон будет содержать приблизительно то же самое что и макет. 1.1 Создание файлов Создаём html файл templates/assets.html и SCSS файл, который будет отвечать этому блоку assets/scss/_assets.scss с исходным содержимым .assets { // } и не забудем импортировать этот файл стилей в общие стили в "styles.scss" @import "assets"; 1.2 Написание HTML Следующим шагом давайте наполним наш html-файл основным форматированием и простыми элементами, которые присутствуют в Assets. ℹ️ Непосредственно сам HTML код я не буду сюда выкладыввать, так как особого смысла в этом нет. Весь код доступен в репозитории. 1.3 Написание стилей 1.3.1 Подключение кастомных шрифтов В качестве основного шрифта дизайнер использовал Rubik из Google Fonts. Через конфигуратор я выставил значения жирности 400, 400i, 500, 500i и добавил Кирилицу: <link href="https://fonts.googleapis.com/css?family=Rubik:400,400i,500,500i&amp;subset=cyrillic" rel="stylesheet"> ℹ️ Данный подход подключения шрифта не является оптимизированным, но, пока что, нет задачи оптимизировать загрузку шрифтов. Потому будем его подключать "как есть". Далее следует указать использоавние данного шрифта в проекте. Для этого в файле конфигуратора (assets/scss/config/variables.scss) добавил следующие строки: // Fonts $theme-font-family-base: 'Rubik' !default; А теперь надо применить эту настройку в Bootstrap. Для этого откроем файл переменных Bootstrap (assets/scss/vendor/bootstrap/_variables.scss) и добавим следующее: // Fonts $font-family-base: $theme-font-family-base, $font-family-sans-serif; Пересобираем стили и смотрим удачное применение кастомного шрифта в проекте. 1.3.2 Типография Есть ряд элементов которые имеют стандартные стили во всём проекте. Но, так как нами изначально был подключен Bootstrap то сейчас стилизация этих элементов не соответствует макету. Это поправимое дело и его легко исправить. Для начала внесём изменения для заголовов H1-H6, добавив соответствующие значения перенменных для них в файл "bootstrap/_variables.scss". Выглядит это так: $h1-font-size: $font-size-base * 3.5; $h2-font-size: $font-size-base * 1.75; $h3-font-size: $font-size-base * 1.625; $h4-font-size: $font-size-base * 1.5; $h5-font-size: $font-size-base * 1.125; $h6-font-size: $font-size-base; Но, мы так же обратим внимание на то что каждый загловок, согласно макета, имеет свой "line-height". А H4 — "font-weight: 400;". Что бы внести эти изменения в проект мы создим файл "bootstrap/_type.scss" и внесём изменения: А так же импортируем эти стили в файле "bootstrap/bootstrap.scss" следующими строками в самом конце файла: // Custom Updates // @import "type"; 1.3.3 Цвета Цвета — это не отъемлемая часть дизайна, которая всегда присутвует в вёрстке. Их множество может быть, условно, безконечным. Под разные проекты конфигурировать палитру цветом предстоит индивидуально, так как задачи разные. У Вас может быть как не большая конфигурация цветов, из 10-15 штук, так и более сложный варинат — полноценная политра для мультитем, со своим индивидуальным набором цветов. В рамках данного обучения нет задачи создавать гибкую настройку по цветам, так как не предполагается их часто и\или кардинально менять. Палитру цветов для всего проекта мы опишем в файле "assets/scss/config/variables.scss" в разделе "// Colors". Цвета, для начала, возьмём из "Assets/Assets.png". Выглядеть это будет приблизительно вот так: ℹ️ Несколько раз я пытался как-то каталогизировать по смыслу цветовую палитру, но универсального варианта найти мне не удалось. В тех или иных случаях целесообразнее тот или иной вариант. Однажды я разрабатывал проэкт, который предполагал наличие разных тем со своей палитрой. Конфиг цветов был следующим: И так, мы начали создавать палитру цветов в конфигураторе. Теперь на примере Bootstrap давайте применим эту палитру к фреймворку. Для этого внесём изменения в файл "assets/scss/vendor/bootstrap/_variables.scss" // // Color system // $primary: $color-primary; $secondary: $color-secondary; $warning: $color-warning; $theme-colors: (); $theme-colors: map-merge(( "primary": $primary, "secondary": $secondary, "success": $success, "info": $info, "warning": $warning, "danger": $danger, "light": $light, "dark": $dark ), $theme-colors); Этими стилями мы переопределили основные цветы темы. Остальные цвета сохранили свои значения, которые идут изначально во фреймворке. ℹ️ Хочу обратить Ваше внимание на то что я не рекомендую добавлять в файл ("assets/scss/vendor/bootstrap/_variables.scss"), который отвечает за переопределение переменных Bootstrap, кастомные переменные. В этом файле я храню только изменения основных переменных. А вот в основном конфиге все другие переменные, которые используются в проекте. Таким образом в шаблоне "templates/assets.html" в тот же момент перекрасились кнопки Как можно заметить "Primary Button" имеет однотонный фоновый цвет, в отличии от того что в дизайне — градиент. Всё потому что конфигурация фреймворка предполагает использовать общую конфигурацию Bootstrap для всех элементов. Плохого в этом ничего нет, конечно же, но нам, в рамках разработки, это не подходит. Давайте перекрасим кнопку градиентом. 1.3.4 Стилизация элементов Bootstrap (на примере кнопок) Следующей задачей мы перерисуем кнопки фреймворка и сделаем их такими, какие они представленны в макете. Создадим файлы: "assets/scss/vendor/bootstrap/_buttons.scss" "assets/scss/vendor/bootstrap/_mixins.scss" "assets/scss/vendor/bootstrap/mixins/_buttons.scss" Далее импортируем их в "assets/scss/vendor/bootstrap/bootstrap.scss" // Custom Updates // @import "mixins"; @import "type"; @import "buttons"; А так же давайте импортируем файл с миксином в "assets/scss/vendor/bootstrap/_mixins.scss" @import "mixins/buttons"; ℹ️ Так как часть кнопок имеет border, а часть нет (что в свою очередь влияет на размер кнопки), мы напишем небольшой миксин, который будет выравнивать высоту для обоих случаев. Давайте добавим в файл "assets/scss/vendor/bootstrap/mixins/_buttons.scss" следующий миксин: Далее в "_buttons.scss" давайте добавим стили, которые изменят вид кнопок под требуемый нам (так же учтём и ":hover", ":focus" состояния) ℹ️ В данном решении используются не только переменные Bootstrap, но так же и кастомные, которые описанны в файле "assets/scss/config/variables.scss". Что же касается миксинов, которые используются в данном файле, то они были взяты непосредственно из кодовой базы Bootstrap — "node_modules/bootstrap/scss/mixins/" Теперь можно посмотреть что у нас в итоге получилось после наших модификаций Рабочая ветка: $ git checkout tags/2.0-html-assets-v1.0 -b 2.0-html-assets-v1.0 Добра и удачи 🙏
  17. Честно говоря я несколько недель думал стоит ли вообще писать эту статью. Сама тема является лютым холиваром и, по сути, каждый опытный разработчик давно для себя сформировал определённый стандарт форматирования стилей, который, на его взгляд, удобочитаем и лёгок в поддержке. Я не буду Вас переубеждать. Более того, если у Вас есть стандарт форматирования стилей, на котором написан не один проект возрастом от 3-5 лет и старше, если код не требовал рефакторинга из-за не грамотной организации стилей, если этот стандарт легко воспринимается и используется новыми сотрудниками — это очень классно. Это значит что Вы прошли богатый путь проб и ошибок и выявили для себя золотую середину. Я искренне за Вас рад! Но, так как кроме тех, кто умеет создавать внутренний стандарт в компании, есть разработчики, которые этого делат не умеют. Причина этому, скорее всего, — недостаток опыта. Ниже изложенная мною статья это рекомендации, а не готовое решение которое подходит в 100% случаев. Я никоим образом не хочу Вам навязать свои стандарты, а лишь поделиться тем опытом, который мне достался за более чеим 15 летний опыт в веб-разработке. Я буду искренне Вам благодарен если Вы ознакомитесь с данной статьёй и поделитесь своим виденьем на обсуждаемую тему. Вот краткий пример, который наглядно описывает обычный блок в проекте: .block-name { // Стили текущего блока // Стили всевдо-элементов &:before {} &:after {} // Стили псевдо-классов &:first-child {} &:last-child {} &:hover {} // @media стили текущего блока // Стили составных элементов &__title {} // Стили дочерних элементов .menu-list { &__item {} .link {} } // Стили модификаторов &_shown {} // @media стили иерархии дочерних элементов } Но что бы этот пример не был "сухим", довайте посмотрим на реальный код: .assets { &__title { font-size: 56px; font-weight: 500; padding: 56px 0 68px; line-height: 1.14; background: #00d6d9; color: #ffffff; & > .assets__section { padding-top: 0; padding-bottom: 0; } } &__sub-title { font-size: 28px; font-weight: 500; padding: 45px 0 9px; line-height: 1.29; background: #f9fafc; & > .assets__section { padding-top: 0; padding-bottom: 0; } } &__section { @if $enable-grid-classes { @include make-container(); @include make-container-max-widths(); } padding-top: 1rem; padding-bottom: 1rem; } &__colors { display: flex; flex-wrap: wrap; justify-content: space-between; padding: 0; list-style-type: none; .color { font-size: 13px; margin-bottom: 20px; width: 23%; border: solid 1px #e5e9ed; box-shadow: 3px 3px 5px 0 rgba(42, 43, 51, 0.1); &__preview { height: 90px; } &__name { font-weight: 600; padding: 14px 18px 6px; } &__hex { padding: 0 18px 14px; } &_gradient { width: 100%; } } } } Предполагаю с этим наглядным примером многое станет понятнее. Что же касается форматирования свойств, то я разделил их на 4 группы (каждая разделена пустой строкой для повышения читабельности) Свойства шрифтов Блочные свойства Текстовые свойства Стилизирующие и остальные свойства Порядок свойств, как правило, по алфавиту. ℹ️ Настройки форматирования стилей можно изменить. Про это рассказано в статье 1.4 Создание сборщика проекта. Пособие для верстальщика в разделе 1.4.6 Настройки форматирования стилей CssComb Ниже представлен более сложный пример, из реальной ситуации: ℹ️ Любите свой код, относитесь к нему надлежащим с уважением. Думайте о том, что его будут читать другие. Постарайтесь создать наиболее простые и комфортные условия для работы с Вашим кодом для любого разработчика в команде. Используйте в именах классов смысловую нагрузку — это сделает код читабельным без комментариев. Не создавайте глубокие цепочки иерархии класов, вместо этого продумывается простые структуры на столько на сколько это будет возможно. Добра и удачи 🙏
  18. 1.1 Конфигурирование темы проекта Ветка конфигуратора: $ git checkout 1.5-theme-config В данной статье речь идёт о создании структури стилей с гибкой конфигурацией, которая позволит выборочно импортировать модули фреймворка Bootstrap и применять к ним значения конфигурации проекта. 1.2 Организация структуры Ранее мы уже обсуждали организацию структуры проекта, но вскольз. Давайте размерём как организовать и подключить стили и скрипты. 1.2.1 Структура стилей Рассмотрим структуру директории стилей: ./assets/ ├── _mixin.scss ├── config/ - файлы конфигурации проекта │ └── variables.scss - пременные конфигурации ├── styles.scss - основной файл стилей, который импортирует стили проекта └── vendor/ - директория сторонних ресурсов ├── bootstrap/ │ ├── _variables.scss - файл с изменёнными значениями переменных │ └── bootstrap.scss - основной файл стилей Bootstrap └── vendor.scss - файл, который импортирует сторонние ресурсы Логика предложенной структуры такова (styles.scss): в начале мы импортируем переменные из конфига: "config/variabless.scss" далее импортируются все сторонние ресурсы (такие как Bootstrap) потом импортируются все стили проекта ℹ️ Стили проекта подключаются последними для того, что бы можно было пользоватся ресурсами сторонних ресурсов. На пример — использовать миксины Bootstrap grid. Для того что бы к Bootstrap так же применять настройки конфигуратора, их следует использовать в файле "vendor/bootstrap/_vartiabless.scss". Что бы это сделать в файл "vendor/bootstrap/bootstrap.scss", в котором поочерёдно импортируются все модули фреймворка, в первых строках добавлена запись: @import "variables"; // custom variables update которая будет импортировать обновлённые настройки Bootstrap. В результате чего, в конечном, итоге мы импортируем в проект Bootstrap и вносим в его конфигурацию значения из конфигуратора проекта. Это позволит управлять свойствами проекта из одного файла. Наглядно эта схема выглядит так: 1.2.2 Структура скриптов Директория со скриптами выглядит так: assets/ └── js/ - скрипты проекта └── vendor/ - сторонние скрипты └── slick-slider/ - slick slider (пример) В директорию "js/" мы складываем наши самописные скрипты, которые испольщзуются в проекте. В случае если скриптов много то, как правило, они помещаются в иерархию директорий по смыслу. В нашем проекте скриптов будет не много, потому мы будем складывать их просто в "js/" В директорию "vendor/" складываются скрипты стороних разработчиков. На пример slick slider или noUIslider. Так же не стоит забывать что скрипты могут быть подключены из предварительно установленных NPM пакетов, из директории "node_modules/module-name/". 1.3 Подключение модулей Bootstrap Зачастую в том или ином проекте используются не все модули Bootstrap. Некоторые модули используют скрипты, остальные нет. Мы рассмотрим оба варианта подключения ресурсов. 1.3.1 Подключение стилей Bootstrap Стили модулей подключаются в файле "assets/scss/vendor/bootstrap/bootstrap.scss". По умолчанию я, как правило, отключаю все модули, за исключением основных (reboot, type, grid, прочее). По мере вёрстки проекта я подключаю те, в которых нуждается проект. Вот пример файла в котором частично подключены только требуемые модули: 1.3.2 Подключение скриптов Bootstrap А вот скрипты модулей, в свою очередь, подлючаются через конфигурацию Сборщика проекта. Для этого следует открыть файл "gulp/config.js" и найти запись "config.scripts". Изначально все модули так же отключены для импорта, и по мере необходимости они подключаются в проект. Изначально конфигурация выглядит так: // // scripts configuration config.scripts = { files: [ config.path.sourceJS + '**/*.js' // , cofig.path.modulesDir + 'bootstrap/js/src/alert.js' // , cofig.path.modulesDir + 'bootstrap/js/src/button.js' // , cofig.path.modulesDir + 'bootstrap/js/src/carousel.js' // , cofig.path.modulesDir + 'bootstrap/js/src/collapse.js' // , cofig.path.modulesDir + 'bootstrap/js/src/dropdown.js' // , cofig.path.modulesDir + 'bootstrap/js/src/modal.js' // , cofig.path.modulesDir + 'bootstrap/js/src/popover.js' // , cofig.path.modulesDir + 'bootstrap/js/src/scrollspy.js' // , cofig.path.modulesDir + 'bootstrap/js/src/tab.js' // , cofig.path.modulesDir + 'bootstrap/js/src/tooltip.js' // , cofig.path.modulesDir + 'bootstrap/js/src/util.js' ], concatFile: 'scripts.js' }; Добра и удачи 🙏
  19. 1.1 Основные требования к сборщику Сборщик проект — это система сборки и задач, которая выполняет типовые задания автоматически, тем самым экономит время разработки проекта. Написанный нами сборщик (или билдер от англ. builder) должен стабильно работать в рамках проекта на протяжении всего его существования. Определимся со списком задач, которыми должден владеть сборщик: Иметь единый конфигурационный файл, в котором описываются настройки проекта и пакетов, которые участвуют в обработке ресурсов проекта Обрабатывать ресурсы проекта "на лету", после внесения в них изменений Генерировать стили проекта Генерировать prod-версию (максимальное сжатие и оптимизация) и dev-версию (без сжатия) Поддерживать Sourcemaps — для отладки стилей Поддерживать AutoPrefixer — для автоматического генерирования стилей под старые версии браузеров Поддерживать cssBase64 — для встраивания маленьких картинок (иконок размером, обычно, до 2048КБ) непосредственно в CSS Поддерживать CSSO — структурная оптимизация стилей Генерировать criticalCSS (про это можно ознакомится в статье Разбираемся с критичным CSS) Автоматически организовать стили проекта. При помощи csscomb.com приводить все стили к единому стандрату форматирования, что очень удобно для ситуаций, когда над проектом работает больше одного разработчика Собирать и генерировать скрипты проекта Генерировать prod-версию (максимальное сжатие и оптимизация) и dev-версию (без сжатия) Проверять код при помощи eslint — это инструмент проверки качества написанного программного кода на JavaScript Делать конкатенацию js-фалов (собирать все файлы в один) Иптимизировать изображения, которые используются в проекте Хочу обратить внимание на то, что требования составлены из целей создавать оптимизированный код и иметь гибкий инструмент для этого. В большинстве случаев бОльшую часть из этого списка Заказчик не требует (так как это повышает стоимость проекта). Но, так как автор последние пол десятилетия работает с высоконагруженными системами, где высокие требования к клиентской оптимизации идут "из коробки", то было решено использовать именно такой подход в данном обучении. Более простую версию билдера, имея эти знания, Вы сможете создать когда угодно. А за более сложную — Вы честно потребуете больший оклад, и будуте правы :) Но, так же обращаю внимание что нет пределу совершенству в оптимизации. В рамках обучения мы будем собирать все ресурсы (JS/CSS) в один файл. Но есть методы которые позволяют асинхронно подгружать как CSS (редкий случай), так и JS (обычное являние). Если Вам интересно углубится в мир клиентской оптимизации я советую начать с просмотра лекции Виталий Фридман: Responsive Web-дизайн. Трюки и уловки (всего 1:40 но море полезной информации). 1.2 Инициализация Этот этап разработки крайне прост. Да бы не повторятся в том о чём уже было сказанно в Интернетах множество раз я предлагаю посмотреть видео, в котором рассказываются шаги, которые будут проделанны на данном этапе: 1.3 Установка NPM пакетов Пакеты, которые мы будем в разработке условно поделим на 2 типа: ресурсы проекта (такие как jQuery, bootstrap, прочее) пакеты сборщика (ПО которое будет использоватся для обработки ресурсов для оптимизации, проверки кода, прочее) 1.3.1 Установка пакетов проекта Первым шагом установим пакеты, которые будут использоватся непосредственно в вёрстке: $ npm install -D jquery popper.js bootstrap 1.3.2 Установка пакетов сборщика Следующей командой установим пакеты которые будут использоватся для сборки ресурсов проекта $ npm i -D gulp-autoprefixer gulp-concat gulp-css-base64 gulp-csscomb gulp-debug gulp-if gulp-imagemin gulp-load-plugins gulp-sass gulp-sourcemaps gulp-uglify require-dir gulp-newer browser-sync gulp-notify gulp-notify through2 stream-combiner2 gulp-eslint penthouse gulp-csso gulp-babel babel-preset-latest babel-core Краткое описание предназначения устанавливаемых пакетов: 1.4 Сборщик проекта Ветка сборщика: $ git checkout 1.4-gulp-builder 1.4.1 Структура Файлы и директории которые отвечают за сборку проекта: . ├── gulp/ │ ├── .csscomb.json - файл настроек cssComb │ ├── .eslintrc - файл настроек eslint https://goo.gl/4K6TyF │ ├── config.js - файл настроек задач и пакетов Gulp │ └── tasks/ - задачи Gulp │ ├── scripts.js │ ├── server.js │ └── styles.js └── gulpfile.js - основной файл конфигурации Gulp Далее пройдём по всем файлам и обсудим что каждый делает. 1.4.2 Основной файл конфигурации Gulp Содержимое файла gulpfile.js 'use strict'; require('require-dir')('./gulp/tasks/'); const gulp = require('gulp'); // Default tasks gulp.task('default', gulp.series('styles', 'scripts')); gulp.task('dev', gulp.series('default', gulp.parallel('styles:watch', 'scripts:watch', 'server'))); Это основной файл конфигурации сборщика. Он легковеснее того, который Вы видели в Скринкасте по Gulp и вот почему... require('require-dir')('./gulp/tasks/'); Эта строка загрузки всех задачи, которые размещаются в директории "./gulp/tasks". После её выпонения будут загружены написанные нами задачи автоматически. const gulp = require('gulp'); Следующим шагом мы загружаем Gulp, так как ниже мы используем его для объявления задач // Default tasks gulp.task('default', gulp.series('styles', 'scripts')); gulp.task('dev', gulp.series('default', gulp.parallel('styles:watch', 'scripts:watch', 'server'))); А эти строки объявляют задачи, которые мы будем запускать для выпонения тех или иных операций. Первая задача "default" — это задача, которая запускается по умолчанию при запуске Gulp (если задачи для выполнения не указаны явным образом). На пример команда: $ gulp запустит те же задачи, которые будут запущенны если мы выполним: $ gulp default Значит при выполнении этой команды будут запущены задачи "styles" и "scripts", а чём нас проинформирует терминал: $ gulp [16:48:19] Using gulpfile ~/http/htdocs/aworker/aworker-education/gulpfile.js [16:48:19] Starting 'default'... [16:48:19] Starting 'styles'... [16:48:20] Finished 'styles' after 1.36 s [16:48:20] Starting 'scripts'... [16:48:21] Finished 'scripts' after 250 ms [16:48:21] Finished 'default' after 1.61 s Вторая задача "dev" будет выпонять другой набор. Для начала будут веполнены задачи, описанный в "default". Потом паралельно запустятся задачи: "styles:watch" — мотиторинг фалов стилей в ожидании изменений "scripts:watch" — мониторинг файлов скриптов в ожидании изменений "server" — запустится локально статичный веб-сервер, который будет доступен оп адресу http://localhost:3000/. А так же автоматически откроется окно с этим путём в браузере Googlee Chrome. Вот как это выглядит в терминале: Что бы посмотреть весь список задач которые доступны для запуска выполните команду: 1.4.3 Режим отладки Сборщик позволяет выпонять задачи как для продакшена (минимизация стилей, скриптов, картинок, прочее) так и версию для разработки. По умолчанию задачи выполняются для продакшена. Что бы запустить сборщик в режиме отладки, требуется выполнить следующую команду $ NODE_ENV=develop gulp Если требуется запустить мониторинг файлов и сервер то выполните следующее NODE_ENV=develop gulp dev 1.4.4 Файл конфигурации проекта Почти все настройки, которые мы будем использовать в задачах Gulp, для большего удобства, были вынесены в индивидуальный файл. Это позволяет использовать в задачах только переменные, значения которых определены в одном месте. Такой подход упрощает процесс конфигурации сборщика проекта. Файл размещается по адресу — "gulp/config.js". Полную версию файла Вы можете увидеть в репозитории, я лишь приведу наглядный пример как он оформлен: 1.4.5 Настройки eslint Для проверки JavaScript кода используется gulp-eslint пакет. Он требует присутвия файла настроек, согласно которых будет проверятся код. Файл размещается по адресу "gulp/.eslintrc" и содержит настройки, которые так же можно сгенерировать самостоятельно в онлайн генераторе 1.4.6 Настройки форматирования стилей CssComb Файл "gulp/.csscomb.json" отвечает за то, как будут автоматически форматироватся исходные стили проекта, приводя их к единому формату. Файл достаточно большой, выкладывать его здесь будет избыточно. Посмотрите на его содержимое в репо. Свой файл настроек CssComb можно создать в онлайн генераторе 1.4.7 Настройки Autoprefixer Согласно оффициальной документации gulp-autoprefixer, указать в директиве "browsers" для каких браузеров следует применять вендорные префиксы можно непосредственно в конфигурации: const gulp = require('gulp'); const autoprefixer = require('gulp-autoprefixer'); gulp.task('default', () => gulp.src('src/app.css') .pipe(autoprefixer({ browsers: ['last 2 versions'], cascade: false })) .pipe(gulp.dest('dist')) ); Но, в официальной документации Autoprefixer сказано несколько иначе: Они рекомендуют использовать или файл ".browserslistrc" (который должен лежать в корне проекта) или директиву в файле "package.json". Требуется это для того, что бы другие плагины (такие как: Babel, postcss-preset-env, eslint-plugin-compat, stylelint-no-unsupported-browser-features, postcss-normalize) так же пользовались этими настройками. Об этом рассказано на странице плагина Browserslist. По этому мы добавим эти настройки в файл package.json "browserslist": ["last 2 version", "> 5%", "iOS >= 7"] 1.4.8 Задачи Gulp Теперь давайте перейдём обсуждению непосредственно задач, которые присутвуют в сборщике проекта. ℹ️ Обращаю внимание читателя на то, что описанные ниже задачи могут быть не полностью описанны (или не все). Только те задачи и в том виде, когда автор писал эти строки. Но, скорее всего, у Вас не будет проблем в понимании как они работают и для чего созданы. В случае если что-то будет не понятно — задавайте вопросы 🙂 1.4.8.1 Сборка стилей Файл задачи сборки стилей расположен по адресу "gulp/tasks/styles.js". Полную версию файла Вы можете найти в репо, а тут давайте обсудим что он делает. Задача "styles" выполняет сборку стилей SCSS -> CSS. Настройки, которые используются в задачах предварительн описанны в файле "gulp/config.js" 1.4.8.2 Форматирование стилей Ещё одной важной для нас задачей будет форматирование стилей. Эта задача приведёт в порядок все стили Поясню почему "*variables*" вынесены из обработки под катом. 1.4.8.3 Создание criticalCss В нашей разработке мы так же будем генерировать criticalCss. В одной из следующих статья мы поговорим как эти стили должны использоватся а пока обсудим как их создавать. Сама задача, которая генерирует criticalCss-файл имеет мало кода: Для выполнения задачи в файле "gulp/config.js" есть список параметров, приблизительно такой: Все настройки описанны в на офф. странице в соответствующем разделе Options. Я лишь обращаю Ваше внимание одни из наиболее важных параметров: forceInclude — принимает массив, согласно которого будут добавлены стили, которые не были добавлены в criticalCss автоматически propertiesToRemove — принимает массив, согласно которого будут удалены стили из criticalCss Что же делает penthouse? Пакет создаёт виртуальное окно браузера (для этого используется puppeteer), размер которого указан в настройках (в выше приведённом примере это 1200x960). Далее penthouse проверяет какие из стилей присутвуют в этой области документа (в частности проверяет какие элементы присутвуют в области) и сохраняет их в указанном файле. Остальные стили, которые не попадают в область видимости (находятся за экраном) — не учитываются. ℹ️ Обращаю Ваше внимание на то, что зачастую в criticalCss так же не попадают стили элементов (или не полностью), которые по тем или иным причинам не отображались в момент их генерирования. Но разработчик может добавить их самостоятельно, указав в настройках. На пример: forceInclude: [ /^\.dialog/, // Будут добавленны все стили классов, которые начинаются с ".dialog" '.configurator' // Будут добавленны стили, которые применены к классу ".configurator" ], Режим отладки penthouse В случае если возникнут какие либо проблемы в создании "critical.css" следующей командой можно запустить задачу с выводом в терминал служебной информации: $ env DEBUG="penthouse,penthouse:*" gulp styles:critical ℹ️ В случае если Вам требуется создать criticalCss сразу для нескольких URL обратите внимание на оффициальный пример 1.4.8.4 Сборки скриптов Одной из не мало важных задач так же является сборка и минимизация скриптов. Задача расположена в файле по адресу "gulp/tasks/scripts.js". 1.4.8.5 Линтер скриптов Как работает данная задача шикарно изложенно в скринкасте Ильи Кантора — Более сложный поток: eslint, gulp-if, stream-combiner2 Особо тут добавить нечего, потому выложу только сам код, который используется в рамках нашего обучения Итоги подведём Подводя черту под вышесказанным хочу сказать, что мы рассмотрели более-менее универсальный вариант сборщика, под нашу задачу. От проекта к проекту на Вашум пути в разработке будут попадатся разные задачи, которые можно будет реализовать разными способами. Выбирайте тот который проще для понимания и поддержки другими разработчиками на сколько это возможно. Не создавайте слишком сложные конфиги но и не дробите их на множества файлов — это излишне. Соблюдайте баланс между гибкостью в коде и сложности его исполнения. Эти простые рекомендации позволят Вашему коду годами выполнять свою задачу, поддерживатся и изменятся без особых трудозатрат. Добра и удачи 🙏
  20. 1 Технические требования к среде разработки Дорогой читатель, проект, который реализуется в рамках данного обучения, имеет определённые требования к среде разработки. Нам потребуется использовать препроцессоры, инструменты оптимизации и проверки кода. По мере того, как вес веб-страницы в реалиях соверменного мира растёт, в выиграше остаются те, у которых вес и скорость загрузки страниц меньше, чем у конкурентов. Мы создадим инструмент, который позволит "не лету" обрабатывать и оптимизировать наш код, уменьшая его в размере и времени загрузки. 1.1 Node.js Для сборки проекта нам понадобится установленный Node.js версии LTS (на момент публикации данной статьи версия node.js — 8.11.1). В качестве менеджера версий использовался nvm Когда оба ПО установленны выполняем в терминале следующую команду $ nvm install --lts Installing latest LTS version. Downloading and installing node v8.11.1... Downloading https://nodejs.org/dist/v8.11.1/node-v8.11.1-darwin-x64.tar.gz... ######################################################################## 100.0% Computing checksum with shasum -a 256 Checksums matched! Now using node v8.11.1 (npm v5.6.0) И в итоге будет использованна актуальная LTS версия Node.js 1.2 GulpJS В качестве сборщика в данном обучении будет использоватся GulpJS. Данный инструмент выбран как наиболее подходящий для данной задачи. В следующей статье разговор пойдёт о создании сборщика. Я настоятельно рекомендую посмотреть замечательный Cкринкаст по GulpJS что бы понимать в будущем что мы будем делать и как это работает. После уставки Gulp локально и глобально их версии, на момент публикации данной статьи, были следующие: $ gulp -v [20:16:35] CLI version 2.0.1 [20:16:35] Local version 3.9.1 2. Организация структуры файловой системы В данном разделе я даю общие рекомендации по организации структуры файловой системы (в рамках реализации нашего проекта). Но, хочу обратить ваше внимание на то, что описанные рекомендации могут изменятся в зависимости от проекта. Так как в рамках задачи нам следует создать только вёрстку, без её интеграции в серверный код, наша структура будет достаточно простая: . ├── assets/ - ресурсы │ ├── images/ - картинки │ ├── js/ - js-скрипты проекта │ └── scss/ - стили проекта ├── .gitignore - список ресурсов, которые не следует добавлять в GIT ├── gulp/ │ ├── .csscomb.json - файл настроек cssComb │ ├── .eslintrc - файл настроек eslint https://goo.gl/4K6TyF │ ├── config.js - файл настроек задач и пакетов Gulp │ └── tasks/ - задачи Gulp ├── gulpfile.js - основной файл конфигурации Gulp ├── node_modules/ - npm пакеты ├── package-lock.json ├── package.json - файл, в котором описана информация о проекте и версиях пакетов, которые используются в проекте ├── public/ - директория, в которую будут генерироватся обработанные/сжатые ресурсы └── templates/ - html шаблоны 3. Структура HTML файлов За основу типичного html-файла взят пример от Bootstrap, описанный в документации: Все html-файлы в данном материала так или иначе будут основыватся на эту структуру. Добра и удачи 🙏
  21. По мере выполнения тех или иных задач я делал коммиты в репо, специально созданный для обучения. Для навигации по выполненой работе я использовал ветки в Git. Для тех кто не знаком с Git я рекомендую начать от сюда: 1.5 Введение - Установка Git .1 Введение - О контроле версий Git: советы новичкам — часть 1 Git: советы новичкам — часть 2 Git: советы новичкам — часть 3 Вы можете выполнять задания по мере прохождения обучения и сверять выполнную Вами работу с обучающим материалом, которые представлен в репозатории. Для навигации по веткам будет предложено переключится на ветку или тег. Пример: # Переключится в ветку git checkout origin/<branch_name> -b <branch_name> # Переключится по тегу git checkout tags/<tag_name> -b <branch_name> Если же говорить более предметно то следующая команда позволит переключится на ветку, в которой создан сборщик: $ git checkout 1.4-gulp-builder Сделанно это для бОльшего удобства, так как в рамках конкретной ветки может существовать несколько меток (тегов) кода, которые поэтапно имеют изменения. Добра и удачи 🙏
  22. Вступление Первое с чем сталкивается верстальщик — макет. Для начала следует проанализировать layout, блоки и элементы макета, что бы оценить время, которое потребуется на его реализацию. Техническое задание Требуется сверстать макет дизайна сайта. В качестве основы использовать Bootstrap последней актуальной версии. Вёрстка должна поддерживать Responsive Web Design и корректно отображается в браузерах, версии которые поддерживает фреймворк. Сетку проекта так же следует использовать из фреймворка. Дизайн Макеты, представленные в рамках проекта, в подавляющем большинстве для Desktop. Задача разработчика опираясь на текущие макеты реализовать Tablet и Mobile версии, учитывая сетку фреймворка. Допускаются незначительные отклонения в реализации, которые не влияют на функциональную часть проекта. За конечную реализацию и визуальное отображение отвечает исполнитель (разработчик). Заказчик за ранее соглашается с тем, что выбранное решение исполнителем будет наиболее подходящее для той или иной задачи. Но, в спорных моментах, когда видеться несколько путей решения задачи, разработчику следует обратится к заказчику для обсуждения решения. Реалии этого мира Дизайн, который я взял для реализации поставленной задачи, из реального проекта, который разрабатывался в конце 2017 г., за который не было выплачено ни цента. Он был представлен в рамках среды программы Zeplin, потому исходников нет. Но, по сути сам дизайн достаточно простой и даже по предоставленным PNG можно воспроизвести его в разметке. Поддержка браузеров Вёрстка должна корректно отображатся и работать в следующих браузерах: Последние 2 версии любого современного браузера В любом браузере, доля которого на рынке более 5% (согласно мировой статистике) Версия iOS 7 и выше Анализ макета Когда разработчик, или команда разработчиков, принимают проект то наличие макетов делится на 2 варианта ситуации: Присутвуют все макеты. Они утверждены заказчиком и можно приступать к работе Присутвует лишь часть макетов. Но так как сроки горят, требуется начинать работу уже вчера. Этот вариант сложнее, так как невозможно спрогнозировать как будет видоизменяться UI и, следовательно, каким изменениям будет подтвержены блоки страницы. В таких случаях Заказчика больше интересует время, и он согласен жертвовать временем, так как в процесе разработки будут затраты на рефакторинг кода (в лучшем случае) и частичная перепись кода из-за новой логики работы (в худшем случае). В рамках данного обучения мы будем опираться на первый вариант — есть все макеты для создания вёрстки под Desktop и Mobile. И так, вопросы технического характера изучены, цель поставленна. 1. Layout's Давайте определим какими они бывают: Одноколоночный — присутвует одна колонка для размещения контента Двухколоночный — присутвует основная колонка для размещения контента и дополнительная справа\слева для размещения второстипенных блоков Трёхколоночный — присутвует основная колонка для размещения контента и две дополнительных колонки для размещения второстипенных блоков Произвольный/Кастомный — данный тип layout строго не выражен, имеет плавающее расположение блоков и контента. Как правило такой вариавнт можно увидеть на Landing page. По сути любой вариант layout, который нельзя назвать одним из первых трёх вариантов можно считать произвольным, а его тип каждый может называть по своему. Приведу, на вскидку, несколько вариантов типов layout, которые мне часто встречаются в работе, где его название полностью соответствует смыслу его пользования: popup, modal, print, empty Помимо всего прочего вне зависимости от кол-ва колонок layout может быть как фиксированной ширины (имеется ввиду ширина контейнера, в котором размещаются колонки, но с учётом Responsive) так и по ширине страницы (в таких случаях контейнер занимает всю или почти всю ширину окна браузера). Для начала посмотрим какие layout's представленны в макетах: "Customer Flow/All Screens/homepage-customer.png"— одноколоночный, по ширине страницы "Customer Flow/All Screens/SEO-services.png", "Customer Flow/Search/search-services-results.png" — двухколоночный, фиксированная максимальная ширина "Customer Flow/Chat/customer-chat.png" — двухколоночный, по ширине страницы Так же обратите внимание что на страницах с максимальной фиксированной шириной присутвуют элементы, которые занимают всю ширину страницы. Это Header и блок под ним, который выступает в роли описания страницы или слайдера (как это показано на домашней странице). Все остольные макеты дизайна подпадают под один из этих layout's. Теперь мы знаем структуру страниц и как контент будет размещатся на них. Но, мы сразу будем учитывать на будущее что кол-во layout's может вырости, а значит их создание не должно как либо влиять на контент. Данная часть разметки должна быть самодостаточной, универсальной и легкорасширяемой. В общем по этому принципу будет создаваться львиная часть блоков веб-сайта. 2. Блоки и элементы Если с layout вопрос решается достаточно быстро, то с блоками и элементами этот процесс длиться дольше. А так как "время = деньги", особо много вкладывать времени в это не хотелось бы. Нам надо определиться какие блоки заведомо имеют визуальные отличия в зависимости от контента и/или наполнения, а какие нет (следует учесть что последние, в перспективе, могут видоизменятся). Так же нам следует определится с примитивными элементами (поля, рейтинги, кнопки, простые конструкции, аватарки, элементы интерфейса). Это нам позволит изначально раздельно описать их без какой либо зависимости от контекста, в котором они будут размещаться. 2.1 Header и Слайдер Начнём с домашней страницы — "Customer Flow/All Screens/homepage-customer.png" Кнопки, которые присутвуют в заголовке и в слайдере одного стиля. Но, они не одинаковые, так как у них разные поля и высота что, в целом, обычное дело для таких элементов. Это нам говорит что в данных блоках будут использоваться стандартные элементы интерфейса, но с некоторыми локальными изменениями. А ещё следует обратить внимание на поле для ввода в строке поиска. Оно тоже кастомное, так как в формах поля выглядят иначе (формы, как правило, задают стиль полям на всём сайте, которые, в случае надобности, имеют локальные изменения в рамках блока). 2.2 Блоки главной страницы Опускаемся ниже и видим 4 блока, которые на первый взгляд разные. Но если разбрать на примере то станет понятно, что блоки имеют область для Заголовока и Контента, что делает их однотипными. Заголовки "Как работает Aworker" и "Популярные услуги" однотипны Этим мы и будем пользоватся во время разработки как тут, так и в других аналогичных ситуациях. А дальше по странице ещё более интересная ситуация Как видим на скриншоте в разных блоках один и тот же блок — аватар пользователя. Он, если пробежатся по макетам, встречается в разных комбинациях на рызных страницах в разных блоках. Не смотря на то что, с виду, это минорный элемент страницы, забегая вперёд скажу что это сложный конфигурируемый блок, который будет отображать ряд дополнительныйх данных. Об этом мы узнаем в процессе разработки. Ниже несколько примеров где этот блок отображается 2.3 Блоки на внутренних страницах Далее давай посмотрим на страницу — "Customer Flow/All Screens/SEO-services.png" В лево колонке отображены блоки фильров, которые так же имеют идентиынй дизайн. Все, кроме блока "Типы услуг". Этот блок частично схож, но имеет индивидуальный контет — список тегов. В основной области лэйаута разместился список курьеров, который содержит информацию о пользователе и органы взаимодействия Этот блок нам частично знаком, так как он содержит блок пользователя, которыйй состоит из: аватара, имени, строки состояния и строки экшенов. Это не все варианты модификации данного блока и мы это будем учитывать в разработке. 2.4 Внутрение layout Ранее мы уже говорили про layout's, но в разрезе общего оформления страницы. Сейчас же мы посмотрим на layout в рамках блока В данном блоке, да и в других, нам будут попадатся ситуации когда содержимое блока потребуется поместить в N-колоночный лейаут, который, при том же, будет видоизменятся в размерах и расположении элементов в зависимости от ширины экрана. Такие конструкцию "тяжелее", по сравнению с обычными лэйаутами, которые используются для описания структуры страницы. Связанно это с тем, что описание структуры страницы, как правило, в случае измнения её ширины, из N-колоночного макета видоизменяется в одноколоночный. В случае же с layout's внутри блоков, за частую, колонки меняются местами между собой и\или меняюи свои размеры. Во время анализа макета я стараюсь обращать внимание на то, как элементы блока перемещаются по странице в результате изменения её ширины. Предвидя на перёд такие нюансы можно написать более универсальный код, который потом потребует существенно меньше изменений в непредвиденных ситуациях. 3. Итоги подведём По образу и подобию таким образом разработчик ознакамливается с предоставленными от заказчика макетами. Перед тем как начинать разработку ожидается что итоговая картина лэйаутов, блоков (и их модификаций), а так же их содержимого, прорисована в его голове. Добра и удачи 🙏
  23. Для кого Данная серия статей нацелена на html разработчиков, которые владеют азами html разметки, умеют пользоваться CSS а так же владеют JS на базовом уровне. Конкретнее говоря аудитория, которой будет интересен данный материал, — это начинающие специалисты в сфере вёрстки, которые создают не сложные странички, используя язык гипертекстовой разметки (html) и каскадные таблицы стилей (CSS) с применением простых скриптов JavaScript (чаще всего jQuery). Разработчикам предлагается материал который поможет повысить уровень знаний в предметной области, что в итоге должно привести к профессиональному и финансовому росту. Новичкам, которые только начинают своё ознакомление с вёрсткой, освоение данного материала может быть затруднительно по нескольким причинам: материал нацелен на уровень разработчики junior-middle автор материала не является редактором, но старается изложить в максимально доступной и простой форме на сколько это ему под силу Для чего Цель данных статей помочь в профессиональном росте специалистам-верстальщикам, научится пользоваться современными инструментами, анализировать объем работ, за ранее выявлять будущие ошибки, писать легко читаемый и самодокументируемый код, научится быстро выявлять проблемы и пути их решения, стремится к решению сложных и сверхсложных задач. Научится давать оценку времени на реализацию и писать/оформлять код для долгосрочных проектов (700+ часов на реализацию с последующей поддержкой и разработкой). Опираясь на свой опыт автор столкнулся с проблемой отсутствия на рынке специалистов в области вёрстки (не путать с front-end developer). За последние годы подбирая кадры всё реже и реже попадаются те, кто хорошо разбирается в предметной области. Об авторе Автором данного материала является @klierik, работающий в сфере web-разработки с начала 2000-х. В данной серии статей автор делится своим опытом на примере проекта, срок реализации которого более 100 часов. Хочу обратить ваше внимание на то что видение, изложенное в статьях является личным, и никоим образом не обязывает кого либо думать и делать так же. Я бы сказал так — я стремлюсь поделится своим опытом в надежде, что читатель проанализирует изложенный материал, поймёт суть и будет использовать основные принципы в повседневной работе, получать от неё удовольствие, усовершенствовать и делится идеями с другими разработчиками. Я надеюсь что читатель, прочитав материал, будет творить код, опираясь на простой принцип: код должен быть самодокументируемым, оформлен таким образом, что бы другие разработчики могли легко его понять и просто модифицировать без последствий для проекта. Добра и удачи 🙏
  24. klierik

    Помогите выровнять текст в потоке float

    Здравствуйте. Попробуйте вот так: .Departure { float: none; clear: left; color: #727272; font-size: 15px; margin: 0px auto; text-align: center; }