Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing margin from flex items when they wrap

Tags:

html

css

flexbox

Following is my code which is working fine, except the last line in a container which is adding margin-bottom: 5px; from .tag css class.

Problem I am facing is the tag list is dynamic so I cannot directly target the Item-13,14 and so on and so forth.

Let me know in flex do we have any privilege to add custom css w.r.t the last row in my flex container.

* {     margin: 0;     padding: 0; }  html, body {     box-sizing: border-box; }  .container {     width: 600px;     margin: 0 auto;     margin-top: 25px;     border: 1px solid;     padding: 5px; }  .tags {     list-style-type: none;     display: flex;     flex-direction: row;     flex-wrap: wrap;     justify-content: flex-start; }  .tag {     padding: 5px;     background-color: #76FF03;     margin: 0 5px 5px; }
<div class="container">   <ul class="tags">     <li class="tag item-1">Tag Item 1</li>     <li class="tag item-2">Tag Item 2</li>     <li class="tag item-3">Tag Item 3</li>     <li class="tag item-4">Tag Item 4</li>     <li class="tag item-5">Tag Item 5</li>     <li class="tag item-6">Tag Item 6</li>     <li class="tag item-7">Tag Item 7</li>     <li class="tag item-8">Tag Item 8</li>     <li class="tag item-9">Tag Item 9</li>     <li class="tag item-10">Tag Item 10</li>     <li class="tag item-11">Tag Item 11</li>     <li class="tag item-12">Tag Item 12</li>     <li class="tag item-13">Tag Item 13</li>     <li class="tag item-14">Tag Item 14</li>     <li class="tag item-15">Tag Item 15</li>     <li class="tag item-16">Tag Item 16</li>   </ul> </div>
like image 265
Nesh Avatar asked Oct 16 '17 08:10

Nesh


People also ask

How do you remove margins from flex-wrap?

So what you would do is use grid-gap for spacing between the items. Then use padding for the same spacing between the items and the container. The last row margin problem is eliminated.

Can you use margin with Flex?

If you apply auto margins to a flex item, that item will automatically extend its specified margin to occupy the extra space in the flex container, depending on the direction in which the auto-margin is applied.


2 Answers

Update in late 2021

Now the gap property also works with Flexbox (on newer browser versions).

* {   margin: 0;   padding: 0; }  html, body {   box-sizing: border-box; }  .container {   width: 600px;   margin: 0 auto;   margin-top: 25px;   border: 1px solid;   padding: 5px; }  .tags {   list-style-type: none;   display: flex;   flex-direction: row;   flex-wrap: wrap;   justify-content: flex-start;   gap: 5px;                          /* added */ }  .tag {   padding: 5px;   background-color: #76FF03;   /* margin: 0 5px 5px;                 removed */ }
<div class="container">   <ul class="tags">     <li class="tag item-1">Tag Item 1</li>     <li class="tag item-2">Tag Item 2</li>     <li class="tag item-3">Tag Item 3</li>     <li class="tag item-4">Tag Item 4</li>     <li class="tag item-5">Tag Item 5</li>     <li class="tag item-6">Tag Item 6</li>     <li class="tag item-7">Tag Item 7</li>     <li class="tag item-8">Tag Item 8</li>     <li class="tag item-9">Tag Item 9</li>     <li class="tag item-10">Tag Item 10</li>     <li class="tag item-11">Tag Item 11</li>     <li class="tag item-12">Tag Item 12</li>     <li class="tag item-13">Tag Item 13</li>     <li class="tag item-14">Tag Item 14</li>     <li class="tag item-15">Tag Item 15</li>     <li class="tag item-16">Tag Item 16</li>   </ul> </div>

Older versions


The most common way, which most framework use to solve that, is to set a top margin on the items (tag) instead, and then compensate that with a negative margin on the items parent (tags)

* {   margin: 0;   padding: 0; }  html, body {   box-sizing: border-box; }  .container {   width: 600px;   margin: 0 auto;   margin-top: 25px;   border: 1px solid;   padding: 5px; }  .tags {   list-style-type: none;   display: flex;   flex-direction: row;   flex-wrap: wrap;   justify-content: flex-start;   margin-top: -5px;                 /*  compensate top  */ }  .tag {   padding: 5px;   background-color: #76FF03;   margin: 5px 5px 0 0;              /*  top, right  */ }
<div class="container">   <ul class="tags">     <li class="tag item-1">Tag Item 1</li>     <li class="tag item-2">Tag Item 2</li>     <li class="tag item-3">Tag Item 3</li>     <li class="tag item-4">Tag Item 4</li>     <li class="tag item-5">Tag Item 5</li>     <li class="tag item-6">Tag Item 6</li>     <li class="tag item-7">Tag Item 7</li>     <li class="tag item-8">Tag Item 8</li>     <li class="tag item-9">Tag Item 9</li>     <li class="tag item-10">Tag Item 10</li>     <li class="tag item-11">Tag Item 11</li>     <li class="tag item-12">Tag Item 12</li>     <li class="tag item-13">Tag Item 13</li>     <li class="tag item-14">Tag Item 14</li>     <li class="tag item-15">Tag Item 15</li>     <li class="tag item-16">Tag Item 16</li>   </ul> </div>

And an even better way might be to give the same margin to all item's sides, though half the value.

* {   margin: 0;   padding: 0; }  html, body {   box-sizing: border-box; }  .container {   width: 600px;   margin: 0 auto;   margin-top: 25px;   border: 1px solid;   padding: 5px; }  .tags {   list-style-type: none;   display: flex;   flex-direction: row;   flex-wrap: wrap;   justify-content: flex-start; }  .tag {   padding: 5px;   background-color: #76FF03;   margin: 2.5px; }
<div class="container">   <ul class="tags">     <li class="tag item-1">Tag Item 1</li>     <li class="tag item-2">Tag Item 2</li>     <li class="tag item-3">Tag Item 3</li>     <li class="tag item-4">Tag Item 4</li>     <li class="tag item-5">Tag Item 5</li>     <li class="tag item-6">Tag Item 6</li>     <li class="tag item-7">Tag Item 7</li>     <li class="tag item-8">Tag Item 8</li>     <li class="tag item-9">Tag Item 9</li>     <li class="tag item-10">Tag Item 10</li>     <li class="tag item-11">Tag Item 11</li>     <li class="tag item-12">Tag Item 12</li>     <li class="tag item-13">Tag Item 13</li>     <li class="tag item-14">Tag Item 14</li>     <li class="tag item-15">Tag Item 15</li>     <li class="tag item-16">Tag Item 16</li>   </ul> </div>
like image 51
Asons Avatar answered Oct 11 '22 11:10

Asons


As mentioned in another answer, the common way to solve this problem, which is used by many frameworks, is to apply negative margin and padding combinations. Even flexbox provides no clean solution. Ugly hacks are the norm in this situation.

However, if you're open to another CSS3 technology – Grid Layout – the solution is simple, clean and easy.

CSS Grid provides the grid-column-gap and grid-row-gap properties. The shorthand for both is grid-gap. These properties allow you to create space between grid items. But they never apply to the space between items and the container. Again, they only work between items (i.e., the gutters).

So what you would do is use grid-gap for spacing between the items. Then use padding for the same spacing between the items and the container.

Here are just a few benefits to this method:

  • The last row margin problem is eliminated. The number of items is no longer a concern.
  • No need for hacks.
  • No need for margins.
  • Your items align in columns (if that's something you want).
  • All free space in the container is distributed evenly among items (if that's something you want).

.container {    width: 600px;    margin: 0 auto;    margin-top: 25px;    border: 1px solid;    padding: 5px;  }    .tags {    display: grid;    grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));    grid-gap: 5px;    list-style-type: none;  }    .tag {    padding: 5px;    background-color: #76FF03;  }    * {    margin: 0;    padding: 0;    box-sizing: border-box;  }
<div class="container">    <ul class="tags">      <li class="tag item-1">Tag Item 1</li>      <li class="tag item-2">Tag Item 2</li>      <li class="tag item-3">Tag Item 3</li>      <li class="tag item-4">Tag Item 4</li>      <li class="tag item-5">Tag Item 5</li>      <li class="tag item-6">Tag Item 6</li>      <li class="tag item-7">Tag Item 7</li>      <li class="tag item-8">Tag Item 8</li>      <li class="tag item-9">Tag Item 9</li>      <li class="tag item-10">Tag Item 10</li>      <li class="tag item-11">Tag Item 11</li>      <li class="tag item-12">Tag Item 12</li>      <li class="tag item-13">Tag Item 13</li>      <li class="tag item-14">Tag Item 14</li>      <li class="tag item-15">Tag Item 15</li>      <li class="tag item-16">Tag Item 16</li>    </ul>  </div>

jsFiddle demo

Spec reference: https://www.w3.org/TR/css3-grid-layout/#gutters

like image 39
Michael Benjamin Avatar answered Oct 11 '22 11:10

Michael Benjamin