Не стоит недооценивать Jiugongge, один вопрос может раскрыть истинный характер кандидата!

CSS

предисловие

По неполной статистике(На самом деле, я считаю своих друзей и коллег вокруг себя.), после исключения приложений для коротких видео, таких как Douyin или Kuaishou, больше всего времени каждый день тратится на мобильные телефоны, чтобы просматривать Weibo и посещать Moments.

Я часто вижу такие вещи, пролистывая Weibo и посещая круг друзей:

У него высокое имя: Jiugongge. Как следует из названия, Jiugongge обычно представляет собой макет из трех строк и трех столбцов, как показано на рисунке.

Клиент WeChat использует этот макет:

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

И Вейбо:

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

Маржин Цзюгунге

Цзюгунгэ обычно делится на два вида: граничный цзюгунге и граничный цзюгунге.

Margin Jiugongge - это такой круг друзей, что у каждой картинки есть определенный запас:

Это на самом деле проще, потому что не связано с проблемами границ, такими как этот макет с несколькими строками и несколькими столбцами с использованием макета сетки (grid) просто не может быть более подходящим.

Но учитывая, что с сетками вообще никто не знаком, используем макет таблицы, который подходит и для нескольких строк и столбцов.Почему бы не использовать универсальный эластичный блок (flex) сделать это? Поскольку вопрос интервью ниже предназначен дляflexЯ не хочу использовать два одинаковых макета для его реализации, здесь для красоты используется библиотека китайских градиентных цветов:chinese-gradient, посмотрите на код:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 在这里用link标签引入中文渐变色 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chinese-gradient">
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 全屏显示 */
    html, body, ul { height: 100% }

    /* 父元素 */
    ul {
      /* 给个合适的宽度 */
      width: 100%;

      /* 清除默认样式 */
      list-style: none;

      /* 令其用table方式去显示 */
      display: table;
 
      /* 设置间距 */
      border-spacing: 3px
    }

    /* 子元素 */
    li {
      /* 令其用table-row方式去显示 */
      display: table-row
    }

    /* 孙子元素 */
    div {
      /* 令其用table-cell方式去显示 */
      display: table-cell;

      /* 蓝色渐变 */
      background: var(--湖蓝)
    }
  </style>
</head>
<body>
  <ul>
    <li>
      <div></div>
      <div></div>
      <div></div>
    </li>
    <li>
      <div></div>
      <div></div>
      <div></div>
    </li>
    <li>
      <div></div>
      <div></div>
      <div></div>
    </li>
  </ul>
</body>
</html>

результат операции:

Видно, что мы не используем традиционные элементы таблицы, такие как

, ,
в структуре DOM, потому что в этом случае используются только несколько строк и столбцов таблицы. Но на самом деле Jiugongge — это не таблица, поэтому, чтобы соответствовать семантическому стандарту W3C, мы используем другие элементы DOM.

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

  • display: table;эквивалентно изменению поведения элемента на<table></table>
  • display: inline-table;Эквивалентно изменению поведения элемента на версию встроенного элемента.<table></table>
  • display: table-header-group;эквивалентно изменению поведения элемента на<thead></thead>
  • display: table-row-group;эквивалентно изменению поведения элемента на<tbody></tbody>
  • display: table-footer-group;эквивалентно изменению поведения элемента на<tfoot></tfoot>
  • display: table-row;эквивалентно изменению поведения элемента на<tr></tr>
  • display: table-column-group;эквивалентно изменению поведения элемента на<colgroup></colgroup>
  • display: table-column;эквивалентно изменению поведения элемента на<col></col>
  • display: table-cell;эквивалентно изменению поведения элемента на<td></td>или<th></th>
  • display: table-caption;эквивалентно изменению поведения элемента на<caption></caption>

граница девять сетки

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

Итак, давайте рассмотрим этот вопрос:

Требования следующие:

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

