Comparing and contrasting: Grid, Margin, Flex, Float

Whoops well caught I’ll change it now :blush:

1 Like

@PaulOB

What I mean is, isn’t it better:

To have display:none; on .nav, rather than 'a'

Or do you not agree with this?

And if you don’t agree, why not?

.nav is containing the ‘a’, so wouldn’t it be better to have display:none; on .nav instead?

This:

.wrapd.inactive .nav {
  display: none;
}

Instead of:

.wrapd.inactive  a {
  display: none;
}


.wrapd {
  position: relative;
  width: 266px;
  height: 174px;
  margin-top: 8px;
  overflow: hidden;
}


  <div class="nav">
    <a href="" target="_blank" title=""></a>
 <a href="" target="_blank" title=""></a>
 <a href="" target="_blank" title=""></a>
   </div>

@PaulOB

When referring to the magic number nightmare, you mean this, right?

margin: -50px 0 0

Because it has a negative number, and that’s not good, right?

This explains magic numbers: https://css-tricks.com/magic-numbers-in-css/

2 Likes

Assuming that .nav has no functional impact on the layout then yes it would be better to get rid of the whole block.

On its own that wouldn’t be too bad but you also have various left margins on each element with specific amounts. Imagine how much work that would be too change if you changed the size of the element. It’s an unworkable practice that works only for one use case because it relies on magic numbers.

2 Likes

I thought only negative numbers are considered magic numbers?

.wrapb .nav a.x1 {
  margin: 0;
}

.wrapb .nav a.x2 {
  margin-left: 54px;
}

.wrapb .nav a.x3 {
  margin-left: 108px;
}

.wrapb .nav a.x4 {
  margin-left: 162px;
}

.wrapb .nav a.x5 {
  margin-left: 216px;
}

Wait a second, by itself the -50 is not too bad, but it would be a pain if I had to change the size of the whole element, that’s what you mean.

Thank you for showing me this example.

Now I see why hidden is needed, and how to test it.

No any number that relies on something else to be consistent is basically a magic number. If you change one then you have to change everything else that relies on it.

Read the link we have posted (see gandalf’s post above) as it is clearly explained. I have posted that same link numerous times in your threads so there is no excuse not to know what we mean by magic numbers.

5 Likes

So all of those numbers from post #9 are magic numbers, those being 54px, 108px, 162px, and 216px.

In that link above the anchors are all set to display:block; which by default stacks blocks one below another, A perfectly normal layout method for web pages.

But in a situation where you want your elements to be inline with each other, then you reach for a tool that puts you in that direction off the bat.

float: left or right;
display: inline-block;
flex-direction: row;

Then you won’t need classes on every anchor to manipulate it out of it’s normal flow like you’ve done with all those margins from post #9. That is not too much different than using position:relative to move boxes around, they only move visually while they retain their original place. Things get out of hand real quick and each manipulated position is dependent on the other.

That layout is held together by this one rule margin: -50px 0 0;

.wrapb .nav a {
  display: block;
  width: 50px;
  height: 50px;
 /* margin: -50px 0 0; */
  background: rgba(0, 0, 0, 0.2);
  border: 3px solid #0059dd;
  box-sizing: border-box;
}

With that rule removed or altered you get this…

If you ever needed to change the dimensions on the main container you would have a lot of unnecessary work to do.

1 Like

What do I do next?

  float: left;
  display: inline-block;
  flex-direction: row;

That all depends on what you are wanting to achieve? Is it grid, flex, margin, or float?

I just realized display:block; isn’t needed on flex.

.wrapc .nav a {
  /*display: block;*/
  width: 50px;
  height: 50px;
  background: rgba(0, 0, 0, .2);
  border: 3px solid #0059dd;
  box-sizing: border-box;
}

This isn’t working:

.wrapb .nav div {
  margin: 0 0 12px 0;
}

