根据父容器的大小隐藏元素

时间:2018-04-19 17:39:26

标签: javascript css responsive-design media-queries

我创建一个表组件,根据收到的数据,它将包含1-10列。列位于响应的容器内,它们永远不会小于100px。根据屏幕尺寸,我想显示所有列,但随着容器变小,我想隐藏不合适的列。

e.g。如果容器的宽度是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
    }
    }

1 个答案:

答案 0 :(得分:2)

我认为可以有一个更简单的解决方案,但我试图弄清楚如何做到这将限制JavaScript和media queries。方法是有一个“开始”类,表示“聚焦”表列。隐藏所有不是“开始”列的列,或者不是“start”旁边的已配置数量的兄弟。

这是通过多个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>