Статьи

Создайте клон Twitter с нуля: дизайн

Эта статья представляет собой первое в новой групповой работе сотрудников Nettuts +, которая охватывает процесс разработки и создания веб-приложения с нуля — на нескольких языках! В качестве основы для этой серии мы будем использовать вымышленный твиттер-клон под названием Ribbit.

В этом уроке мы должны сосредоточиться на пользовательском интерфейсе. Мы будем использовать популярный препроцессор LESS, чтобы сделать наш CSS максимально управляемым.


Обязательно загрузите ресурсы для этого урока, если будете работать вместе.

Этот урок разделен на пять основных частей, которые объясняют, как стилизовать различные страницы макета Ribbit. Я буду ссылаться на элементы HTML с помощью селекторов CSS, чтобы их было легче понять. Но прежде чем углубляться в макет, давайте кратко обсудим вложение.

В CSS ссылка на вложенный элемент может привести к длинным селекторам. Например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
someId {
  /* … */
}
 
someId div.someClass {
  /* … */
}
 
someId div.someClass p.someOtherClass {
  /* … */
}
 
someId div.someClass p.someOtherClass target {
  /* … */
}

И это может стать еще больше! С LESS вы можете вкладывать один элемент в другой, что облегчает чтение:

01
02
03
04
05
06
07
08
09
10
11
12
someId {
  /* … */
    div.someClass {
        /* … */
        p.someOtherClass {
            /* … */
            target {
                /* … */
            }
        }
    }
}

Создайте новый файл и назовите его style.less . При использовании любого препроцессора стиля рекомендуется хранить важные цвета и размеры в переменных; Вы можете легко настроить их значения без поиска в файле, ища значения свойств, которые вам нужно изменить. Мы будем использовать несколько переменных для цвета текста, цвета рамки и ширины содержимого:

1
2
3
@text-color: #3F3E3D;
@border-color: #D2D2D2;
@content-width: 860px;

Теперь давайте создадим два миксина. Первый создаст иллюзию сглаженного текста, а второй позволит использовать кросс-браузерные градиенты. Первый довольно прост:

1
2
3
4
.antialiased (@color) {
    color: @color;
    text-shadow: @color 0 0 1px;
}

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

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

1
2
3
4
5
6
7
8
9
.gradient4f (@p1, @c1, @p2, @c2, @p3, @c3, @p4, @c4) {
    background: @c1;
    background: -moz-linear-gradient(top, @c1 @p1, @c2 @p2, @c3 @p3, @c4 @p4);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(@p1, @c1), color-stop(@p2, @c2), color-stop(@p3, @c3), color-stop(@p4, @c4));
    background: -webkit-linear-gradient(top, @c1 @p1, @c2 @p2, @c3 @p3, @c4 @p4);
    background: -o-linear-gradient(top, @c1 @p1, @c2 @p2, @c3 @p3, @c4 @p4);
    background: -ms-linear-gradient(top, @c1 @p1, @c2 @p2, @c3 @p3, @c4 @p4);
    background: linear-gradient(to bottom, @c1 @p1, @c2 @p2, @c3 @p3, @c4 @p4);
}

У каждого браузера есть префикс: -moz- для Firefox, -webkit- для Chrome и т. Д. В последней строке используется версия W3C, рекомендованная для градиентов. Если браузер поддерживает его, он переопределит предыдущие свойства, потому что это последнее объявление свойства background в правиле. Функция linear-gradient принимает восемь параметров: четыре пары значений цвета в процентах. Это создает градиент с четырьмя шагами цвета.


Давайте теперь стилизуем некоторые глобальные элементы, такие как кнопки и ссылки. Мы хотим, чтобы все элементы использовали шрифты Helvetica или Arial с цветом текста, определенным ранее:

1
2
3
4
* {
    font-family: sans-serif;
    color: @text-color;
}

Тело довольно легко; нам нужен белый фон с рисунком на основе изображения. Там нет полей и отступов:

1
2
3
4
5
body {
    background: white url(gfx/bg.png);
    margin: 0;
    padding: 0;
}