.wrapb .nav a {
  display: inline-block;
  flex-direction: row;
  width: 50px;
  height: 50px;
  margin: 0 0 2px 0;

Personally, I would go with something that required less work on your end.
Let the display model do the heavy lifting and positioning for you.

display:table; might work out for you.

Just a quick example of it’s automatic layout model.
Of course you would need to tailor it to your needs.

The entire layout is controlled by the anchor dimensions :slight_smile:
EDIT: 3px border on each anchor butted together = 6px

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test Page</title>
<style>
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
.wrap {
   display:table; /*shrink to fit without width*/
   margin:0 auto;
   border:3px solid red;
   position:relative;
}
.wrap div {
   display:table-row;
}
.wrap a {
   display:table-cell;
   width:50px;
   height:50px;
   border:3px solid blue;
   background:lime;
}
   .wrap::after,
   .wrap::before {
       content: "";
       position:absolute;
       width:3px;
       height:100%;
       top:0; left:calc(33.3% - 1px);
       background:red;
   }
   .wrap::before {
      left:auto;
      right:calc(33.3% - 1px);
   }
</style>

</head>
<body>

<div class="wrap">
   <div>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
   </div>
   <div>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
   </div>
   <div>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
   </div>
</div>

</body>
</html>

What am I doing wrong?

It’s not working.

.wrapb {
  display: table;
  position: relative;
  width: 266px;
  height: 174px;
  margin-top: 8px;
  background: red;
}

.wrapb div {
   display:table-row;
}

.wrapb .nav a {
  display: table-cell;
  width: 50px;
  height: 50px;
  margin:3px;
  background: rgba(0, 0, 0, 0.2);
  border: 3px solid #0059dd;
  box-sizing: border-box;
}

1 Like

I’m not sure what is wrong above, haven’t looked.

Appears to be something stretching one of the table-cells and the others are following along. That is how tables work.

You probably won’t get a pixel perfect replication of your other methods.

CSS tables follow a different set of rules. For one margins don’t apply to table cells. You would need to use border-spacing instead. Along with border-collapse: separate;

In my other post I said it ‘might work out for you’
But then again it might not. You have to accept it’s layout rules.

2 Likes

To help with the flex design, I commented out all of the existing nav styles. I also added a number to each link, to help me see what’s going on.

Using flex, and with a div for each row of links, we want the nav section to take up the full height of the available area, and we want the divs to auto size so that they take up an equal amount of space:

.wrapc .nav {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.wrapc .nav>div {
  flex: 1;
  border: 1px solid red;
}

The flex of 1 is shorthand for grow:1, shrink:1 and basis:auto. It is recommended that the short version be used, as it sets the other values intelligently.

  /*flex: 1 1 auto;*/
  flex: 1;

Removing the button numbers for simplicity, I can set justify-content on the container to be space-between and reduce the flex to 0.3, so that each div is 30% of the total height, the remaining space will be added between each div.

.wrapc .nav {
  ...
  justify-content: space-between;
}
.wrapc .nav>div {
  ...
  flex: 0.3;
}

With that red border removed, we now want each div to be a flex row with space-between too, and for each button to have a border:

.wrapc .nav>div {
  ...
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
.wrapc .nav a {
  flex: 1;
  border: 3px solid #0059dd;
}

Because each button is 20% of the total width, a flex of slightly less than that gives a good spacing between each button:

.wrapc .nav a {
  flex: 0.18;
  ...
}

Here’s the jsfiddle for this flex version of the nav: https://jsfiddle.net/m9wexxny/189/

3 Likes

This doesn’t work either:

border-spacing: 3px;


.wrapb div {
   display:table-row;
}

.wrapb .nav a {
  display: table-cell;
  width: 50px;
  height: 50px;
  border-spacing: 3px;
  background: rgba(0, 0, 0, 0.2);
  border: 3px solid #0059dd;
  box-sizing: border-box;
}

You’ll have to learn how CSS tables work. Like I said above it follows it own set of rules and they are not the same as other css methods.

The border-spacing CSS property specifies the distance between the borders of adjacent

cells. This property applies only when border-collapse is separate.

Both properties go on the parent

.wrap {
   display:table; /*shrink to fit without width*/
   margin:0 auto;
   border:3px solid red;
   position:relative;
   border-collapse: separate;
   border-spacing: 4px;
   padding: 0;
}

But you can’t collapse the spacing on the inner edges of the parent.