preface

According to incomplete statistics (actually counting friends and colleagues), after excluding short video apps such as Douyin or Kuaishou, the most time spent on a phone every day is scrolling through Weibo and Wechat moments.

When checking Weibo and Wechat moments, you often see something like this:

It has a lofty name: the nine grid. As the name suggests, the grid is usually three rows and three columns.

Wechat client uses this layout:

The most familiar circle of friends also adopted the nine-sign pattern:

And weibo:

It is very widely used on mobile, and not only on mobile, it is even used in some interview questions, because it is a good way to test candidates’ CSS skills.

The margin is nine grids

Sudoku is usually divided into two types, one is the margin sudoku, the other is the border sudoku.

Margin grid is the type of circle of friends where each picture has a certain margin:

This is actually simpler because there are no borders involved, and a grid layout with rows and columns like this is perfect.

But given the fact that you’re not familiar with grids, why not use the all-purpose Flex box instead of a table layout that is also suitable for several rows and columns? The following interview question is implemented in Flex, so we don’t want to use two identical layouts. For the sake of appearance, we use a chinese-gradient library:

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <! -- Use link tag to introduce Chinese gradient -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chinese-gradient">
  <style>
    /* Clear the default style */
    * { padding: 0; margin: 0; }

    /* Full screen display */
    html.body.ul { height: 100% }

    /* Parent element */
    ul {
      /* Give a suitable width */
      width: 100%;

      /* Clear the default style */
      list-style: none;

      /* To display */ as a table
      display: table;
 
      /* Set spacing */
      border-spacing: 3px
    }

    /* Child element */
    li {
      /* Display */ in table-row mode
      display: table-row
    }

    /* Sun Tzu element */
    div {
      /* Display */ in table-cell mode
      display: table-cell;

      /* Blue gradient */
      background: var(-- Lake blue)}</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>
Copy the code

Running result:

As you can see, we are not using traditional table elements such as <table>, <tr>, and <td> in the DOM structure, because in this case we are only using a few rows and columns of the table. But the grid is not actually a table, so in order to comply with W3C’s semantic standards, we use other DOM elements.

In cases where it is appropriate to use a table layout but not a table, you can use the display property to mimic the behavior of a table:

  • display: table;It’s going to change the behavior of the element to<table></table>
  • display: inline-table;This is equivalent to changing the behavior of the element to the inline element version<table></table>
  • display: table-header-group;It’s going to change the behavior of the element to<thead></thead>
  • display: table-row-group;It’s going to change the behavior of the element to<tbody></tbody>
  • display: table-footer-group;It’s going to change the behavior of the element to<tfoot></tfoot>
  • display: table-row;It’s going to change the behavior of the element to<tr></tr>
  • display: table-column-group;It’s going to change the behavior of the element to<colgroup></colgroup>
  • display: table-column;It’s going to change the behavior of the element to<col></col>
  • display: table-cell;It’s going to change the behavior of the element to<td></td>or<th></th>
  • display: table-caption;It’s going to change the behavior of the element to<caption></caption>

Frame nine

You may look at the previous content and think: this? It’s so simple and you want to show your true colors?

So let’s look at this:

Requirements are as follows:

  • The numbers in each cell of the frame should be centered
  • The border and numbers will turn red when the mouse is over
  • Clicking on the grid will bring up the corresponding number

Still doesn’t seem like a big deal, does it? Do you think it is just to add a border to the nine grid? If that’s what you think, then your sign will look like this:

Isn’t that what I thought it would be? Why is that?

Because each box looks normal with margins, but when you merge them together the two adjacent borders fit together, and to the naked eye it looks like a double border:

So how to solve this problem?

Method 1

Aren’t two adjacent borders thicker when combined? So the simplest way is to make two adjacent boxes one of the adjacent side of the border does not show the border. Like this:

There’s absolutely nothing wrong with doing that. But this is a stupid method, if changed to four, six, twelve, then have to think about how to achieve, and write the code is more redundant, almost every box to define a different style.

