Reputation: 3488
How do you get an inline-block
element to fit its content width, if the content line-breaks because of screen width?
<!-- parent inline-block -->
<div style='display: inline-block;'>
<div style='display: inline-block; width:200px;'></div>
<!--
If this child line breaks,
two 200px wide blocks are stacked vertically.
That should make the parent width 200px,
but the parent stays much wider than that
-->
<div style='display: inline-block; width:200px;'></div>
</div>
I can't think of how to phrase the question so it sounds easy, but I put together a simple JSFiddle illustrating.
#wide {
position: relative;
width: 100%;
border: 1px solid black;
padding: 5px;
}
#narrow {
position: relative;
width: 175px;
border: 1px solid black;
padding: 5px;
}
.wrap {
display: inline-block;
border: 1px solid green;
margin: auto;
}
.inlineblock {
display: inline-block;
vertical-align: top;
background: red;
min-width: 100px;
min-height: 100px;
border: 1px solid black;
}
<section id='wide'>
<div class='wrap'>
<div class='inlineblock'></div>
<div class='inlineblock'></div>
</div>
</section>
<p>
When the red inline-blocks are forced to line break, how do you make a parent with display:inline-block (the green border) snap to fit? How do you get rid of all the extra horiztonal space in the lower green bordered div?
</p>
<section id='narrow'>
<div class='wrap'>
<div class='inlineblock'></div>
<div class='inlineblock'></div>
</div>
</section>
Upvotes: 46
Views: 27170
Reputation: 125473
inline-block
elements can't achieve this layout - as demonstrated by @Oriol - but,
body {
margin: 0;
}
ul {
display: inline-grid;
grid-template-columns: repeat(auto-fit, 100px);
min-width: 50vw;
/* decorative properties */
grid-gap: 10px;
padding: 0;
list-style: none;
border: 5px solid salmon;
box-sizing: border-box;
/* center the grid */
position: relative;
left: 50vw;
transform: translateX(-50%);
}
li {
background-color: lightblue;
height: 100px;
}
<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>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
<li>21</li>
<li>22</li>
</ul>
Basically the relevant code boils down to this:
ul {
display: inline-grid; /* (1) */
grid-template-columns: repeat(auto-fit, 100px); /* 100px = column width - (2) */
min-width: 50vw; /* or any user-defined min-width (3) */
}
Make the container element an inline-grid container. This will cause the grid to 'shrink-wrap' its contents - so that the grid width will never be wider than it's contents.
Set the grid with a responsive layout (The auto-fill
/ auto-fit
value is used for responsive layouts). If there is no room in a row to fit the next item - it wraps to the next row.
When a responsive layout is used together with an inline-grid - the grid width will equal the width of one item of the grid. (when no width/min-width is explicitly set - like this)
So if the given min-width exactly fits in a certain number of items - that means that this will also be the maximum width of the grid because the next item will wrap.
If however the min-width doesn't exactly correspond to the width of 'n' items in that it also fits in part of the n+1th item - in this case the grid will slightly expand to exactly fit the n+1th item - with the n+2th item wrapping to the next row.
Upvotes: 21
Reputation: 288130
You can't. By default, inline-block
elements have a shrink-to-fit width:
The shrink-to-fit width is:
min(max(preferred minimum width, available width), preferred width)
.
Then,
preferred minimum width <= preferred width <= available width
, the width will be the preferred width
, as you desire.available width <= preferred minimum width <= preferred width
, the width will be the preferred minimum width
, as you desire.preferred minimum width <= available width <= preferred width
, the width will be the available width
, even if you don't like it.If you really don't want this, I guess you could add a resize
event listener with JS, and set the desired width manually.
Upvotes: 31