Константин Капельников

личная страница для коллег, работодателей, клиентов и делового нетворкинга

верстка

Создание красивого адаптивного алфавитного указателя

На сайте du9.org есть красивый список авторов.

Сделан он следующим образом:

В четырех колонках расположены списки фамилий, каждый со своей буквы.

Первые четыре буквы стоят вначале каждой из колонок. Затем при прокрутке вниз следующая буква “E” попадает в колонку, которая заканчивается первой. В данном случае это первая колонка с буквой “A”.

Затем по тому же принципу идут остальные буквы:

Первый этап

Загорелся сделать такое на одном из своих сайтов. Только у оригинала верстка не адаптивная, я же попробую сделать чтобы при уменьшении окна браузера 4 колонки на десктопе переходили в 2 колонки на планшете и затем в 1 колонку на мобильных. И списки по буквам должны вести себя аналогичным образом, т.е. следующая буква должна попадать именно в ту колонку, которая заканчивается первой.

Для адаптивности я использую свою простую колоночную сетку на флексбоксах на манер Бутстрапа:

<div class="row">
   <div class="col-lg-3 col-md-6 col-xs-12 abc_col-1"></div>
   <div class="col-lg-3 col-md-6 col-xs-12 abc_col-2"></div>
   <div class="col-lg-3 col-md-6 col-xs-12 abc_col-2"></div>
   <div class="col-lg-3 col-md-6 col-xs-12 abc_col-4"></div>
</div>

Таким образом col-lg-3 на десктопах будет делить 12 колонок на 3 и выстраивать списки в 4 колонки как на сайте исходнике, col-md-6 будет делить 12 колонок пополам и выдавать по 2 колонки на планшете, но а при col-xs-12 все колонки будут занимать всю ширину экрана.

Припишем к концу каждой колонки технические классы с номером (abc_col-1, abc_col-2 и так далее). Они будут нужны в дальнейшем для указания куда класть список следующей буквы.

Всю магию будем делать на jQuery. Но перед этим нужно определиться что нам выдает php-шаблон Вордпресса и какой HTML на выходе мы получаем.

Авторы просто идут друг за другом в одной колонке.

<p class="abc_main-letter" id="A">A</p>

<p class="abc_author letter A">Achdé</p>
<p class="abc_author letter A">Adam Święcki</p>
<p class="abc_author letter A">Alain Bardet</p>
<p class="abc_author letter A">Alain Dodier</p>
<p class="abc_author letter A">Alberto Madrigal</p>
...

<p class="abc_main-letter" id="B">B</p>

<p class="abc_author letter  B">Bartolomé Segui Nicolau</p>
<p class="abc_author letter  B">Bartosz Sztybor</p>
<p class="abc_author letter  B">Bastien Vivès</p>
<p class="abc_author letter  B">Bec</p>
<p class="abc_author letter  B">Benec</p>
...

Мне не удалось обернуть в шаблоне вывод авторов в тег списка <ul>, что семантически неверно, так как это именно список. В итоге каждая строчка пока идет в теге абзаца <p> с техническими классами и айдишниками.

Добавим красоту в css-стилях как у исходника и центруем.

.abc_author {
	text-align: center;
}

.abc_main-letter {
	background: url(img/bg-letter.jpg) center 263px no-repeat;
	font-family: 'LeagueGothicRegular', sans-serif;
	font-size: 300px;
	line-height: 285px;
	margin-top: 2px;
	margin-bottom: 2px;
	text-align: center;
	color: black;
}

Получаем уже красивые крупные буквы и список по центру:

Скрипты я подключил в шаблон footer.php перед закрывающим тегом <body>. Не стал навешивать на все страницы, прописал условие:

<?php
     if (is_category(“здесь ID категории авторов”)) {
	   $path = get_template_directory_uri();
	   echo "<script src='https://code.jquery.com/jquery-3.2.1.min.js'></script>";
	   echo "<script src='$path/js/abc.js'></script>";
	   }
?>

Все визуально выглядит пока вот так:

Также создадим технические дивы обертки для отдельных букв со списками и дадим им соответствующий технических класс.

<div class="letter-A"></div>
<div class="letter-B"></div>
<div class="letter-C"></div>
<div class="letter-D"></div>
<div class="letter-E"></div>
<div class="letter-F"></div>
<div class="letter-G"></div>
<div class="letter-H"></div>
<div class="letter-I"></div>
...

