【问题标题】:Hide elements based on parent's container size根据父容器大小隐藏元素
【发布时间】:2018-04-20 06:14:26
【问题描述】:

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

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

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

我的问题是如何删除多余的列并将我的类应用于父容器?那么如何点击这些以便查看所有列?下面是我开始编写的 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 css responsive-design media-queries


    【解决方案1】:

    我认为可能有一个更简单的解决方案,但我试图弄清楚如何做到这一点将限制 JavaScript 和 media queries。该方法是有一个表示“重点”表列的“开始”类。隐藏所有不是“start”列或不是与“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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-08
      • 2011-01-10
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      相关资源
      最近更新 更多