Основы верстки / подсказка к 8 задачке

Сегодня поверстаем фиксированную менюшку. Которая весит вверху окна и никуда не пропадает.

Начнем сначала просто с достаточно длинного текста. Если ты работаешь с большим окном, просто продублируй текст:

В лесу родилась ёлочка,<br>
В лесу она росла.<br>
Зимой и летом стройная,<br>
Зелёная была.<p>

Метель ей пела песенку:<br>
«Спи, ёлочка, бай-бай!»<br>
Мороз снежком укутывал:<br>
«Смотри, не замерзай!»<p>

Трусишка зайка серенький<br>
Под ёлочкой скакал.<br>
Порою волк, сердитый волк,<br>
Рысцою пробегал.

теперь попробуем добавить блок меню

<div class="menu">
    Менюшка
</div>

<!-- тут длинный текст --!>

<style>
    .menu {
        width: 100%;
        border: 1px silver solid;
        box-shadow: 0 0 4px silver;
        box-sizing: border-box;
        padding: 1em;
    }
</style>

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

<style>
    body {
        margin: 0;
        padding: 0;
    }
    .menu {
        /* ... */
    }
</style>

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

<style>
    body {
         /* ... */
    }

    .menu {
        width: 100%;
        border-bottom: 1px silver solid; /* поменял border на border-bottom*/
        box-shadow: 0 0 4px silver;
        box-sizing: border-box;
        padding: 1em;
    }
</style>

теперь обернем текст также в блок:

<div class="menu">
    Менюшка
</div>

<div class="content"> <!-- обернул-->
    В лесу родилась ёлочка,<br>
    В лесу она росла.<br>
    Зимой и летом стройная,<br>
    Зелёная была.<p>

    Метель ей пела песенку:<br>
    «Спи, ёлочка, бай-бай!»<br>
    Мороз снежком укутывал:<br>
    «Смотри, не замерзай!»<p>

    Трусишка зайка серенький<br>
    Под ёлочкой скакал.<br>
    Порою волк, сердитый волк,<br>
    Рысцою пробегал.
</div>

и добавим стиль с padding в класс:

<style>
    body {
        /* ... */
    }

    .menu {
        /* ... */
    }

    .content {
        padding: 1em;
    }
</style>

вот так получится

Imgur

правда менюшка не держится.

Для того, чтобы заставить блок оставаться на месте есть специально свойство position. Добавим его:

<style>
    body {
         /* ... */
    }

    .menu {
        /* ... */
        position: fixed; /* добавили свойство, фиксированная позиция */
    }

    .content {
        /* ... */
    }
</style>

вах, что получается:

Imgur

так, менюшка зафиксировалась, это хорошо. Но сразу видим первую проблему, меню прозрачное. Добавим цвета:

<style>
    body {
         /* ... */
    }

    .menu {
        /* ... */
        background-color: white; /* добавили цвет */
    }

    .content {
        /* ... */
    }
</style>

Imgur

уже симпатичнее. Осталась вторая проблема, меню перекрывает текст.

На самом деле это совсем не проблема. Решают ее очень просто. Добавляя отступ сверху блоку content:

<style>
    body {
        /* ... */
    }

    .menu {
        /* ... */
    }

    .content {
        padding: 1em;
        /* добавил отступ сверху, 4em потому что 1em -- высота строки,  */
        /* 1em+1em две строки padding сверху снизу в menu и 1em отступ текста от менюшки, */
        /* можно указать значение в пикселях, 1em = 16px, то есть можно указать 64px, либо вообще подогнать на глаз */
        padding-top: 4em; 
    }
</style>

вот теперь красота

И все, собственно менюшка хотя и фиксированная она все равно обыкновенный блок, можно пихать туда внутрь обыкновенные flex строки. Например, попробовать что-то похожее на менюшку инсты замутить:

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <div style="flex-grow: 1; flex-basis: 0;" >
            <img src="https://www.instagram.com/static/images/web/mobile_nav_type_logo.png/735145cfe0a4.png" alt="">
        </div>
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >Поиск</div>

        <div style="flex-grow: 1; flex-basis: 0; ; text-align: right;" >
            <i class="fas fa-user"></i>
            <i class="fas fa-cat"></i>
        </div>
    </div>
</div>

немного подправим стили:

<style>
    body {
        /* ... */
    }

    .menu {
        /* ... */
        padding-bottom: 0.5em; /* чуток подкорректировал отступ снизу, чтобы красивее смотрелось */
    }

    .content {
        padding: 1em;
        padding-top: 80px; /* так как лого инсты растянула меню, то и отступ содержимого увеличиваем */
    }
</style>

о как:

Добавляем поле для поиска

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

Для этого используется тег input

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <div style="flex-grow: 1; flex-basis: 0;" >
            <!-- ... -->
        </div>
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >
            <input class="search"> <!-- добавили, и сразу класс какой-нибудь приклеим -->    
        </div>

        <div style="flex-grow: 1; flex-basis: 0; ; text-align: right;" >
            <!-- ... -->
        </div>
    </div>
</div>

Imgur

так как input это просто блок в который можно только чего-то вписать его так же можно стилизовать:

<style>
    /* ... */

    .search {
        border-radius: 3px;
        background-color: #fafafa;
        color: rgb(153, 153, 153);
        border: 1px solid rgb(223, 223, 223);
        height: 24px;
    }
</style>

вот уже более похоже на настоящий

единственное при фокусе, в зависимости от браузера может появляется черная рамочка:

чтобы ее не было, надо добавить свойство outline: none