Первое, что мы делаем в jQuery — это кладем соответствующую букву и идущие за ним строчки в соответствующий <div>.

$('#A').appendTo( $('.letter-A') );
$('.A').appendTo( $('.letter-A') );

$('#B').appendTo( $('.letter-B') );
$('.B').appendTo( $('.letter-B') );

$('#C').appendTo( $('.letter-C') );
$('.C').appendTo( $('.letter-C') );

$('#D').appendTo( $('.letter-D') );
$('.D').appendTo( $('.letter-D') );

$('#E').appendTo( $('.letter-E') );
$('.E').appendTo( $('.letter-E') );

$('#F').appendTo( $('.letter-F') );
$('.F').appendTo( $('.letter-F') );

$('#G').appendTo( $('.letter-G') );
$('.G').appendTo( $('.letter-G') );

$('#H').appendTo( $('.letter-H') );
$('.H').appendTo( $('.letter-H') );

$('#I').appendTo( $('.letter-I') );
$('.I').appendTo( $('.letter-I') );
...

Затем нам нужно первые четыре буквы расставить по колонкам слева направо. Просто переносим дивы по номерам колонок (мы для этого создавали технические классы abc_col-1, abc_col-2… с номерами):

$('.letter-A').appendTo( $('.abc_col-1') );
$('.letter-B').appendTo( $('.abc_col-2') );
$('.letter-C').appendTo( $('.abc_col-3') );
$('.letter-D').appendTo( $('.abc_col-4') );

Теперь визуально это выглядит так:

Далее нужно определить куда класть следующую букву «E». Она должна попасть в колонку с меньшим количеством строк.

Для этого считаем число элементов по-буквенно, используя один из технических классов, и выведем сразу в консоль для наглядности:

var count_A = $('.A').length
console.log("столбец A", count_A);
 
var count_B = $('.B').length
console.log("столбец B", count_B); 

var count_C = $('.C').length
console.log("столбец C", count_C);

var count_D = $('.D').length
console.log("столбец D", count_D);

Затем посчитаем минимальное значение и выведем результат в консоль:

var count_min = Math.min(count_A, count_B, count_C, count_D);
console.log("минимальное значение начальных столбцов для E", count_min);

В итоге в консоли видим следующее:

В последнем столбце «D» количество строк минимальное. Значит нашу букву “E” нужно класть именно туда. Теперь нужно как-то сообщить это jQuery.

Делаем проверку на равнозначность минимального значения (11) и числа из каждой колонки. Если значения равные, то скрипт положит <div class="letter-E"> в эту колонку.

if (count_min == count_A) {
    $('.letter-E').appendTo($('.abc_col-1'));
}

if (count_min == count_B) {
    $('.letter-E').appendTo($('.abc_col-2'));
}

if (count_min == count_C) {
    $('.letter-E').appendTo($('.abc_col-3'));
}

if (count_min == count_D) {
    $('.letter-E').appendTo($('.abc_col-4'));
}

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

Чтобы этого избежать пишем следующее:

if (count_min == count_A && count_min == count_B) {
    $('.letter-E').appendTo($('.abc_col-1'));
} // если число строк буквы A и буквы B одинаковое, то клади в первую колонку

if (count_min == count_A && count_min == count_C) {
    $('.letter-E').appendTo($('.abc_col-1'));
} // если число строк буквы A и буквы C одинаковое, то клади в первую колонку

if (count_min == count_A && count_min == count_D) {
    $('.letter-E').appendTo($('.abc_col-1'));
} // если число строк буквы A и буквы D одинаковое, то клади в первую колонку

Это была первая часть. Мы раскидали по колонкам первые четыре буквы и положили в минимальную колонку следующую букву «E».

Второй этап

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

В начале я решал это следующим образом: просто считал число строк уже по всем колонкам, находил минимальное значение и клал туда следующую букву:

var count_abc_col_1 = $(".abc_col-1").find(".letter")
var count_abc_col_1 = $(count_abc_col_1).length
console.log("первая колонка", count_abc_col_1);

var count_abc_col_2 = $(".abc_col-2").find(".letter")
var count_abc_col_2 = $(count_abc_col_2).length
console.log("вторая колонка", count_abc_col_2);

