skip to Main Content

When a display: flex container has flex-wrap: wrap applied the elements still try to take all the available space left. Is there a way to get rid of that extra space on the right of the inner elements or rather the parent element no trying to be 100% of the outer space by default?

As you can see on the image the <- {month} -> could have been narrower if the flex element wasn’t trying to take the entire space that’s left after the wrap.

enter image description here

Here’s similar case but just made simpler. When you start making the window smaller for the elements to wrap, calendars‘ inner elements take entire width even though they don’t have to. What am I missing here? Can the "< January >" block automatically take less space?

.actions {
  display: flex;
  justify-content: space-between;
}

.calendars {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
}

.no {
  display: inline-block;
  width: 30px;
  background: lightgreen;
}
<div>
  <div class="actions">
    <span><</span>
    <span>January</span>
    <span>></span>
  </div>
  
  <div class="calendars">
    <div>
      <span class="no">1</span>
      <span class="no">2</span>
      <span class="no">3</span>
      <span class="no">4</span>
      <span class="no">5</span>
      <span class="no">6</span>
      <span class="no">7</span>
    </div>

    <div>
      <span class="no">1</span>
      <span class="no">2</span>
      <span class="no">3</span>
      <span class="no">4</span>
      <span class="no">5</span>
      <span class="no">6</span>
      <span class="no">7</span>
    </div>
  </div>
<div>

Desired outcome
enter image description here

2