If you go to an interview and do this, the interviewer won’t give you a full mark or even a passing grade. But after all, it is realized, better than those who did not realize the point, will not give zero points.

Method 2

The above implementation requires a different set of patterns for each box, and it is not suitable for other cases such as hexagonal and twelve-dimensional grids, because the code is redundant and is not reusable.

So how can you use only one pattern per box, and also apply to other grids? Here’s an idea:

But on closer inspection, it doesn’t stand up to scrutiny: the right and bottom border of the entire nine palace is gone! We just need to add the right and bottom borders to the parent element:

And it doesn’t have to be in this direction. Other directions can also be realized, such as Aunt Jiang’s:

Soy aunt son:

There is sauce aunt son:

It doesn’t matter if you have a 4, 6, 9, or 12 grid, you simply add a style to the child element and then add a complementary border style to the parent element.

Solution 3

The above solution works, but it’s not perfect, so what are the problems with it?

  • First of all, although it can be reused in other cases, they are only suitable for full cases. For example, like the circle of friends, the biggest is the nine grid, right? But instead of sending nine photos all the time, users can send seven, or maybe five, and they’ll give away their information (hence the use of margin frames instead of border frames).

  • Second, it is not suitable for the interview question, because the interview question requires the border to turn red when the mouse moves in, and the above solution will cause the border of each box to be incomplete, so when the mouse moves in, the effect will look like this:

So what’s the perfect way to solve this problem? First of all, the frame of each box can’t be given any less weight, but that would bring us back to the original question:

Some interview questions are just like that, you can’t come up with them when you’re thinking about them, but with a little thought, you can quickly understand them!

Each box is given a negative margin, which happens to be the same as the width of the border, so that the back box “stacks” on top of the front box. Let’s write a thicker translucent border to show this:

The ones in the middle that get darker are the borders that are stacked together, and because they’re translucent, they get darker when they’re stacked together.

However, some careful friends may wonder: since all the boxes are moved to the top left corner with negative margins, will the nine squares not be in the original position? Yes! So we need to keep the leftmost row and the top row free of negative margins. We need to check the candidate’s CSS level to see if he or she can use pseudo class selectors: what should be written on the first line of each line?

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

You can do that too, but a better way is to write it like this:

  • :nth-child(3n+1)

The top row of negative margins can be left alone, because if the grid moves even a pixel or two to the left, it will not align with the layout on the page, and if it moves a pixel or two up, no one will see it.

But if you were to write it, most people would think something like this:

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

And a better way to do it is this:

  • :nth-child(-n+3)

The number in each grid should be centered. Grid is recommended here because the grid can be implemented in Flex, but the contents of the grid can be implemented in flex, and the grid can be less centered than Flex code, even if you are not interested in grid. Just remember this idiom:

The parent element {display: grid;

    /* Center its children */
    place-items: center;
}
Copy the code

Click here to see more ways to implement a centered layout

Flex default is one dimensional layout, but if only one dimensional support will not be called the universal Flex, the idea is this, if each lattice width and height is 100 x 100, nine lattice is 300 x 300, every three let it line, This will give you an idea of how flexible a candidate is with Flex:

The parent element {width: 300px;

  /* Set to flex layout */
  display: flex;

  /* Set line feed */
  flex-flow: wrap; } child element {width: 100px;
  height: 100px;
  
  border: 1px solid black;
}
Copy the code

Looks fine, doesn’t it? In fact, only two boxes per line will be newline, because the width and height of the child elements will be 102 x 102, and the width and height of the child elements will be over 300 with three boxes.

Child elements {width: 100px;
  height: 100px;
  
  border: 1px solid black;
  
  /* Set the box model */
  box-sizing: border-box;
}
Copy the code

This way, even with the border added, the width and height will still be 100, just enough to cover 3 lines, imagine if you were the interviewer, directly asking if the box model looks low, but this one little nine squares will immediately tell how good the candidate is.