var count_abc_col_3 = $(".abc_col-3").find(".letter")
var count_abc_col_3 = $(count_abc_col_3).length
console.log("треться колонка", count_abc_col_3);

var count_abc_col_4 = $(".abc_col-4").find(".letter")
var count_abc_col_4 = $(count_abc_col_4).length
console.log("четвертая колонка", count_abc_col_4);

var count_min = Math.min(count_abc_col_1, count_abc_col_2, count_abc_col_3, count_abc_col_4);
console.log("минимальное значение столбцов для F", count_min);

if (count_min == count_abc_col_1) {
    $('.letter-F').appendTo($('.abc_col-1'));
}

if (count_min == count_abc_col_2) {
    $('.letter-F').appendTo($('.abc_col-2'));
}

if (count_min == count_abc_col_3) {
    $('.letter-F').appendTo($('.abc_col-3'));
}

if (count_min == count_abc_col_4) {
    $('.letter-F').appendTo($('.abc_col-4'));
}

if (count_min == count_abc_col_1 && count_min == count_abc_col_2) {
    $('.letter-F').appendTo($('.abc_col-1'));
}

if (count_min == count_abc_col_1 && count_min == count_abc_col_3) {
    $('.letter-F').appendTo($('.abc_col-1'));
}

if (count_min == count_abc_col_1 && count_min == count_abc_col_4) {
    $('.letter-F').appendTo($('.abc_col-1'));
}

Консоль показывает, что буква «F» должна идти во вторую колонку:

Проблемы в процессе работы

Но по ходу столкнулся с одной не очевидной проблемой: в середине процесса заметил, что после буквы «J» должна идти буква «К», но почему то визуально встает буква «M». Стал проверять на предмет ошибки в подсчетах минимального числа строк в колонках, но все было правильно. В колонке 2 было 33 строки, а в колонке 4 было 30. Скрипт все подставил правильно, но визуально выглядело так, как будто буква «М» опережала букву «К» и попала не туда. Оказалось что на внешнее восприятие влияют сами буквы. Стилями они сделаны большими для красоты, и даже не смотря на меньшее число строк в колонке из-за самих букв колонка визуально смотрится больше.

В итоге подсчет числа строк для определения нужной строки не подходит.

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

var full_height1 = 0;
$(".abc_col-1 div").each(function() {
    full_height1 += $(this).height();
});
console.log("4 колонка", full_height1);

var full_height2 = 0;
$(".abc_col-2 div").each(function() {
    full_height2 += $(this).height();
});
console.log("4 колонка", full_height2);

var full_height3 = 0;
$(".abc_col-3 div").each(function() {
    full_height3 += $(this).height();
});
console.log("4 колонка", full_height3);

var full_height4 = 0;
$(".abc_col-4 div").each(function() {
    full_height4 += $(this).height();
});
console.log("4 колонка", full_height4);

var min_div = Math.min(full_height1, full_height2, full_height3, full_height4);
console.log("минимальная высота дивов для F", min_div);


if (min_div == full_height1) {
    $('.letter-F').appendTo($('.abc_col-1'));
}

if (min_div == full_height2) {
    $('.letter-F').appendTo($('.abc_col-2'));
}

if (min_div == full_height3) {
    $('.letter-F').appendTo($('.abc_col-3'));
}

Консоль:

Как видим все высчитывается более точнее с учетом визуальной составляющей и буква «K» спокойно перемещается во вторую колонку.

Планшетная и мобильная версии

С этим разобрались. Теперь делаем адаптивную подстройку букв для планшетов и мобильных. Напоминаю, что при сужении видимой области экрана до max-width: 1100px наша верстка из четырех колонок превращается в две (планшетный вариант). А при max-width: 640px в одну (мобильные). И наши буквы должны вести себя соответствующе.

Нам нужно динамически отслеживать изменение ширины экрана и реагировать на это. Для этого получаем ее значение. Создаем нужные переменные, прописываем функцию проверки ширины checkWidth() и кладем туда нужные условия.

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

Комментарий для мобильный версии: тут еще проще, мы просто складываем все буквы, начиная с В, в первую колонку и они спокойно выстраиваются в нужной порядке по алфавиту.

var $window = $(window);

