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>
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.
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.
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>
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:
.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>
Spec reference: https://www.w3.org/TR/css3-grid-layout/#gutters
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With