flex-grow not sizing flex items as expected

前端 未结 5 1093
你的背包
你的背包 2020-11-22 11:55

It seems that the content inside a flex div affects its calculated size concerning the flex-grow property. Am I doing something wrong?

In the fiddle pr

5条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-22 12:12

    Update 3:

    I figured out yet another way to get rid of the misalignment.

    This version, together with the 2:nd update, works with the original html untouched, and is using pseudo elements to create the buttons, button hover/click effects included.

    flex only version

    .row {
      width: 60%;
      margin: auto;
      display: flex;
    }
    .button {
      flex: 0 0 33.3%;
      text-align: center;
      position: relative;
      padding: 10px 5px;
      box-sizing: border-box;
      pointer-events: none;
    }
    .button#number0 {
      flex: 0 0 66.6%;
    }
    
    .button:before,
    .button:after {
      content: " ";
      border-radius: 5px;
      border: 1px solid gray;  
      cursor: pointer;
      position: absolute;
      left: 5px;
      top: 5px;
      right: 5px;
      bottom: 5px;
      pointer-events: auto;
    }
    .button:before {
      background: rgba(255, 255, 255, 0.9);
      z-index: -1
    }
    .button:hover:before {
      background: rgba(0, 0, 0, 0.1);
    }
    .button:hover:after {
      border: 2px solid red;
    }
    .button:active:before {
      background: rgba(255, 0, 0, 0.5);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    0
    :

    flex version with a display: table fallback for browsers that does not support the new flexbox model.

    .row {
      display: table;              /* remove for flex only */
      width: 60%;
      margin: auto;
      display: flex;
    }
    .button {
      display:table-cell;          /* remove for flex only */
      width: 33.3%;                /* remove for flex only */
      flex: 0 0 33.3%;
      text-align: center;
      position: relative;
      padding: 10px 5px;
      box-sizing: border-box;
      pointer-events: none;
    }
    .button#number0 {
      width: 66.6%;                /* remove for flex only */
      flex: 0 0 66.6%;
    }
    
    .button:before,
    .button:after {
      content: " ";
      border-radius: 5px;
      border: 1px solid gray;  
      cursor: pointer;
      position: absolute;
      left: 5px;
      top: 5px;
      right: 5px;
      bottom: 5px;
      pointer-events: auto;
    }
    .button:before {
      background: rgba(255, 255, 255, 0.9);
      z-index: -1
    }
    .button:hover:before {
      background: rgba(0, 0, 0, 0.1);
    }
    .button:hover:after {
      border: 2px solid red;
    }
    .button:active:before {
      background: rgba(255, 0, 0, 0.5);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    0
    :


    Update 2:

    In addition to Michael_B's answer, which by the way has a very good explanation, is here an updated version, that actually does give the desired alignment without the, in this case, 1-2 px off.

    Here is a fiddle sample, and an image, of both mine and Michael_B versions, where the border has been increased a little to make it easier to see the misalignment.

    It all comes down to how flexbox calculates sizes when border/padding is present, which you can read more about in this post, where box-sizing: border-box needs to be set along with a few more adjustments, which is commented in the code.

    Here is my fiddle and snippet

    .row {
        display: flex;
        width: calc(100% - 30px);   /* 30px = the sum of the buttons margin: 5px
                                              to avoid horizontal scroll            */
    }
    
    .button {
        display: flex;
        flex-basis: 33.33%;
        flex-shrink: 0;             /* we need flex-grow/shrink to be 1/0 to make
                                       it calculate the size properly               */
        box-sizing: border-box;     /* to take out the borders when calculate the 
                                       flex shrink/grow factor                      */
        justify-content: center;
        align-items: center;
        margin: 5px;
        border-radius: 5px;
        border: 1px solid gray;
        background: rgba(0, 0, 0, 0.1);
        cursor: pointer;
    }
    
    #number0 {
        flex-basis: calc(66.66% + 10px);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    0
    :


    Update:

    flex only version, with a minor change of the existing html structure, using pseudo elements.

    .row {
      display: flex;
    }
    .button {
      flex: 0 0 33.3%;
    }
    .button:after {
      content: attr(data-nr);
      display: block;
      border-radius: 5px;
      border: 1px solid gray;
      background: rgba(255, 255, 255, 0.9);
      text-align: center;
      padding: 3px;
      margin: 5px;
      cursor: pointer;
    }
    .button#number0 {
      flex: 0 0 66.6%;
    }


    flex version, with a minor change of the existing html structure, using pseudo elements, and has a display: table fallback for browsers that does not support the new flexbox model (like IE8/9).

    .row {
      display: table;
      width: 100%;
    }
    .button {
      display: table-cell;
      width: 33.3%;
      padding: 5px;
    }
    .button:after {
      content: attr(data-nr);
      display: block;
      border-radius: 5px;
      border: 1px solid gray;
      background: rgba(255, 255, 255, 0.9);
      text-align: center;
      padding: 3px;
      cursor: pointer;
    }
    .button#number0 {
      width: 66.6%;
    }
    
    
    @supports (display: flex) {
      .row {
        display: flex;
      }
      .button {
        display: block;
        width: auto;
        flex: 0 0 33.3%;
        padding: 0;
      }
      .button#number0 {
        flex: 0 0 66.6%;
      }
      .button:after {
        margin: 5px;
      }  
    }

提交回复
热议问题