javascript - 根据父容器大小隐藏元素

标签 javascript css responsive-design media-queries

我正在创建一个表组件,该组件将包含 1-10 列,具体取决于它接收到的数据。这些列位于响应式容器内,并且它们永远不会小于 100 像素。根据屏幕大小,我想显示所有列,但随着容器变小,我想隐藏不适合的列。

例如如果容器的宽度是550px,有7列。我想隐藏最后两列并显示剩余的 5 列。这 5 列的宽度应为 (550/5 = 110px)。我可以通过简单地向父容器添加一个类来实现这一点,该类将子容器除以 5 (20%)。

一旦我隐藏了最后两列,我希望能够单击一个按钮来移动行以显示隐藏的列。请记住,我希望它根据容器中的空间来移动列。 例如如果用户缩小窗口并且容器的宽度现在为 380px 并且有 7 列,您应该一次只能看到三列。如果单击下一个底部,它将显示接下来的三个元素。如果您再次单击它,它将显示最后一个。

我的问题是如何删除多余的列并将我的类应用于父容器?那么我怎样才能点击这些以便我可以查看所有列?下面是我开始编写的 JS 代码,但我需要帮助将它们组合在一起。

    function calcSize() {
    var tableExpenses = document.querySelectorAll('.table-expenses');
    var tableExpensesWidth = document.querySelector('.table-expenses').offsetWidth;
    var tableExpensesLength = document.querySelector('.table-expenses').children.length;

    if (tableExpensesWidth > 699 ) {
        tableExpenses.classList.add('Rtable--7cols');
        // remove all other 'Rtable--' classes
    }

    if (tableExpensesWidth > 599 ) {
        tableExpenses.classList.add('Rtable--6cols');
        // remove all other 'Rtable--' classes
    }

    if (tableExpensesWidth > 499) {
        tableExpenses.classList.add('Rtable--5cols');
        // remove all other 'Rtable--' classes
    }


     // Do the same thing for other widths...


    if (tableExpensesWidth/tableExpensesLength < 100) {
        //only show children that can fill that space
    }
    }

最佳答案

我认为可能有一个更简单的解决方案,但我试图弄清楚如何做到这一点会限制 JavaScript 和 media queries .该方法是有一个“开始”类,表示“重点”表列。隐藏所有不是“开始”列或不是与“开始”相邻的已配置同级数的列。

这是用多个 adjacent sibling selectors 完成的.

在我的示例中,我有一些辅助类来模拟媒体查询,而无需实际调整屏幕大小。您可以使用单选按钮控制模拟屏幕的大小,以及使用数字输入聚焦哪一列。

它有很多 CSS,但您不必在代码中调整任何元素大小。

const m = document.getElementsByTagName("main")[0],
  table = document.getElementById("table"),
  countInput = document.getElementById("count"),
  sizeRadios = document.getElementsByName("size");

const vars = {
  get size() {
    return this._size;
  },
  set size(val) {
    if (this._size === val) return;
    this._size = val;
    Array.from(sizeRadios).forEach(r => r.removeAttribute("checked"));
    let tmp = document.querySelector(`input[type="radio"][name="size"][value="${val}"]`);
    tmp.setAttribute("checked", "");
    m.className = this._size;
  },
  get count() {
    return this._count;
  },
  set count(val) {
    if (this._count === val) return;
    this._count = val;
    countInput.value = val;
    this.updateTable();
  },
  updateTable() {
    const trs = table.querySelectorAll("tr");
    for (const tr of trs) {
      const tds = Array.from(tr.querySelectorAll("th, td"));
      if (tds.length < this.count) {
        return;
      }

      tds.forEach(td => td.classList.remove("start"));
      tds[this.count - 1].classList.add("start");
    }
  }
};

Array.from(sizeRadios).forEach(radio => radio.addEventListener("change", e => {
  if (!e.target.checked) return;
  vars.size = e.target.value;
}));

countInput.addEventListener("input", e => {
  vars.count = parseInt(countInput.value, 10);
});

vars.size = "medium";
vars.count = 2;
table {
  width: 100%;
}

table th,
table td {
  border: 1px solid black;
}

main:not(.default) table th,
main:not(.default) table td {
  display: none;
}


/* Simulated Media Query Rules */