Мы также предоставим стиль по умолчанию для всех элементов <input/> на странице:

01
02
03
04
05
06
07
08
09
10
11
12
input {
    width: 236px;
    height: 38px;
    border: 1px solid @border-color;
    padding: 0 10px;
    outline: none;
    font-size: 17px;
 
    &:focus {
        background: #FFFDF2;
    }
}

Мы устанавливаем размер и отступ по умолчанию и используем переменную @border-color чтобы удалить раздражающий синий контур, когда элемент находится в фокусе. Вы должны заметить еще один кусочек LESS: мы можем добавить псевдоклассы CSS (и обычные классы тоже), используя символ & (родительская ссылка), как показано здесь:

1
2
3
&:focus {
    background: #FFFDF2;
}

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

Кнопки Submit будут использовать как ранее определенный mixin, так и border-radius для создания приятного эффекта:

01
02
03
04
05
06
07
08
09
10
11
input[type=»submit»] {
    height: 36px;
    border: 1px solid #7BC574;
    border-radius: 2px;
    color: white;
    font-size: 12px;
    font-weight: bold;
    padding: 0 20px;
    cursor: pointer;
    .gradient4f(0%, #8CD585, 23%, #82CD7A, 86%, #55AD4C, 100%, #4FA945);
}

Ссылки должны иметь цвет, отличный от обычного текста. Мы также подчеркнем их при наведении:

1
2
3
4
5
6
7
a {
    text-decoration: none;
    .antialiased(#58B84E);
    &:hover {
        text-decoration: underline;
    }
}

Мы начнем с той части макета, которая остается неизменной на каждой странице. Вот HTML-код, который я объясню ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE HTML>
<html>
<head>
    <link rel=»stylesheet/less» href=»style.less»>
    <script src=»less.js»></script>
</head>
<body>
    <header>
        <div class=»wrapper»>
            <img src=»gfx/logo.png»>
            <span>Twitter Clone
 
    </div>
  </header>
  <div id=»content»>
    <div class=»wrapper»>
 
    </div>
  </div>
  <footer>
    <div class=»wrapper»>
      Ribbit — A Twitter Clone Tutorial<img src=»gfx/logo-nettuts.png»>
    </div>
  </footer>
</body>
</html>

Мы начнем с обычного определения типа документа и doctype документа. Вы можете использовать библиотеку less.js и включить style.less на этапе разработки (как я делал в этом коде). Позже вы можете скомпилировать файл LESS в CSS, если вы не хотите использовать less.js Как вы, наверное, уже заметили, макет разделен на три части: header , #content и footer . Вы должны сохранить этот HTML-код, чтобы увидеть, правильно ли вы все оформляете.

Давайте займемся header . Он содержит логотип Ribbit и два слова: «Twitter Clone». Он обернут в оболочку, ширина которой контролируется переменной @content-width . В макете есть несколько оберток, и все они имеют @content-width с auto полем:

1
2
3
4
.wrapper {
    width: @content-width;
    margin: auto;
}

Сам заголовок имеет высоту 85px и ширину страницы:

1
2
3
4
5
header {
  background: url(gfx/bg-header.png);
  height: 85px;
  width: 100%;
}

После ширины добавьте стиль div.wrapper с вертикальным заполнением:

1
2
3
div.wrapper {
    padding: 11px 0;
}

Таким образом, заголовок должен выглядеть так:

1
2
3
4
5
6
7
8
header {
    background: url(gfx/bg-header.png);
    height: 85px;
    width: 100%;
 
    div.wrapper {
        padding: 11px 0;
    }

Изображения в обёртке должны быть на 10px ниже, чтобы быть хорошо отцентрированными:

1
2
3
4
5
img {
    position: relative;
    top: 10px;
    margin: 0 15px 0 0;
}

Кроме того, шрифт в элементах <span/> должен быть больше размера по умолчанию:

1
2
3
4
span {
    font-size: 18px;
    margin: 0 42px 0 0;
}

Вот как должен выглядеть наш дизайн на этом этапе.

Header in basic template.

Сейчас мы мало что можем сделать с #content . Мы добавим немного поля в нижней части и минимальной высоты; макет будет выглядеть прикольным, если он недостаточно высок:

1
2
3
4
#content {
  margin-bottom: 15px;
  min-height: 560px;
}

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

1
2
3
div.wrapper {
    margin: 38px auto;
}

Как и заголовок, нижний колонтитул одинаков для всех страниц. Мы будем использовать фоновое изображение и меньший размер шрифта. Нам также нужно clear: both , потому что мы будем использовать плавающие в контенте. Без clear нижний колонтитул не будет корректироваться в соответствии с содержанием:

1
2
3
4
5
6
footer {
  background: url(gfx/bg-footer.png);
  height: 251px;
  font-size: 14px;
  clear: both;
}

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

1
2
3
4
5
6
7
div.wrapper {
    padding: 15px;
 
    img {
        float: right;
    }
}

Вот наш нижний колонтитул:


Эта страница отображается для пользователей, не вошедших в Ribbit. Следовательно, необходимо будет представить форму входа в систему в заголовке и форму регистрации с большим изображением лягушки в содержании. Начнем с базового шаблона.

Добавьте эту форму входа в div.wrapper header после элемента <span/> :

1
2
3
4
<form>
    <input type=»text»>
    <input type=»password»>
</form>

Эти входные данные уже оформлены, но нам нужно добавить поля и сделать display формы inline . Добавьте это после span в div.wrapper header :

1
2
3
4
5
6
7
form {
    display: inline;
 
    input {
        margin: 0 0 0 14px;
    }
}

Вот HTML-код для формы регистрации:

01
02
03
04
05
06
07
08
09
10
<img src=»gfx/frog.jpg»>
<div class=»panel right»>
    <h1>New to Ribbit?</h1>
    <form>
        <input name=»email» type=»text»>
        <input name=»password» type=»text»>
        <input name=»password2″ type=»password»>
        <input type=»submit» value=»Create Account»>
    </form>
</div>

Добавьте этот HTML в div.wrapper из #content . Мы хотим, чтобы изображение имело закругленные углы и плавало влево (добавьте это после margin в div.wrapper of #content ):

1
2
3
4
img {
    border-radius: 6px;
    float: left;
}

Теперь мы можем оформить регистрационную форму. Это также будет панель, которую мы будем использовать позже; вот почему мы будем .panel :

1
2
3
4
5
6
7
8
div.panel {
    border: 1px solid @border-color;
    background: white;
    margin: 0;
    margin-bottom: 29px;
    border-radius: 6px;
    font-size: 14px;
}

Однако сейчас мы будем стилизовать только right панель. Это уже и прилипает к правой стороне панели. Естественно, вставьте в div.panel следующее:

1
2
3
4
5
&.right {
    width: 303px;
    height: 313px;
    float: right;
}

Также нам нужно позаботиться о заголовке и содержимом панели. Мы используем элементы <h1/> для заголовка и элементы <p/> для содержимого. Обратите внимание, что вы можете использовать подстановочный знак * внутри другого элемента:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
* {
    margin: 6px 0;
}
form {
    padding: 0 23px;
}
h1 {
    border-bottom: 1px solid @border-color;
    margin: 5px 0;
    font-weight: normal;
    font-size: 18px;
    padding: 13px 23px;
    height: 23px;
}
p {
    padding: 0 24px;
    margin: 18px 0;
}

Вот как должен выглядеть стиль div.panel :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
div.panel {
    border: 1px solid @border-color;
    background: white;
    margin: 0;
    margin-bottom: 29px;
    border-radius: 6px;
    font-size: 14px;
 
    &.right {
        width: 303px;
        height: 313px;
        float: right;
    }
     
    * {
    margin: 6px 0;
  }
  h1 {
    border-bottom: 1px solid @border-color;
    margin: 5px 0;
    font-weight: normal;
    font-size: 18px;
    padding: 13px 23px;
    height: 23px;
  }
  p {
    padding: 0 24px;
    margin: 18px 0;
  }
}

И вот скриншот того, как эта страница должна выглядеть до сих пор (нажмите, чтобы увидеть полный размер):

Home page preview


Страница друзей должна отображаться, когда пользователь входит в систему. На ней будет отображаться список последних «Риббитов», а также некоторая статистика вашего аккаунта. Еще раз начнем с базового шаблона. Эта страница, наряду с другими страницами, будет отображать кнопку выхода вместо формы входа в header :

1
2
3
<form>
    <input type=»submit» id=»btnLogOut» value=»Log Out»>
</form>

Кнопки уже стилизованы, поэтому нам нужно только прикрепить их к правой стороне контейнера и добавить несколько полей:

1
2
3
4
#btnLogOut {
  float: right;
  margin: 14px 0 0 0;
}

Поскольку селектор этого правила является идентификатором элемента, вы можете разместить его либо за пределами любого элемента, либо внутри div.wrapper заголовка. Это ваш выбор, но помните, что если вы решите разместить его внутри другого элемента, скомпилированный CSS будет иметь более длинный селектор ( header div.wrapper #btnLogOut ).

Сначала добавьте код этой панели в div.wrapper из #content :

1
2
3
4
5
6
7
8
9
<div id=»createRibbit» class=»panel right»>
    <h1>Create a Ribbit</h1>
    <p>
        <form>
            <textarea name=»text» class=»ribbitText»></textarea>
            <input type=»submit» value=»Ribbit!»>
        </form>
    </p>
</div>

Класс .right был стилизован ранее, но нам нужно добавить некоторые стили для элемента <textarea/> . Мы дадим ему правильный размер и границу:

1
2
3
4
5
textarea.ribbitText {
    width: 249px;
    height: 160px;
    border: 1px solid @border-color;
}

Добавьте это в определение стиля на правой панели.

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

01
02
03
04
05
06
07
08
09
10
11
<div id=»ribbits» class=»panel left»>
    <h1>Your Ribbit Profile</h1>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user1.png»>
        <span class=»name»>Frogger
        <p>
            567 Ribbits<span class=»spacing»>45 Followers
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
</div>

Это может выглядеть сложно, но структура довольно проста, когда вы удаляете содержимое:

01
02
03
04
05
06
07
08
09
10
<div id=»ribbits» class=»panel left»>
  <h1>Your Ribbit Profile</h1>
  <div class=»ribbitWrapper»>
    <img class=»avatar» src=»gfx/user1.png»>
    <span class=»name»>
    <p>
       <span class=»spacing»>
    </p>
  </div>
</div>

Несмотря на это, у нас есть еще одна панель; поэтому сначала нужно его стилизовать:

1
2
3
4
&.left {
    width: @content-width — 327;
    float: left;
}

Вы, вероятно, знаете, где разместить этот код (обратите внимание, как легко вы можете выполнять арифметические операции в LESS). Эта панель содержит div.ribbitWrapper . Итак, добавьте следующий код:

1
2
3
div.ribbitWrapper {
    padding: 15px 0;
}

Внутри этого элемента есть два элемента <span/> , каждый из которых имеет свой цвет и размер шрифта. У них есть классы .name и .time :

01
02
03
04
05
06
07
08
09
10
11
span {
    &.name {
        font-size: 18px;
        color: #58B84E;
    }
 
    &.time {
        font-size: 12px;
        color: #CCC;
    }
}

Мы также должны разместить изображение аватара рядом с левой границей. Добавьте следующий код:

1
2
3
4
img.avatar {
    margin: 0 19px 0 20px;
    float: left;
}

Кроме того, текст Риббита должен быть сглажен, выровнен и перемещен вправо. Этот код будет размещать текст рядом с аватаром, а не под ним:

1
2
3
4
5
6
7
p {
    margin: 5px 50px 0 90px;
    padding: 0;
    text-align: justify;
    line-height: 1.5;
    .antialiased(@text-color);
}

В этом абзаце есть элементы <span/> с вертикальными линиями, визуально разделяющими их. Этот эффект достигается использованием границ, отступов и полей:

1
2
3
4
5
6
span.spacing {
    padding-left: 9px;
    margin-left: 9px;
    height: 10px;
    border-left: 1px solid @border-color;
}

На этой панели перечислены последние кролики от людей, которым следует пользователь. Вставьте следующее после информационной панели пользователя:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<div class=»panel left»>
    <h1>Your Ribbit Buddies</h1>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user2.png»>
        <span class=»name»>Kermit
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user1.png»>
        <span class=»name»>Frogger
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user2.png»>
        <span class=»name»>Kermit
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user3.png»>
        <span class=»name»>Hypnotoad
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user2.png»>
        <span class=»name»>Kermit
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user3.png»>
        <span class=»name»>Hypnotoad
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
</div>

Есть несколько примеров кроликов, чтобы увидеть, как это выглядит. Мы добавим некоторые границы, чтобы визуально отделить их. Добавьте этот код в div.ribbitWrapper :

1
2
3
4
border-bottom: 1px solid @border-color;
&:last-child {
    border: none;
}

Этот стиль добавляет нижнюю границу, одновременно удаляя границу последнего div.ribbitWrapper ; граница уже существует на панели.

Вот как эта страница должна выглядеть сейчас:

Buddies page preview


На странице «Общедоступные ленточки» будут перечислены последние ленточки профилей, не помеченных как частные, чтобы пользователи могли просматривать лопатки тех, кого у них нет в списке друзей. Удивительно, но больше нечего стилизовать, но нам нужно добавить немного HTML. Единственная разница между этой и предыдущей страницами состоит в том, что на этой странице нет информационной панели пользователя, но на конечном сайте будет другое содержимое. Так что не стесняйтесь копировать код страницы друзей, но удалите эту панель:

01
02
03
04
05
06
07
08
09
10
11
<div id=»ribbits» class=»panel left»>
    <h1>Your Ribbit Profile</h1>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user1.png»>
        <span class=»name»>Frogger
        <p>
            567 Ribbits<span class=»spacing»>45 Followers
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
</div>

Также измените заголовок панели на «Public Ribbits». Вот предварительный просмотр этой страницы:


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

В окне поиска будет использоваться панель .right с элементом <input/> внутри:

1
2
3
4
5
6
7
8
9
<div class=»panel right»>
    <h1>Search for profiles</h1>
    <p>
        <form>
            <input name=»query» type=»text»>
            <input type=»submit» value=»Ribbit!»>
        </form>
    </p>
</div>

Вот несколько примеров профилей для списка профилей, чтобы вы могли увидеть, как он выглядит в браузере. На следующем уроке мы, конечно, заменим это соответственно.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id=»ribbits» class=»panel left»>
    <h1>Public Profiles</h1>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user2.png»>
        <span class=»name»>Kermit
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user1.png»>
        <span class=»name»>Frogger
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
    <div class=»ribbitWrapper»>
        <img class=»avatar» src=»gfx/user3.png»>
        <span class=»name»>Hypnotoad
        <p>
            Cras justo odio, dapibus ac facilisis in, egestas Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
        </p>
    </div>
</div>

Эта страница должна выглядеть так:


Ссылка на вложенный элемент может привести к длинным селекторам.

Как я уже отмечал ранее, для производства вы можете скомпилировать LESS в CSS (и я рекомендую вам сделать это из соображений производительности). Есть несколько доступных онлайн-компиляторов:

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

  • Crunch! (это полноценный редактор LESS)
  • WinLess (функция автоматической компиляции при изменении файла)
  • SimpLESS (включает минимизацию CSS)

Если какой-либо из этих компиляторов не работает для вас, Google для больше; Есть много! Вы также можете использовать lessc с сайта LESS, но гораздо проще скомпилировать ваши файлы LESS с другими компиляторами. Конечно, нет ничего плохого в использовании библиотеки less.js для динамической компиляции макета; новые браузеры кэшируют полученный CSS.


Как вы можете видеть, LESS — это мощный инструмент, который делает намного проще и быстрее, чем простой CSS, стилизовать красивые макеты.

Но это только начало. Будьте готовы внедрить серверную часть Ribbit во множество языков и платформ в следующем наборе руководств!