Это все еще не кажется чем-то большим, не так ли? Как вы думаете, достаточно ли добавить границу к Jiugongge? Если вы так думаете, то ваша сетка из девяти квадратов будет выглядеть так:

Разве это не отличается от того, что вы себе представляли? Почему это так?

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

Итак, как решить эту проблему?

Решение 1

Не станут ли две соседние границы толще при слиянии? Тогда самый простой и грубый способ - заставить соседнюю сторону одного из двух соседних ящиков не отображать границу, и все! так:

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

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

Решение 2

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

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

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

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

Тетя Соус:

И тетушки:

Таким образом, независимо от того, есть ли у вас 4, 6, 9 или 12 сеток, вам нужно только добавить стиль к дочернему элементу, а затем добавить дополнительный стиль границы к родительскому элементу.

Решение 3

Приведенное выше решение на самом деле нормальное, но оно не самое совершенное, так в чем же с ним проблемы?

  • Прежде всего, хотя его можно повторно использовать с другими сетками, он подходит только для «полных» ситуаций. Например, в кругу друзей самым большим является Jiugongge, верно? Но пользователю не нужно каждый раз присылать все девять фото, может 7 фото, может 5 фото, в этом случае он будет раскрыт (Таким образом, круг друзей использует маргинальную сетку из девяти квадратов вместо пограничной сетки из девяти квадратов.).

  • Во-вторых, это не подходит для этого вопроса интервью, потому что требование этого вопроса интервью состоит в том, что граница становится красной при перемещении мыши, а приведенное выше решение приведет к тому, что граница каждого поля будет неполной, поэтому, когда мышь перемещается, эффект будет следующим:

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

Некоторые вопросы на собеседовании такие: вы не можете думать об этом, когда сильно думаете, но вы можете понять это сразу же, немного подумав!

На самом деле, каждому блоку дается отрицательное поле. Расстояние поля оказывается толщиной границы, так что следующий блок будет «наложен» на границу предыдущего блока. Давайте напишем более толстую полупрозрачную границу. Показывать:

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

Однако некоторые более осторожные друзья могут задаться вопросом: поскольку все прямоугольники были перемещены в верхний левый угол с отрицательными полями, разве сетка из девяти квадратов не оказалась бы в исходном положении? Поэтому нам нужно сделать так, чтобы крайняя левая и самая верхняя строки не имели отрицательных полей.На данный момент нам нужно проверить уровень CSS кандидата, чтобы увидеть, может ли он / она гибко использовать селектор псевдокласса: каждая строка Первая один, как это должно быть написано?

  • :nth-child(1), :nth-child(4), :nth-child(7)?

Это тоже можно сделать, но лучше написать так:

  • :nth-child(3n+1)

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

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

  • :first-child, :nth-child(2), :nth-child(3)

А лучше так:

  • :nth-child(-n+3)

Цифры в каждой сетке должны располагаться по центру, здесь рекомендуется использоватьgrid, потому что Jiugongge можно использоватьflexРеализовать его, но если содержание внутри продолжает реализовываться вместе с ним, то это не будет отражать комплексность вашей технологии, а в аспекте центрированияgridможно сравнить сflexменьше кода, даже если выgridНе интересно, тогда просто запомните это фиксированное использование:

父元素 {
    display: grid;

    /* 令其子元素居中 */
    place-items: center;
}

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

Содержимое внутри решено, давайте использовать универсальный для Jiugongge снаружи.flexДля реализации flex по умолчанию является одномерным макетом, но если он поддерживает только одномерный, он не будет вызываться万能的flexТеперь идея такова, если ширина и высота каждой сетки100 x 100, девять дворцов составляют300 x 300, оберните его каждую третью, чтобы можно было проверить пару кандидатовflexСтепень гибкости использования:

父元素 {
  width: 300px;

  /* 设置为flex布局 */
  display: flex;

  /* 设置换行 */
  flex-flow: wrap;
}

子元素 {
  width: 100px;
  height: 100px;
  
  border: 1px solid black;
}