Then the next is when the mouse moves in the border and the contents inside the red, this has what difficult, is not:

:hover {
  /* Red font */
  color: red;

  /* Red border */
  border: 1px solid red;
}
Copy the code

Again, that’s true, but if you’re writing javascript and you’re using a value like red in multiple places, don’t you always set it to a variable? So I’m going to put a CSS variable here, right? That’s fine, but there’s a better variable called currentColor. This property can be thought of as a built-in variable, just like innerWidth(window.innerWidth) in js.

Unlike CSS variables, it takes the color value on itself or on its parent element, and it is more compatible all the way up to IE9.

If you’re wondering how much easier it is to write “red” as a long word, remember that color is inherited! If you define a color in an outer element, all the children in the element can be inherited. To control javascript, you just need to get the outer DOM element and change its color style.

CurrentColor is a variable that can be used for border, box-shadow, background, linear-gradient() and many other CSS properties… Even fill and stroke in SVG can be used with this variable, and there’s a lot of things it can do, but I’m not going to go into it here, so if you’re interested, look it up.

:hover {
  /* Red font */
  color: red;

  /* Red border */
  border: 1px solid;
}
Copy the code

The modified code is as above, why is there no currentColor? That’s because if you don’t, the default is currentColor, and this keyword represents your currentColor.

Most candidates probably won’t write this, but if you’re the interviewer you might want to give him a hint and see if he can say currentColor or CSS

Then click on the corresponding number for each grid. This looks at the event bubble and the event agent:

The parent element. The addEventListener ('click'.e= > alert(e.target.innerText))
Copy the code

You can look at whether the candidate binds the event to the parent element or one by one to the child elements, which is almost always the right question. But if you find that the candidates one by one to bind the event on the child elements, that can stop, also do not waste time to ask other questions, you can ten points loaded B to say: OK, I have a basic understanding of your situation, go back to wait for notification!

