Left aligned and centered grid with flexbox

后端 未结 7 2077
半阙折子戏
半阙折子戏 2020-12-30 02:21

I\'d like to implement a responsive grid-like layout using flexbox (without media queries). There can be variable number of elements in the grid. Each item should have fixed

相关标签:
7条回答
  • 2020-12-30 02:59

    If you set an explicit width on the container, you can then apply margin: 0 auto to the containing element as it no longer spans the full width of the window.

    Here is a Codepen example of what you are looking for: http://codepen.io/alexverner/pen/MaExqb

    0 讨论(0)
  • 2020-12-30 03:01

    I think you just need to give your grid container some kind of max-width, then your auto margins should work too. What's happening is your container is expanding 100% to either side so there's nothing for the auto margin to work with.

    So if you want it to expand to 3 items per row max, just set the max-width to 660 (item width + item margin):

    .container {
      max-width: 660px;
      margin: 0 auto;
      display: flex;
      flex-flow: row-wrap;
    }
    .item {
      width: 200px;
      height: 200px;
      margin: 10px;
    }
    

    Here's a Codepen: http://codepen.io/kgrote/pen/qbpGWZ

    The container will fluidly expand until its maximum width is met, then center itself while keeping its children in a left-aligned grid. As the container shrinks, the children will stack as needed.

    0 讨论(0)
  • 2020-12-30 03:05

    I haven't managed to achieve this behavior using flexbox. But it's pretty simple with CSS Grid. You need to apply justify-content: center to the container.

    Example on CodePen

    0 讨论(0)
  • 2020-12-30 03:11

    You can't achieve this with flexbox out of the box (at least I didn't manage to do it). You can try with justify-content: center; but this will center all childer and you'll get something like:

    So the only solution I managed to find is to use another parent element and wrap everything in it.

    Please see this CodePen http://codepen.io/justd/pen/rOeMGZ

    I'm sure you'll find something working for you, just try to combine different CSS techniques.

    0 讨论(0)
  • 2020-12-30 03:12

    Basically, you should structure your page to have default margins to the left and the right. Use percentages, rather than widths in pixels. That way it will be responsive and should look just as good all devices. If you want to add a max width you can of course do that. This will give pretty much the result you wanted originally. With no Javascript. I removed two lines from the .container css as well. Since your handling padding and margins in the items themselves.

    .pageLayout {
        margin: 0 auto;
        width: 80%;
        /* add optional max width  */
    }
    
    .container {
      display: flex;
      flex-wrap: wrap;
    }
    .item {
      height: 200px;
      width: 200px;
      background-color: purple;
      padding: 10px;
      margin: 10px;
    }
    <div class="pageLayout">
      <div class="container">
        <div class="item">Flex item 1</div>
        <div class="item">Flex item 2</div>
        <div class="item">Flex item 3</div>
        <div class="item">Flex item 4</div>
        <div class="item">Flex item 5</div>
      </div>
    </div>

    0 讨论(0)
  • 2020-12-30 03:15

    CSS Grid

    CSS Grid solution is the only elegant and flexible CSS solution.

    .container {
      display: grid;
      grid-template-columns: repeat(auto-fill, 200px);
      grid-auto-rows: 200px;
      grid-gap: 10px;
      justify-content: center;
    }
    
    .item {
      background-color: purple;
      padding: 10px;
    }
    <div class="container">
      <div class="item">Flex item 1</div>
      <div class="item">Flex item 2</div>
      <div class="item">Flex item 3</div>
      <div class="item">Flex item 4</div>
      <div class="item">Flex item 5</div>
    </div>

    Unfortunately, it doesn't have the best browser support, so if you need outdated browsers like IE you'll have to use Javascript to achieve this. It's due the fact that flexbox container occupies all width even in case when items don't.

    Pure Javascript version

    So basically we are calculating needed value of margin-left to center our flexbox items. This Javascript should work regardless of initial markup settings.

    // get width of element with margins
    function getOuterWidth(el) {
      var styles = window.getComputedStyle(el);
      var margins = parseFloat(styles["marginLeft"]) +
        parseFloat(styles["marginRight"]);
    
      return Math.ceil(el.getBoundingClientRect().width + margins);
    }
    
    // get width of element without paddings
    function getContentWidth(el) {
      var styles = window.getComputedStyle(el);
      var paddings = parseFloat(styles["paddingLeft"]) +
        parseFloat(styles["paddingRight"]);
    
      return Math.ceil(el.getBoundingClientRect().width - paddings);
    }
    
    // Get top of element
    function getTopOfElement(el) {
      return el.getBoundingClientRect().top;
    }
    
    var container = document.querySelector(".container");
    var initialMarginLeft = parseFloat(window.getComputedStyle(container)["marginLeft"]);
    // getting array of items
    var items = Array.prototype.slice.call(document.querySelectorAll(".item"));
    
    function centerItems() {
      if (items.length === 0) return 0;
    
      // set margin-left to initial value to recalculate it
      container.style.marginLeft = initialMarginLeft + "px";
    
      var topOfFirstItem = getTopOfElement(items[0]);
      var spaceTakenByElementsOnFirstLine = getOuterWidth(items[0]);
    
      for (var i = 1; i < items.length; i++) {
        // Break in case we are in second line
        if (getTopOfElement(items[i]) > topOfFirstItem)
          break;
        spaceTakenByElementsOnFirstLine += getOuterWidth(items[i]);
      }
    
      // Set margin-left to center elements
      var marginLeft = initialMarginLeft + (getContentWidth(container) - spaceTakenByElementsOnFirstLine) / 2;
    
      container.style.marginLeft = marginLeft + "px";
    };
    
    window.addEventListener("resize", centerItems);
    
    centerItems();
    .container {
      display: flex;
      flex-wrap: wrap;
    }
    
    .item {
      height: 200px;
      width: 200px;
      background-color: purple;
      padding: 10px;
      margin: 10px;
    }
    <div class="container">
      <div class="item">Flex item 1</div>
      <div class="item">Flex item 2</div>
      <div class="item">Flex item 3</div>
      <div class="item">Flex item 4</div>
      <div class="item">Flex item 5</div>
    </div>

    jQuery version

    // get width of element with margins
    function getOuterWidth(el) {
      return $(el).outerWidth(true);
    }
    
    // get width of element without paddings
    function getContentWidth(el) {
      return parseFloat($(el).css("width"));
    }
    
    function getTopOfElement(el) {
      return $(el).position().top;
    }
    
    var $container = $(".container");
    var $items = $(".item");
    var initialMarginLeft = parseFloat($container.css("margin-left"));
    
    function centerItems() {
      if ($items.length === 0) return 0;
    
      // set margin-left to initial value to recalculate it
      $container.css("margin-left", initialMarginLeft + "px");
    
      var topOfFirstItem = getTopOfElement($items[0]);
      var spaceTakenByElementsOnFirstLine = getOuterWidth($items[0]);
    
      for (var i = 1; i < $items.length; i++) {
        // Break in case we are in second line
        if (getTopOfElement($items[i]) > topOfFirstItem)
          break;
        spaceTakenByElementsOnFirstLine += getOuterWidth($items[i]);
      }
    
      // Set margin left to center elements
      var marginLeft = initialMarginLeft + (getContentWidth($container) - spaceTakenByElementsOnFirstLine) / 2;
    
      $container.css("margin-left", marginLeft + "px");
    };
    
    $(window).resize(centerItems);
    
    centerItems();
    .container {
      display: flex;
      flex-wrap: wrap;
    }
    
    .item {
      height: 200px;
      width: 200px;
      background-color: purple;
      padding: 10px;
      margin: 10px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="container">
      <div class="item">Flex item 1</div>
      <div class="item">Flex item 2</div>
      <div class="item">Flex item 3</div>
      <div class="item">Flex item 4</div>
      <div class="item">Flex item 5</div>
    </div>

    0 讨论(0)
提交回复
热议问题