One hacky idea is to add a new line using pseudo element and make the element inline
so that the line-break will affect the inline-block
elements. The drawback is that you will not be able to style an inline
element like you do with an inline-block
one
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
}
.block-start {
display: inline;
padding: 3px;
white-space: pre-wrap;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "\A";
}
/* to rectify the position of the first one*/
.block-start:first-child {
padding-left: 0;
}
<div class="container">
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
To keep the styling (the border in this case) we can consider more hacks:
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
}
.block-start {
display: inline;
padding: 3px 3px 4px;
white-space: pre-wrap;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "\A";
}
/* to rectify the position of the first one*/
.block-start:first-child {
padding-left: 0;
border:1px solid red;
}
.block-start:not(:first-child) {
border:1px solid transparent;
border-right-color:red; /*the right is not an issue*/
background:
linear-gradient(red,red) top right / calc(100% - 3px) 1px,
linear-gradient(red,red) bottom right / calc(100% - 3px) 1px,
linear-gradient(red,red) left 4px top 0 / 1px 100%;
background-repeat:no-repeat;
background-origin:border-box;
padding-right:4px;
}
<div class="container">
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
As we can see, the padding-left
is the issue here since it's applied to the pseudo element creating the line break. One idea to fix this is to consider box-decoration-break
but we will have a small drawback at the end of each line:
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
}
.block-start {
display: inline;
padding: 3px 3px 4px;
white-space: pre-wrap;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
border:1px solid red;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "\A";
}
<div class="container">
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
We can still fix this by adding some negative margin in order to hide it behind the other elements (we should also add background color)
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
background:#fff;
position:relative;
}
.block-start {
display: inline;
padding: 3px 3px 4px;
white-space: pre-wrap;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
border:1px solid red;
margin-left:-15px;
}
.container {
padding-left:15px;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "\A";
}
<div class="container">
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start">block-start</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
We can also consider the other pseudo element and data-attribute to have more control over the styling wihout any hacks. This is the solution I recommend
I have used the class
attribute but you can consider a custom one in case you want a different content.
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
}
.block-start {
display: inline;
white-space: pre-wrap;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "\A";
}
.block-start:after {
content: attr(class);
display:inline-block;
border:1px solid red;
padding: 3px;
}
<div class="container">
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>

The same trick can also work if you want to clear after
.ib {
border: 1px solid #333;
display: inline-block;
padding: 3px;
}
.block-end {
display: inline;
white-space: pre-wrap;
}
/* Create the break line */
.block-end:not(:first-child):after {
content: "\A";
}
.block-end:before {
content: attr(class);
display: inline-block;
padding: 3px;
border:1px solid red;
}
<div class="container">
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-end"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-end"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-end"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>

Here is some variation of the same idea that can be useful in other situation
With flexbox:
.container {
display:flex;
flex-wrap:wrap;
align-items:center;
}
.ib {
border: 1px solid #333;
padding: 3px;
background:#fff;
position:relative;
margin:0 3px 0;
}
.ib + .ib {
margin-left:0;
}
.block-start {
display: contents;
}
.container {
padding-left:15px;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "";
flex-basis:100%;
height:1px;
}
/* Will replace the content*/
.block-start:after {
content: attr(class);
border:1px solid red;
padding: 3px;
}
<div class="container">
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
With CSS grid:
.container {
display:grid;
grid-template-columns:repeat(auto-fill,minmax(90px,1fr));
grid-gap:2px;
align-items:center;
}
.ib {
border: 1px solid #333;
padding: 3px;
background:#fff;
position:relative;
}
.block-start {
display: contents;
}
.container {
padding-left:15px;
}
/* Create the break line */
.block-start:not(:first-child):before {
content: "";
grid-column:1/-1;
}
/* Will replace the content*/
.block-start:after {
content: attr(class);
border:1px solid red;
padding: 3px;
}
<div class="container">
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>
Another one with CSS grid:
.container {
display:grid;
grid-template-columns:repeat(10000,max-content);
grid-gap:2px;
align-items:center;
}
.ib {
border: 1px solid #333;
padding: 3px;
background:#fff;
position:relative;
}
.container {
padding-left:15px;
}
/* Create the break line */
.block-start {
grid-column:1;
border:1px solid red;
padding: 3px;
}
/* Will replace the content*/
.block-start:after {
content: attr(class);
}
<div class="container">
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
<div class="block-start"></div>
<div class="ib">inline-block</div>
<div class="ib">inline-block</div>
</div>