Let’s write a little more complete code to bring up the next question:

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <style>
    /* Clear the default style */
    * { padding: 0; margin: 0; }

    /* Full screen display */
    html.body { height: 100% }

    body {
      /* Grid layout */
      display: grid;

      /* The child element is centered */
      place-items: center;
    }

    /* Parent element */
    ul {
      width: 300px;
      
      /* Clear the default style */
      list-style: none;

      /* Set to flex layout */
      display: flex;

      /* Set line feed */
      flex-flow: wrap;
    }

    /* Child element */
    li {
      /* Display as grid layout */
      display: grid;

      /* Child elements are horizontally and vertically centered */
      place-items: center;

      /* Both width and height are 100 pixels */
      width: 100px;
      height: 100px;

      /* Set the box model */
      box-sizing: border-box;

      /* Set a border of 1 pixel */
      border: 1px solid black;

      /* Negative margin */
      margin: -1px 0 0 -1px;
    }

    /* The first, fourth, and seventh child elements */
    li:nth-child(3n+1) {
      /* Cancel the left negative margin */
      margin-left: 0
    }

    /* The first three children */
    li:nth-child(-n+3) {
      /* Cancel the upper negative margin */
      margin-top: 0
    }

    /* When the mouse is over */
    li:hover {
      /* Red font */
      color: red;

      /* Red border */
      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>
    // Select the ul element
    const ul = document.getElementsByTagName('ul') [0]

    // Listen for ul element click events
    ul.addEventListener('click'.e= > alert(e.target.innerText))
  </script>
</body>
</html>
Copy the code

Running result:

Want to know why? Because the current frame is behind the grid pressure! So only when the mouse over do not let the back of the pressure on the good (adjust high level).

When it comes to the upper level, the first thing you might think of is z-index. The most common use of this attribute may be absolute positioning and fixed positioning. The display:flex box supports z-index as well as position: XXX.

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <style>
    /* Clear the default style */
    * { padding: 0; margin: 0; }

    /* Full screen display */
    html.body { height: 100% }

    body {
      /* Grid layout */
      display: grid;

      /* The child element is centered */
      place-items: center;
    }

    /* Parent element */
    ul {
      width: 300px;
      
      /* Clear the default style */
      list-style: none;

      /* Set to flex layout */
      display: flex;

      /* Set line feed */
      flex-flow: wrap;
    }

    /* Child element */
    li {
      /* Display as grid layout */
      display: grid;

      /* Child elements are horizontally and vertically centered */
      place-items: center;

      /* Both width and height are 100 pixels */
      width: 100px;
      height: 100px;

      /* Set the box model */
      box-sizing: border-box;

      /* Set a border of 1 pixel */
      border: 1px solid black;

      /* Negative margin */
      margin: -1px 0 0 -1px;
    }

    /* The first, fourth, and seventh child elements */
    li:nth-child(3n+1) {
      /* Cancel the left negative margin */
      margin-left: 0
    }

    /* The first three children */
    li:nth-child(-n+3) {
      /* Cancel the upper negative margin */
      margin-top: 0
    }

    /* When the mouse is over */
    li:hover {
      /* Red font */
      color: red;

      /* Red border */
      border: 1px solid;

      /* Adjust high level */
      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>
    // Select the ul element
    const ul = document.getElementsByTagName('ul') [0]

    // Listen for ul element click events
    ul.addEventListener('click'.e= > alert(e.target.innerText))
  </script>
</body>
</html>
Copy the code

Running result:

conclusion

Did not think of such a seemingly insignificant nine lattice can suddenly investigate so much content! If you ask in the interview:

  • What do you know about Flex
  • How does an element behave when its margin is negative
  • Please implement horizontal vertical center
  • Have you read about grid
  • Talk about your understanding of the box model
  • Talk about event binding and event bubbling
  • How about CSS3’s pseudo-class selector
  • How do I control which is up and which is down when page elements overlap
  • How do you use variables in CSS

It’s a waste of breath, it’s low key, and it doesn’t screen out candidates who can really use technology.

Because these questions are not difficult, can answer to come out commonly, but specific can be used flexibly not necessarily, and this 9 palace lattice, be like one side shine on a demon mirror, instant lets a person true form reveal!

If you’re a candidate, practice on this one.

If it is the interviewer, then also recommend you to use this question to check the technical level of the candidate, if it is very perfect to make, then basically don’t need to ask other CSS questions, the style used in daily development is not difficult to him/her, can directly on the JS interview questions.

But if you don’t do it does not necessarily mean that the level of the person, you can try to hint the candidate, and then ask other CSS questions to determine the level of the person.

The article was first published on the front end of the public number

Previous excellent article

  • Microsoft launches comments section on GitHub
  • Vue 3.0.3: New CSS variable passing and the latest Ref Proposal
  • You Yuxi: Ref Grammar Sugar Proposal
  • “Double 11 small black box is cool? Let’s use CSS variables to improve!”
  • “Mobile Layout Interview Questions to test your CSS Skills (Center)”
  • A series of confusing behaviors after setting prototype Objects as Proxies
  • Vue’s Super Fun New Feature: DOM Portal
  • A fun new feature of Vue: Introducing JS variables into CSS
  • Create your own Visual Data Map without any libraries
  • “Use of React’s Super-popular CSS-in-JS Library in the Vue Project: Styled – Components”
  • Is It Finally Vue’s Turn to Inspire React?
  • A Small Pit in Vue3 on IOS
  • Upgrade your React project to Immer instead of Immutable by 2020
  • “Soul Interrogation from the Author of React Hooks and Immutable”
  • Good news, Vue3 official document is available in Chinese!
  • Hooks use of the New VUe-Router
  • Vue 3:20 Years of Status Updates
  • React 17 is officially a transition version!
  • Yu Yuxi: The Design Process of Vue3
  • The Father of Node’s refactoring Deno is finally released. Will it Replace Node after all?
  • The Vue3 beta was released early this morning and openly supports scaffolding!