<style>
    /* ... */

    .search {
        /* ... */
        outline: none;
    }
</style>

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

Добавляем иконку с абсолютным позиционированием

Так как input это особый тег в него нельзя просто взять и запихать внутрь иконку (хотя вообще можно, но не рекомендуется). Поэтому корректный способ — это обернуть input блоком:

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <!-- ... -->
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >
            <div> <!-- обернул -->
                <input class="search"></input>    
            </div>
        </div>
         <!-- ... -->
    </div>
</div>

добавить иконку

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <!-- ... -->
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >
            <div>
                <input class="search"></input>    
                <i class="fa fa-search"></i>  <!-- добавил -->
            </div>
        </div>
         <!-- ... -->
    </div>
</div>

получится такое безобразие:

можно попробовать сделать flex строку:

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <!-- ... -->
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >
            <div style="display: flex;"> <!-- превратил обертку в flex -->
                <input class="search"></input>    
                <i class="fa fa-search"></i>
            </div>
        </div>
         <!-- ... -->
    </div>
</div>

если красиво выровнять, то вполне рабочее решение:

<div class="menu">
    <div style="display: flex; justify-content: space-between;">
        <!-- ... -->
        <div style="flex-grow: 1; flex-basis: 0; text-align: center;" >
            <div style="display: flex; align-items: center;"> <!-- поправил стиль -->
                <input class="search"></input>    
                <i style="margin-left: 1em;" class="fa fa-search"></i> <!-- добавил стиль -->
            </div>
        </div>
         <!-- ... -->
    </div>
</div>

но если все-таки хочется иконку именно внутрь запихать (а я хочу ее в правый угол инпута запихать), то надо воспользоваться снова свойством position. Только уже с другим значением. А именно значением absolute. Если position: fixed устанавливает строгое положение элемента на экране и не учитывает скроллинг, то свойство position: absolute закрепляет элемент относительно других элементов.

Теперь поставим position: absolute

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="margin-left: 1em; position: absolute;" class="fa fa-search"></i> <!-- добавил стиль -->
</div>

уберем margin:

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="position: absolute;" class="fa fa-search"></i>
</div>

как видим блок уехал в самое начало

Вообще этот position: absolute весьма непредсказуем, но по идее, чтобы попросить блок встать в правый край, надо установить свойство right: 0, ну типа правая граница блока встань на расстояние ноль от правого края:

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="position: absolute; right: 0;" class="fa fa-search"></i>
</div>

и он встанет, правда почему-то относительно всего окна:

на самом деле это стандартное поведение этого свойства, если поставить ему свойство left: 0

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="position: absolute; left: 0;" class="fa fa-search"></i>
</div>

то уедет влево экрана:

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

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="position: absolute; left: 100px; top: 50px" class="fa fa-search"></i>
</div>

это конечно здорово, но совсем не то что нам надо. А мы хотим на самом деле все-таки привязаться к правой границе:

<div style="display: flex; align-items: center;">
		<input class="search"></input>    
		<i style="position: absolute; right: 0;" class="fa fa-search"></i>
</div>

но только чтобы за правую границу считалась правая граница инпута. Для этого сделаем две вещи. Сначала укажем обертке, чтобы она стала базовым контейнером для расчета absolute значения. Это делается путем добавления свойства position: relative

<div style="display: flex; align-items: center; position: relative"> <!-- добавил !-->
		<input class="search"></input>    
		<i style="position: absolute; right: 0;" class="fa fa-search"></i>
</div>

получится так

На самом деле иконка выравнивается по краю обертки инпута:

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

<div style="display: flex; align-items: center; position: relative"> 
		<input class="search" style="width: 100%;"></input> <!-- добавил width !-->
		<i style="position: absolute; right: 0;" class="fa fa-search"></i>
</div>

о как:

добавим небольшой отступ иконки справа:

<div style="display: flex; align-items: center; position: relative"> 
		<input class="search" style="width: 100%;"></input> 
		<i style="position: absolute; right: 8px;" class="fa fa-search"></i> <!-- поменял right  !-->
</div>

красота:

можем контролировать размер инпута, если нам не нравится, что он резиновый, меняя width у обертки:

<div style="display: flex; align-items: center; position: relative; width: 150px">  <!-- добавил width   !-->
		<input class="search" style="width: 100%;"></input> 
		<i style="position: absolute; right: 8px;" class="fa fa-search"></i>
</div>

Это тема такая на самом деле специфическая, эти всякие position, но если разобраться позволяет делать интересные шутки.

8

Сверстать заголовок инсты, по возможности максимально похоже.

Обрати внимание на то что у круглых картинок есть границы, тень и и небольшой padding, градиентную границу у аватрки делать не надо, ее штатными средставми не получится сделать. Также цвет фона не белый а немного сероватый, чтобы сделать такой же добавь background-color в стиль body.

Смело используй margin и padding когда хочешь увеличить пространство между колонками или строками. Можно всегда указать значение только с одной стороны если добавить к свойству слова left, right, top, bottom, например:

.column-1 {
    margin-left: 10px;
		margin-right: 25px;
		margin-bottom: 10px;
		margin-top: 30px;
}

для выравниваний не забывай про justify-content и align-items, они очень похоже себя ведут.

Для строки, justify-content отвечает за выравнивание по горизонтали, align-items – по вертикали.

А для колонки (когда flex-direction: column) наоборт: justify-content отвечает за выравнивание по вертикали, align-items – по горизонтали.

на картинке примерная структура, чтобы соориентироваться