Выглядит хорошо, не так ли? На самом деле будут переноситься только две сетки в каждой строке, потому что после добавления границы ширина и высота дочерних элементов становятся102 x 102Ну три слова это уже больше чем300, поэтому перенос строк начинается до трех, и в это время проверяется блочная модель-кандидат:

子元素 {
  width: 100px;
  height: 100px;
  
  border: 1px solid black;
  
  /* 设置盒模型 */
  box-sizing: border-box;
}

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

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

:hover {
  /* 红色字体 */
  color: red;

  /* 红色边框 */
  border: 1px solid red;
}

Опять же, этого действительно можно добиться, но если значение, используемое во многих местах, таких как красный цвет, обычно устанавливается как переменная в процессе написания js? Тогда пиши сюдаCSS-переменные? также работает, но есть лучшая переменная, называемаяcurrentColor, это свойство можно понимать как встроенную переменную, как и innerWidth(window.innerWidth), это, естественно, переменная без определения.

а такжеCSS-переменныеРазница в том, что он принимает значение цвета на себя или на родительский элемент, и его совместимость еще лучше, и он может быть совместим до тех пор, покаIE9.

Если вы озадачены: это слово такое длинное, что его удобнее писать прямо красным, то, пожалуйста, не забывайте, что цвет может передаваться по наследству! Если цвет определен во внешнем элементе, все подэлементы внутри могут наследовать его.Если он управляется JS, вам нужно только получить внешний элемент DOM и изменить его цветовой стиль.

currentColorВ качестве переменной его можно использовать во многих свойствах CSS, таких как граница, тень блока, фон, линейный градиент () ... даже заливка и обводка в svg могут использовать эту переменную, она может делать много вещей ,Чтобы не отклоняться от темы здесь,не буду о ней рассказывать.Если интересно,можете поискать.

:hover {
  /* 红色字体 */
  color: red;

  /* 红色边框 */
  border: 1px solid;
}

Модифицированный код такой же, как указано выше, почему бы и нетcurrentColor? Это потому, что если вы его не напишете, по умолчанию будетcurrentColor, это ключевое слово представляет текущее значение цвета.

Большинство кандидатов могут так не писать, но если вы интервьюер, лучше всего подсказать ему как следует и посмотреть, сможет ли он это сказать.currentColorэта переменная илиCSS-переменные

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

父元素.addEventListener('click', e => alert(e.target.innerText))

Вы можете наблюдать, привязывает ли кандидат событие к родительскому элементу или к дочерним элементам один за другим, этот вопрос в основном не является неправильным. Но если вы обнаружите, что кандидаты привязывают события к подэлементам один за другим, вы можете остановиться на этом, и вам не нужно тратить время на задавание других вопросов, вы можете притвориться Б и сказать: ОК, ваша ситуация у меня есть базовое понимание, вернуться и ждать уведомления!

Далее, давайте напишем немного более полный код, чтобы перейти к следующему вопросу:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 全屏显示 */
    html, body { height: 100% }

    body {
      /* 网格布局 */
      display: grid;

      /* 子元素居中 */
      place-items: center;
    }

    /* 父元素 */
    ul {
      width: 300px;
      
      /* 清除默认样式 */
      list-style: none;

      /* 设置为flex布局 */
      display: flex;

      /* 设置换行 */
      flex-flow: wrap;
    }

    /* 子元素 */
    li {
      /* 显示为网格布局 */
      display: grid;

      /* 子元素水平垂直居中 */
      place-items: center;

      /* 宽高都是100像素 */
      width: 100px;
      height: 100px;

      /* 设置盒模型 */
      box-sizing: border-box;

      /* 设置1像素的边框 */
      border: 1px solid black;

      /* 负边距 */
      margin: -1px 0 0 -1px;
    }

    /* 第1、4、7个子元素 */
    li:nth-child(3n+1) {
      /* 取消左负边距 */
      margin-left: 0
    }

    /* 前三个子元素 */
    li:nth-child(-n+3) {
      /* 取消上负边距 */
      margin-top: 0
    }

    /* 当鼠标经过时 */
    li:hover {
      /* 红色字体 */
      color: red;

      /* 红色边框 */
      border: 1px solid;
    }
  </style>