function checkWidth() {

    var windowsize = $window.width();
    console.log(windowsize);

    if (windowsize >= 1100) {
        console.log("Еще десктоп");
    }

    if (windowsize < 1100 && windowsize > 640) {
        console.log("Уже планшет");

        $('.letter-C').appendTo($('.abc_col-4'));
        $('.letter-D').appendTo($('.abc_col-4'));
        $('.letter-E').appendTo($('.abc_col-4'));
        $('.letter-F').appendTo($('.abc_col-4'));
        $('.letter-H').appendTo($('.abc_col-4'));
        $('.letter-G').appendTo($('.abc_col-4'));

        // буква С

        var full_height1 = 0;
        $(".abc_col-1 div").each(function() {
            full_height1 += $(this).height();
        });
        console.log("1 колонка", full_height1);

        var full_height2 = 0;
        $(".abc_col-2 div").each(function() {
            full_height2 += $(this).height();
        });
        console.log("2 колонка", full_height2);

        var min_div = Math.min(full_height1, full_height2);
        console.log("минимальная высота дивов для C", min_div);

        if (min_div == full_height1) {
            $('.letter-C').appendTo($('.abc_col-1'));
        }

        if (min_div == full_height2) {
            $('.letter-C').appendTo($('.abc_col-2'));
        }

        if (windowsize <= 640) {
            console.log("Уже мобильные");
            $('.letter-B').appendTo($('.abc_col-1'));
            $('.letter-C').appendTo($('.abc_col-1'));
            $('.letter-D').appendTo($('.abc_col-1'));
            $('.letter-E').appendTo($('.abc_col-1'));
            $('.letter-F').appendTo($('.abc_col-1'));
            $('.letter-G').appendTo($('.abc_col-1'));
            $('.letter-H').appendTo($('.abc_col-1'));
            $('.letter-I').appendTo($('.abc_col-1'));
            $('.letter-J').appendTo($('.abc_col-1'));
            $('.letter-K').appendTo($('.abc_col-1'));
            $('.letter-L').appendTo($('.abc_col-1'));
            $('.letter-M').appendTo($('.abc_col-1'));
            $('.letter-N').appendTo($('.abc_col-1'));
            $('.letter-O').appendTo($('.abc_col-1'));
            $('.letter-P').appendTo($('.abc_col-1'));
            $('.letter-Q').appendTo($('.abc_col-1'));
            $('.letter-R').appendTo($('.abc_col-1'));
            $('.letter-S').appendTo($('.abc_col-1'));
            $('.letter-T').appendTo($('.abc_col-1'));
            $('.letter-U').appendTo($('.abc_col-1'));
            $('.letter-V').appendTo($('.abc_col-1'));
            $('.letter-W').appendTo($('.abc_col-1'));
            $('.letter-X').appendTo($('.abc_col-1'));
            $('.letter-Y').appendTo($('.abc_col-1'));
            $('.letter-Z').appendTo($('.abc_col-1'));
        }
    }

Посмотреть пример на CodePen

Новый формат блога

Решил перенести блог с Эгеи на Вордпресс и немного видоизменить дизайн. Эгея была хорошим решением для быстрого развертывания блогового проекта. Но для его расширения уже нужно что-то более серьезное.

Эгея vs Wp

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

Поэтому тут я «убиваю двух зайцев»: пытаюсь хотя бы базово освоить Вордпресс и заодно масштабировать разделы сайта. Его к слову я полностью адаптивно переверстал и «посадил» на движок самостоятельно без дочерних тем. Затем полученные практические знания планирую применять на своих проектах.

А пока постепенно восстанавливаю записи.

О прохождении интенсива Базовый HTML и CSS от HTML Academy

О курсе

Я давно присматривался к курсам HTML Academy. Смотрел видео со старых потоков. Мне импонировал такой мягкий питерский интеллигентный подход ведущих и вообще компании без излишнего навязывания и давления. В итоге решил попробовать пройти интенсив.

Это был 18-й и самый массовый поток из всех базовых интенсивов по верстке.

Большой поток на курсе

Немного статистики

В итоге получил массу информации, как сугубо практичной, так и околотематической для дальнейшего размышления.

Также информация в к этому потоку претерпела массу изменений: на место флоутам пришли флексбоксы, добавилась лекция о доступности интерфейсов, более подробно обсуждались нюансы спецификации HTML5 и много чего еще.

Рабочий процесс

Сам интенсив состоит из одиннадцати живых двухчасовых вебинаров, на которых различные спикеры рассказывают определенную тему.

Алексей Симоненко про DOM-дерево

Один из моих любимых спикеров Алексей Симоненко рассказывает DOM-дереве и JS

К вебинарам идут задания о прохождении бесплатных онлайн-курсов Академии и собственно верстке настоящего макета.

Макеты

На выбор давалось пять макетов, плюс один учебный для тренировок (лендинг барбершопа Бородинский).

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

Обзор выбранного многой макета вымышленной веб-студии Nerds

Сама работа над макетом приближена к реальным условиям веб-разработки. Все правки делаются через сервис контроля версий Гитхаб. Конечная верстка должна отвечать определенным критериям, чтобы проект прошел проверку. Критерии есть базовые (60%) и дополнительные. Притом если хоть один базовый критерий не выполнен, то и дополнительные не засчитываются.

При верстке макета помогает наставник, которого ты выбираешь в интерфейсе интенсива. Он дает в итоге допуск на финальную проверку. Работу же проверяет случайный наставник. Есть жесткий дедлайн сдачи проекта и три попытки.

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

Были даже жаркие споры. Я как интернет-маркетолог «топил» за свое:

Дебаты в группе Телеграмм

Но в целом делились секретами и помогали друг другу.

Наставник

Я немного провозился и выбирал наставника чуть ли не последним. Что забавно, всех наставников-девушек расхватали тут же. Остались только самые хмурые и некоммуникабельные на вид ребята. Я выбрал самого хмурого из Ингушетии 🙂

Выбор наставников

Но в итоге Мурат оказался отличным и ответственным наставником. А в конце сдачи проверки и вовсе выручал, чуть ли не за меня правив код.

Сдача проекта

Финальная сдача проекта была немного нервной. Я кое-где не так прочел и понял ТЗ, что привело к определенным переработкам и задержкам.

Плюс резко ухудшилось состояние отца, его положили на стационар. Мне приходилось через сутки дежурить у него.

Работа за ноутом в больнице

Я на больничной койке рядом с отцом доделываю проект вместе с наставником

А это постоянный недосып, ноутбук на 3g и верстка на больничной койке в неудобной позе.

Рейтинг сдачи 53%

После второй попытки ситуация стала напряженной

В итоге проценты по попыткам выглядят так:

  • 1 попытка — 42%
  • 2 попытка — 53%
  • 3 попытка — 93%

Уже немного жалею, что не поднажал и не закрыл проект на 100%. Но обстоятельства были сильнее и я рад, что хотя бы просто его сдал.

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

Академии, наставнику и ребятам в группе спасибо, увидимся на следующих интенсивах!

Сертификат Базовый HTML и CSS

,

Итан Маркотт [A Book Apart 04] Отзывчивый веб-дизайн

Ethan Marcotte [A Book Apart 4] Responsive Web Design

О чем

A Book Apart — серия небольших книг, преимущественно о веб-дизайне.

Их начал выпускать МИФ, но почему-то напутал с нумерацией. Эта книга в оригинальной серии четвертая, у МИФа — первая.

Я читал в оригинале. Сама книжка как можно догадаться из названия о том, как делать сайты адаптивными. Хотя после погружения в эту тему узнаешь, что «responsive» и «adaptive» в мире веб-разработки вещи разные. Поэтому книжка об отзывчивом дизайне.

О книжке узнал от другого автора. А именно из книги David Sawyer McFarland — CSS: The Missing Manual. В ней Макфарланд в главе об адаптивке указывает на Маркотта и называет его родоначальником самого термина. Это меня заинтриговало и решил прочесть.

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

Вот эти способы:

  1. Гибкие сетки;
  2. Адаптивные картинки;
  3. Медиазапросы.

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

Что понравилось

Однако самая крутая часть книги — последняя. В ней Маркотт начинает размышлять о юзабилити подходах и концепции «вначале мобильные».

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

Также вспомнилась картинка, которая как-то попалась мне в одном паблике о юзабилити:

Что люди ищут на сайтах

Мои эксперименты

Я попробовал сделать мою главную страничку (уже старую версию) адаптивной для маленьких экранов с помощью медиазапросов. Вот что получилось:

Мобильная версия сайта

,