Answers


  1. Does this grid-based solution do what you need? The key style is to set the actions element to span all grid columns.

    .actions {
      grid-column: 1 / -1;
    }
    

    The only limitation I’ve found with it is that if you have fewer months than will fill the screen horizontally, the actions element will still be too wide.

    var m = document.querySelector('.month')
    for (var i = 0; i < 9; i++)
      m.insertAdjacentElement('afterend', m.cloneNode(true))
    .d1 {
      border: 1px solid red;
      display: grid;
      grid-template-columns: repeat(auto-fit, 240px);
      gap: 20px;
    }
    
    .d1>* {
      border: 1px solid blue;
    }
    
    .actions {
      grid-column: 1 / -1;
      display: flex;
      justify-content: space-between;
    }
    
    .month {
      display: flex;
      flex-direction: column;
      gap: 5px;
    }
    
    .month>div {
      display: flex;
      gap: 5px;
    }
    
    .month>div>span {
      background: lightgreen;
      flex: 1 1 0;
    }
    <div class="d1">
    
      <div class="actions">
        <span>&lt;</span>
        <span>January</span>
        <span>&gt;</span>
      </div>
    
      <div class="month">
        <div>
          <span>1</span>
          <span>2</span>
          <span>3</span>
          <span>4</span>
          <span>5</span>
          <span>6</span>
          <span>7</span>
        </div>
    
        <div>
          <span>8</span>
          <span>9</span>
          <span>10</span>
          <span>11</span>
          <span>12</span>
          <span>13</span>
          <span>14</span>
        </div>
      </div>
    </div>

    Make sure you use the full page link when running this snippet, then adjust the width of your browser to see how it responds.

    EDIT Piggy backing on this solution above:
    Consider switch to a grid layout. Here I show the 7 days in a week in a-row for the CSS and then only have to put the correct number of blanks at the start.

    .parent-container
    {
      display: grid;
      grid-template-columns: repeat(auto-fit, 1fr);
    }
    
    .actions {
      display: grid;
      place-items: center;
    }
    
    .calendar-container {
      display: grid;
      grid-gap: 0.5em;
      grid-template-columns: repeat(auto-fill, 13em);
      justify-content: center;
    }
    
    .calendar-month {
      display: grid;
      grid-gap: 0.25em;
      grid-template-columns: repeat(auto-fill, 1fr);
      grid-template-rows: 1.5em;
      border: solid 1px green;
      place-items: center;
    }
    
    .calendar-month .a-row {
      display: grid;
      grid-template-columns: repeat(7, 1.5em);
      grid-gap: 0.25em;
      place-items: center;
    }
    
    .no {
      text-align: center;
      display: block;
      width: 1.5em;
      background: lightgreen;
    }
    <div class="parent-container">
      <div class="calendar-container">
        <div class="calendar-month">
          <div class="actions">
            <span>January</span>
          </div>
          <div class="a-row">
            <span class="no">1</span>
            <span class="no">2</span>
            <span class="no">3</span>
            <span class="no">4</span>
            <span class="no">5</span>
            <span class="no">6</span>
            <span class="no">7</span>
            <span class="no">8</span>
            <span class="no">9</span>
            <span class="no">10</span>
            <span class="no">11</span>
            <span class="no">12</span>
            <span class="no">13</span>
            <span class="no">14</span>
            <span class="no">15</span>
            <span class="no">16</span>
            <span class="no">17</span>
            <span class="no">18</span>
            <span class="no">19</span>
            <span class="no">20</span>
            <span class="no">21</span>
            <span class="no">22</span>
            <span class="no">23</span>
            <span class="no">24</span>
            <span class="no">25</span>
            <span class="no">26</span>
            <span class="no">27</span>
            <span class="no">29</span>
            <span class="no">30</span>
            <span class="no">31</span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
          </div>
        </div>
        <div class="calendar-month">
          <div class="actions">
            <span>February</span>
          </div>
          <div class="a-row">
            <span class="no"></span>
            <span class="no"></span>
            <span class="no">1</span>
            <span class="no">2</span>
            <span class="no">3</span>
            <span class="no">4</span>
            <span class="no">5</span>
            <span class="no">6</span>
            <span class="no">7</span>
            <span class="no">8</span>
            <span class="no">9</span>
            <span class="no">10</span>
            <span class="no">11</span>
            <span class="no">12</span>
            <span class="no">16</span>
            <span class="no">13</span>
            <span class="no">14</span>
            <span class="no">15</span>
            <span class="no">16</span>
            <span class="no">17</span>
            <span class="no">18</span>
            <span class="no">19</span>
            <span class="no">20</span>
            <span class="no">21</span>
            <span class="no">22</span>
            <span class="no">23</span>
            <span class="no">24</span>
            <span class="no">25</span>
            <span class="no">26</span>
            <span class="no">27</span>
            <span class="no">28</span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
          </div>
        </div>
        <div class="calendar-month">
          <div class="actions">
            <span>Bearanary</span>
          </div>
          <div class="a-row">
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no">1</span>
            <span class="no">2</span>
            <span class="no">3</span>
            <span class="no">4</span>
            <span class="no">6</span>
            <span class="no">7</span>
            <span class="no">8</span>
            <span class="no">9</span>
            <span class="no">10</span>
            <span class="no">11</span>
            <span class="no">12</span>
            <span class="no">13</span>
            <span class="no">14</span>
            <span class="no">15</span>
            <span class="no">16</span>
            <span class="no">17</span>
            <span class="no">18</span>
            <span class="no">19</span>
            <span class="no">20</span>
            <span class="no">21</span>
            <span class="no">22</span>
            <span class="no">23</span>
            <span class="no">24</span>
            <span class="no">25</span>
            <span class="no">26</span>
            <span class="no">27</span>
            <span class="no">29</span>
            <span class="no">30</span>
            <span class="no">31</span>
          </div>
        </div>
        <div class="calendar-month">
          <div class="actions">
            <span>Fishly</span>
          </div>
          <div class="a-row">
            <span class="no"></span>
            <span class="no"></span>
            <span class="no"></span>
            <span class="no">1</span>
            <span class="no">2</span>
            <span class="no">3</span>
            <span class="no">4</span>
            <span class="no">6</span>
            <span class="no">7</span>
            <span class="no">8</span>
            <span class="no">9</span>
            <span class="no">10</span>
            <span class="no">11</span>
            <span class="no">12</span>
            <span class="no">13</span>
            <span class="no">14</span>
            <span class="no">15</span>
            <span class="no">16</span>
            <span class="no">17</span>
            <span class="no">18</span>
            <span class="no">19</span>
            <span class="no">20</span>
            <span class="no">21</span>
            <span class="no">22</span>
            <span class="no">23</span>
            <span class="no">24</span>
            <span class="no">25</span>
            <span class="no">26</span>
            <span class="no">27</span>
            <span class="no">29</span>
            <span class="no">30</span>
          </div>
        </div>
      </div>
    </div>
    Login or Signup to reply.
  2. I’m afraid the available tools in CSS for automatic width can’t exactly handle it the way you want. When using a wrapping content, either with simple inline text or with flex wrapping, there’re 3 relevant automatic width modes:

    • stretch which takes the full width of the container.
    • max-content which disables the wrapping and takes as much horizontal space as needed.
    • min-content which always wrap so you can as well just use flex-direction: column

    True, there’s also fit-content which smartly switches between the other modes (it’s actually an alias for min(max-content, max(min-content, stretch))[1]), but it does no recursive logic, means it doesn’t say "alright if max-content turns out to be wider than stretch then I’ll go to min-content".

    It’s algorithm picks stretch unless even min-content is wider than stretch or unless even max-content is smaller than stretch, so it doesn’t really help if you want to exactly fit wrapped content.

    The best I can suggest you is give the wrapping up and instead use a grid to define the number of columns based on a media query (perhaps there’s a way to fit it automatically with grid but I failed to find one).

    .actions {
      display: flex;
      justify-content: space-between;
    }
    
    .calendars {
      display: grid;
      width: fit-content;
      gap: 24px;
      background: blue;
    }
    
    @media screen and (min-width: 1000px) {
      .calendars {
        grid-template-columns: 1fr 1fr;
      }
    }
    
    .no {
      display: inline-block;
      width: 30px;
      background: lightgreen;
    }
    <div>
      <div class="actions">
        <span><</span>
        <span>January</span>
        <span>></span>
      </div>
      
      <div class="calendars">
        <div>
          <span class="no">1</span>
          <span class="no">2</span>
          <span class="no">3</span>
          <span class="no">4</span>
          <span class="no">5</span>
          <span class="no">6</span>
          <span class="no">7</span>
        </div>
    
        <div>
          <span class="no">1</span>
          <span class="no">2</span>
          <span class="no">3</span>
          <span class="no">4</span>
          <span class="no">5</span>
          <span class="no">6</span>
          <span class="no">7</span>
        </div>
      </div>
    <div>

    [1] https://drafts.csswg.org/css-sizing-4/#valdef-width-fit-content

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search