</head>
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
  <script>
    // 选择ul元素
    const ul = document.getElementsByTagName('ul')[0]

    // 监听ul元素的点击事件
    ul.addEventListener('click', e => alert(e.target.innerText))
  </script>
</body>
</html>

результат операции:

Интересно, почему это происходит? Потому что текущий кадр подавляется сеткой позади него! Тогда просто не позволяйте задней части мыши удерживаться, когда мышь проходит мимо (Поднимите уровень).

Когда дело доходит до повышения уровня, первое, что приходит на ум, может бытьz-indexТеперь наиболее часто используемым местом для этого свойства, вероятно, является абсолютное позиционирование и фиксированное позиционирование. Но на самом деле мало кто знаетz-indexиспользуется не только вposition: xxxДа, универсальная эластичная коробка (display:flex) также поддерживаетz-indexиз:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 全屏显示 */
    html, body { height: 100% }

    body {
      /* 网格布局 */
      display: grid;

      /* 子元素居中 */
      place-items: center;
    }

    /* 父元素 */
    ul {
      width: 300px;
      
      /* 清除默认样式 */
      list-style: none;

      /* 设置为flex布局 */
      display: flex;

      /* 设置换行 */
      flex-flow: wrap;
    }

    /* 子元素 */
    li {
      /* 显示为网格布局 */
      display: grid;

      /* 子元素水平垂直居中 */
      place-items: center;

      /* 宽高都是100像素 */
      width: 100px;
      height: 100px;

      /* 设置盒模型 */
      box-sizing: border-box;

      /* 设置1像素的边框 */
      border: 1px solid black;

      /* 负边距 */
      margin: -1px 0 0 -1px;
    }

    /* 第1、4、7个子元素 */
    li:nth-child(3n+1) {
      /* 取消左负边距 */
      margin-left: 0
    }

    /* 前三个子元素 */
    li:nth-child(-n+3) {
      /* 取消上负边距 */
      margin-top: 0
    }

    /* 当鼠标经过时 */
    li:hover {
      /* 红色字体 */
      color: red;

      /* 红色边框 */
      border: 1px solid;

      /* 调高层级 */
      z-index: 1;
    }
  </style>
</head>
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
  <script>
    // 选择ul元素
    const ul = document.getElementsByTagName('ul')[0]

    // 监听ul元素的点击事件
    ul.addEventListener('click', e => alert(e.target.innerText))
  </script>
</body>
</html>

результат операции:

Эпилог

Я не ожидал, что такая, казалось бы, неприметная Цзюгунгэ сможет просматривать столько контента одновременно! Если вы спросите прямо во время интервью:

  • Что вы знаете о флексе?
  • Что происходит, когда элемент имеет отрицательное поле
  • пожалуйста, сделай этоЦентрируется по горизонтали и вертикали
  • Вы слышали о сетке?
  • Расскажите о своем понимании блочной модели.
  • Расскажите о привязке событий и пузырьковом воспроизведении событий.
  • Как использовать селекторы псевдоклассов в CSS3
  • Как контролировать, что находится сверху, а что снизу, когда элементы страницы перекрываются
  • Как использовать переменные в CSS

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

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

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

Если это интервьюер, то также рекомендуется использовать этот вопрос для проверки технического уровня кандидата.Если вы можете сделать это идеально, вам в принципе не нужно задавать другие вопросы по CSS.Стили, используемые в ежедневной разработке в основном ему/ей трудно перейти непосредственно к вопросам JS-интервью.

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

Эта статья была впервые опубликована в前端学不动Нет публики

Замечательные статьи в прошлом