main.extra-small table th.start,
main.extra-small table td.start,
main.small table th.start,
main.small table td.start,
main.medium table th.start,
main.medium table td.start,
main.large table th.start,
main.large table td.start,
main.small table th.start+th,
main.small table td.start+td,
main.medium table th.start+th,
main.medium table td.start+td,
main.large table th.start+th,
main.large table td.start+td,
main.medium table th.start+th+th,
main.medium table td.start+td+td,
main.large table th.start+th+th,
main.large table td.start+td+td,
main.large table th.start+th+th+th,
main.large table td.start+td+td+td {
  display: table-cell;
}


/* Media Query Rules */

main.media-query table th.start,
main.media-query table td.start {
  display: table-cell;
}

@media (min-width: 768px) {
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start+th,
  main.media-query table td.start+td {
    display: table-cell;
  }
}

@media (min-width: 992px) {
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start+th,
  main.media-query table td.start+td,
  main.media-query table th.start+th,
  main.media-query table td.start+td,
  main.media-query table th.start+th+th,
  main.media-query table td.start+td+td {
    display: table-cell;
  }
}

@media (min-width: 1200px) {
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start,
  main.media-query table td.start,
  main.media-query table th.start+th,
  main.media-query table td.start+td,
  main.media-query table th.start+th,
  main.media-query table td.start+td,
  main.media-query table th.start+th,
  main.media-query table td.start+td,
  main.media-query table th.start+th+th,
  main.media-query table td.start+td+td,
  main.media-query table th.start+th+th,
  main.media-query table td.start+td+td,
  main.media-query table th.start+th+th+th,
  main.media-query table td.start+td+td+td {
    display: table-cell;
  }
}
<main>
  <table id="table">
    <caption>Table that will adjust how many colums are displayed based on screen size/controlling class.</caption>
    <thead>
      <tr>
        <th>Column 1</th>
        <th>Column 2</th>
        <th>Column 3</th>
        <th>Column 4</th>
        <th>Column 5</th>
        <th>Column 6</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>a1</td>
        <td>a2</td>
        <td>a3</td>
        <td>a4</td>
        <td>a5</td>
        <td>a6</td>
      </tr>
      <tr>
        <td>b1</td>
        <td>b2</td>
        <td>b3</td>
        <td>b4</td>
        <td>b5</td>
        <td>b6</td>
      </tr>
      <tr>
        <td>c1</td>
        <td>c2</td>
        <td>c3</td>
        <td>c4</td>
        <td>c5</td>
        <td>c6</td>
      </tr>
    </tbody>
  </table>
  <hr>
  <div>
    <p>Mock media query setter which applies a class to the <code>&lt;main&gt;</code> tag to simulate media queries.</p>
    <ul>
      <li><label><input type="radio" name="size" value="default"> <span>Default (all columns)</span></label></li>
      <li><label><input type="radio" name="size" value="media-query"> <span>Media Query (follow MQ rules)</span></label></li>
      <li><label><input type="radio" name="size" value="extra-small"> <span>Extra Small (1 column)</span></label></li>
      <li><label><input type="radio" name="size" value="small"> <span>Small (2 columns)</span></label></li>
      <li><label><input type="radio" name="size" value="medium"> <span>Medium (3 columns)</span></label></li>
      <li><label><input type="radio" name="size" value="large"> <span>Large (4 columns)</span></label></li>
    </ul>
  </div>
  <hr>
  <div>
    <p>Sets which column you are "focused" as in which column you have scrolled to.</p>
    <label><span>Starting Column</span> <input id="count" type="number" min="1" value="3" step="1"></label>
  </div>
</main>

关于javascript - 根据父容器大小隐藏元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49927077/

相关文章:

javascript - 移动端完全不同的 View

css - 将 div 的高度设置为等于波本威士忌外容器的高度

HTML 参数中的 JavaScript

html - CSS:悬停时更改背景颜色

html - 行高不适用于 ios chrome

css - 页面特定的 CSS 样式,但代码放在哪里?

javascript - CSS - 给定元素之后的样式元素

javascript - 无法对超过 9 个输入 javascript 求和

javascript - Express.js 意外的 'GET' 到 '/json/version'

javascript - 从任意 Angular html Canvas 复制一个矩形