首页 > 解决方案 > 折叠的引导砌体面板在第一次展开时会四处移动

问题描述

嗨,我正在尝试使用 Bootstrap 5 和 Masonry(https://masonry.desandro.com/)在折叠 div 内使用 Pinterest 风格的图像淋浴。这就是我尝试做的事情:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
</head>

<body>

  <button type="button" class="btn btn-secondary btn-lg" data-bs-toggle="collapse" data-bs-target="#My-collapse">Button
</button>

  <div id="My-collapse" class="collapse">
    <div class="mt-3"></div>
    <div class="row" data-masonry='{"percentPosition": true }'>
      <div class="col-sm-4 col-md-3 py-3">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js" crossorigin="anonymous"></script>
</body>

</html>

正如您所看到的,所有图像都堆叠在一起,使它们移开的唯一方法是更改​​屏幕尺寸。因此,我决定尝试使用脚本更新布局:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
</head>

<body>

  <button type="button" class="btn btn-secondary btn-lg" data-bs-toggle="collapse" data-bs-target="#My-collapse">Button
</button>

  <div id="My-collapse" class="collapse">
    <div class="mt-3"></div>
    <div class="row" id="mason">
      <div class="col-sm-4 col-md-3 py-3 mason-item">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3 mason-item">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3 mason-item">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3 mason-item">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
      <div class="col-sm-4 col-md-3 py-3 mason-item">
        <div class="card">
          <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
          <div class="card-body">
            <h5 class="card-title">This is an image</h5>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js" crossorigin="anonymous"></script>
  <script>
    const msnry = new Masonry('#mason', {
      "percentPosition": true,
      "itemSelector": '.mason-item'
    });
    const Col = document.getElementById('My-collapse');

    Col.addEventListener('shown.bs.collapse', function() {
      msnry.layout();
    });
  </script>
</body>

</html>

然而,这仍然不是完美的,因为图像都从一个点离开并向外走。我希望他们从一开始就处于正确的位置。有人可以帮我解决这个问题,或者建议一个可以与 Bootstrap 一起使用的不同 Pinterest 样式的布局库吗?

标签: twitter-bootstrapmasonrybootstrap-5

解决方案


我找到了解决我的问题的方法,它涉及在折叠 div 的高度为最终高度时初始化砌体。我们可以等待过渡完成,但这意味着砌体只会在动画期间弹出,因此您需要在第一次显示坍塌时执行此操作。因此,我们必须添加 show 类,引导程序使用该类设置高度,然后触发浏览器重排(强制浏览器在更改 CSS 时触发重排),初始化砌体,最后删除该类。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
</head>

<body>

<button type="button" class="btn btn-secondary btn-lg" data-bs-toggle="collapse" data-bs-target="#My-collapse">Button
</button>

<div id="My-collapse" class="collapse">
  <div class="mt-3"></div>
  <div class="row" id="mason">
    <div class="col-sm-4 col-md-3 py-3 mason-item">
      <div class="card">
        <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
        <div class="card-body">
          <h5 class="card-title">This is an image</h5>
        </div>
      </div>
    </div>
    <div class="col-sm-4 col-md-3 py-3 mason-item">
      <div class="card">
        <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
        <div class="card-body">
          <h5 class="card-title">This is an image</h5>
        </div>
      </div>
    </div>
    <div class="col-sm-4 col-md-3 py-3 mason-item">
      <div class="card">
        <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
        <div class="card-body">
          <h5 class="card-title">This is an image</h5>
        </div>
      </div>
    </div>
    <div class="col-sm-4 col-md-3 py-3 mason-item">
      <div class="card">
        <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
        <div class="card-body">
          <h5 class="card-title">This is an image</h5>
        </div>
      </div>
    </div>
    <div class="col-sm-4 col-md-3 py-3 mason-item">
      <div class="card">
        <img class="card-img-top" src="https://via.placeholder.com/150" alt="Img">
        <div class="card-body">
          <h5 class="card-title">This is an image</h5>
        </div>
      </div>
    </div>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js" crossorigin="anonymous"></script>
<script>
  const msnry = new Masonry('#mason', {
    "percentPosition": true,
    "itemSelector": '.mason-item',
    "initLayout": false
  });
  const Col = document.getElementById('My-collapse');
  let firstTime = true;
  Col.addEventListener('shown.bs.collapse', function() {
    if (firstTime)
    {
      firstTime = false;
      Col.classList.add('show');
      void(Col.offsetHeight);
      msnry.layout();
      Col.classList.remove('show');
    }
  });
</script>
</body>

</html>

(使用堆栈溢出嵌入时似乎效果不太好,但在普通页面上效果很好)


推荐阅读