Таблица с фиксированным заголовком и фиксированным столбцом на чистом css


100

Мне нужно создать таблицу html (или что-то подобное) с фиксированным заголовком и фиксированным первым столбцом.

В каждом решении, которое я видел до сих пор, используется Javascript или jQueryустановка scrollTop / scrollLeft, но оно не работает плавно в мобильных браузерах, поэтому я ищу решение на чистом CSS.

Я нашел здесь решение для фиксированного столбца: jsfiddle.net/C8Dtf/20/, но я не знаю, как его улучшить, чтобы зафиксировать и заголовок.

Я хочу, чтобы он работал в браузерах webkit или использовал какие-то css3функции, но повторяю, я не хочу использовать Javascriptдля прокрутки.

РЕДАКТИРОВАТЬ: это пример поведения, которого я хочу достичь: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html


Я пока не понимаю, какое отношение имеет <html> <table> с фиксированным заголовком <thead> к css-level-3. Что еще у вас есть ? Что ты уже испробовал ?
Milche Patern

Я пытался применить сложное positionповедение к строкам и ячейкам, но не совсем понимаю, где это применимо или нет.
panfil

2
Этот ответ может помочь вам stackoverflow.com/questions/14834198/…
Гарри,

Ответы:


148

Реальное решение на чистом CSS с фиксированной строкой заголовка и первым столбцом

Мне пришлось создать таблицу с фиксированным заголовком и фиксированным первым столбцом, используя чистый CSS, и ни один из ответов здесь не был тем, что я хотел.

position: stickyСвойство поддерживает как прилипание к вершине (как я видел , как это используется самый) и в сторону в современных версиях Chrome, Firefox, и Edge. Это может быть объединено с , divкоторый имеет overflow: scrollсвойство , чтобы дать вам таблицу с фиксированными заголовками , которые могут быть размещены в любом месте на странице:

Поместите свой стол в контейнер:

<div class="container">
  <table></table>
</div>

Используйте overflow: scrollна своем контейнере для включения прокрутки:

div.container {
  overflow: scroll;
}

Как указала Дагмар в комментариях, контейнер также требует a max-widthи max-height.

Используйте , position: stickyчтобы ячейки таблиц прилипают к краю и top, rightили , leftчтобы выбрать , какой край придерживаться:

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}

Как упоминал MarredCheese в комментариях, если ваш первый столбец содержит <td>элементы вместо <th>элементов, вы можете использовать tbody td:first-childв своем CSS вместоtbody th

Чтобы заголовок в первом столбце оставался слева, используйте:

thead th:first-child {
  left: 0;
  z-index: 1;
}

https://jsfiddle.net/qwubvg9m/1/


22
Кажется, это лучший ответ.
user1190132 08

9
@PirateApp Если вы знаете размер widthсвоего первого столбца, вы можете использовать его position: stickyв ячейках второго столбца со leftзначением, равным значению первого столбца width: jsfiddle.net/wvypo83c/794
Мэтью Шлахтер,

4
Этот ответ доказывает, что его стоит прочитать до конца!
mlerley

4
Это не работает без максимальной ширины и максимальной высоты, установленных для контейнера.
Дагмар

9
Этот ответ - маяк, ведущий нас домой через бесконечное море неисправных, чрезмерно сложных, отнимающих много времени ответов из удивительно уверенных и вызывающих недоумение постеров здесь, на SO и в Интернете. Обратите внимание, что если ваш первый столбец содержит <td>элементы вместо <th>элементов, вы можете использовать tbody td:first-childв своем CSS вместо tbody th.
MarredCheese

33

В настоящее время этого можно добиться с помощью CSS только с помощью position: stickyсвойства.

Вот отрывок:

(jsFiddle: https://jsfiddle.net/hbqzdzdt/5/ )

.grid-container {
  display: grid; /* This is a (hacky) way to make the .grid element size to fit its content */
  overflow: auto;
  height: 300px;
  width: 600px;
}
.grid {
  display: flex;
  flex-wrap: nowrap;
}
.grid-col {
  width: 150px;
  min-width: 150px;
}

.grid-item--header {
  height: 100px;
  min-height: 100px;
  position: sticky;
  position: -webkit-sticky;
  background: white;
  top: 0;
}

.grid-col--fixed-left {
  position: sticky;
  left: 0;
  z-index: 9998;
  background: white;
}
.grid-col--fixed-right {
  position: sticky;
  right: 0;
  z-index: 9998;
  background: white;
}

.grid-item {
  height: 50px;
  border: 1px solid gray;
}
<div class="grid-container">
  <div class="grid">
    <div class="grid-col grid-col--fixed-left">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col grid-col--fixed-right">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
    </div>

  </div>
</div>

По поводу совместимости. Он работает во всех основных браузерах, но не в IE. Есть полифилл для, position: stickyно я никогда не пробовал.


2
Это здорово, нравится!
Captain Lu

3
любым способом добиться этого с помощью тегов <table>, а не <div>
Андреас

1
Я думаю, что это не будет иметь хорошей производительности, если вы разрабатываете приложение и вам нужно перебирать записи для печати этой таблицы, потому что для каждого столбца в таблице вам нужно перебрать весь массив записей. Этот HTML работает столбец за столбцом.
igasparetto

@igasparetto Фактически вы можете расположить строки / столбцы наоборот, и решение все равно будет работать. Если у меня будет время позже, я могу создать сниппет с упорядоченной сеткой строка -> столбец.
Альваро

2
Я бы не советовал отображать табличные данные без использования <table> и связанных тегов. Есть несколько проблем с нарушением предполагаемого использования HTML таким образом, включая доступность. См. Также: w3.org/WAI/tutorials/tables
Бен Моррис

15

Это нелегкий подвиг.

Следующая ссылка - на рабочую демонстрацию:

Ссылка Обновлено в соответствии с комментарием lanoxx

http://jsfiddle.net/C8Dtf/366/

Просто не забудьте добавить это:

<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/extras/FixedColumns/media/js/FixedColumns.js"></script>

я не вижу другого способа добиться этого. Особенно с использованием только css.

Это через многое предстоит пройти. Надеюсь это поможет :)


Для переключения фильтра используйте: "bFilter": false
lanoxx

6
Это является возможным достичь этого только с помощью CSS. Непросто, но возможно.
Джимми Т.

из примерно 10 решений это было единственное, что сработало. Кстати, чтобы убрать «Показывать с 1 по 57 из 57 записей» добавить "bInfo" : falseв .dataTable()звонок
hansaplast

datatables == "awesome"
billynoah

голосование против этого решения, потому что оно плохое. theadв своей таблице , которая не связана с изменениями tdэлементов, так что если текст клетка длинная, thширина не будет корректировать соответствующим образом .
vsync

14

Все эти предложения хороши и все такое, но они либо исправляют либо заголовок, либо столбец, а не оба сразу, либо используют javascript. Причина - они не верят, что это можно сделать на чистом CSS. Причина:

Если бы это было возможно, вам нужно было бы вложить несколько прокручиваемых div один в другой, каждый с прокруткой в ​​другом направлении. Затем вам нужно будет разделить вашу таблицу на три части - фиксированный заголовок, фиксированный столбец и остальные данные.

Хорошо. Но теперь проблема - вы можете сделать так, чтобы один из них оставался на месте при прокрутке, но другой вложен в область прокрутки первого и, следовательно, сам скроллируется вне поля зрения, поэтому не может быть исправлен на месте на экран. «Ага, - скажете вы, - но я могу как-то использовать для этого абсолютное или фиксированное положение» - нет, вы не можете. Как только вы это сделаете, вы потеряете возможность прокручивать этот контейнер. Это ситуация с курицей и яйцом - вы не можете иметь и то и другое, они нейтрализуют друг друга.

Я считаю, что единственное решение - через javascript. Вам нужно полностью разделить три элемента и синхронизировать их позиции с помощью javascript. Есть хорошие примеры в других сообщениях на этой странице. Это тоже стоит посмотреть:

http://tympanus.net/codrops/2014/01/09/sticky-table-headers-columns/


9

Я внес некоторые изменения в jsfiddle. Возможно, это то, что вы пытаетесь сделать.

http://jsfiddle.net/C8Dtf/81/

Я жестко запрограммировал названия так:

<table id="left_table" class="freeze_table">
    <tr class='tblTitle'>
         <th>Title 1</th>
         <th>Title 2</th>
    </tr>
</table>

И еще я добавил несколько стилей.

.tblTitle{
   position:absolute;
    top:0px;
    margin-bottom:30px;
    background:lightblue;
}
td, th{
    padding:5px;
    height:40px;
    width:40px;
    font-size:14px;
}

Надеюсь, это то, что вы хотите :)


1
Мне нужен заголовок правой таблицы для прокрутки вместе с ее содержимым.
panfil

Вот URL-адрес: jsfiddle.net/C8Dtf/84 . Вам просто нужно поиграть со стилем для правой таблицы, чтобы выровнять две таблицы.
Филипп-Хуан

Нет. Вы не совсем понимаете. Мне нужно, чтобы заголовок правой таблицы был закреплен вверху, чтобы он все еще был виден, когда таблица прокручивается вверх и вниз, но когда таблица прокручивается вправо или влево, заголовок должен прокручиваться вправо или влево, но по-прежнему фиксироваться вверху. Извините за плохое знание английского языка.
panfil

Итак, хотите, чтобы заголовок правой таблицы был фиксированным при вертикальной прокрутке и прокручивался при горизонтальной прокрутке?
Филипп-Хуан

Это пример поведения, которого я хочу добиться: datatables.net/release-datatables/extras/FixedColumns/…
panfil

9

Пример с использованием только CSS:

.table {
  table-layout: fixed;
  width: 500px;
  border-collapse: collapse;
}

.header th {
  font-family: Calibri;
  font-size: small;
  font-weight: lighter;
  border-left: 1px solid #000;
  background: #d0d0d0;
}

.body_panel {
  display: inline-block;
  width: 520px;
  height: 300px;
  overflow-y: scroll;
}

.body tr {
  border-bottom: 1px solid #d0d0d0;
}

.body td {
  border-left: 1px solid #d0d0d0;
  padding-left: 3px;
  font-family: Calibri;
  font-size: small;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
<body>

  <table class="table">

    <thead class="header">

      <tr>
        <th style="width:20%;">teste</th>
        <th style="width:30%;">teste 2</th>
        <th style="width:50%;">teste 3</th>
      </tr>

    </thead>
  </table>

  <div class="body_panel">

    <table class="table">
      <tbody class="body">

        <tr>
          <td style="width:20%;">asbkj k kajsb ksb kabkb</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

      </tbody>
    </table>

  </div>

</body>


3
Мне нужен был не только хедер, но и первый столбец.
panfil

В этом примере показан подход с двумя таблицами в html: одна таблица отображает только заголовок; вторая таблица отображает только строки, но делает это внутри файла div. Это то, divчто позволяет прокручивать строку, пока заголовок остается на том же месте. Этот подход сработал для моих нужд.
Дэвид Тэнси

Если есть и горизонтальная прокрутка, вам понадобится JS для синхронизации позиций прокрутки таблиц.
Zoltán Tamási

4

Я нашел отличное решение этой проблемы от Пола О'Брайена и хотел бы поделиться ссылкой: https://codepen.io/paulobrien/pen/LBrMxa

Я удалил стиль нижнего колонтитула:

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
.intro {
  max-width: 1280px;
  margin: 1em auto;
}
.table-scroll {
  position: relative;
  width:100%;
  z-index: 1;
  margin: auto;
  overflow: auto;
  height: 350px;
}
.table-scroll table {
  width: 100%;
  min-width: 1280px;
  margin: auto;
  border-collapse: separate;
  border-spacing: 0;
}
.table-wrap {
  position: relative;
}
.table-scroll th,
.table-scroll td {
  padding: 5px 10px;
  border: 1px solid #000;
}
.table-scroll thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}

th:first-child {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 2;
  background: #ccc;
}
thead th:first-child {
  z-index: 5;
}

4

Чтобы исправить как заголовки, так и столбцы, вы можете использовать следующий плагин:


Обновлено в июле 2019 г.

Недавно появилось также чистое решение CSS , основанное на свойстве CSS position: sticky;( здесь для более подробной информации), применяемом к каждому THэлементу (вместо их родительского контейнера).


1
Первая ссылка не работает. Второй использует jQuery.
PussInBoots

Обновленный ответ для удаления мертвой ссылки
Лука Детоми,

2

Недавно мне пришлось создать решение с фиксированной группой заголовков и фиксированным первым столбцом. Я разделил свою таблицу на div и использовал jquery для захвата прокрутки окна.

http://jsfiddle.net/TinT/EzXub/2346/

var prevTop = 0;
var prevLeft = 0;

$(window).scroll(function(event){
  var currentTop = $(this).scrollTop();
  var currentLeft = $(this).scrollLeft();

  if(prevLeft !== currentLeft) {
    prevLeft = currentLeft;
    $('.header').css({'left': -$(this).scrollLeft()})
  }
  if(prevTop !== currentTop) {
    prevTop = currentTop;
    $('.leftCol').css({'top': -$(this).scrollTop() + 40})
  }
});

1

Мы с коллегой только что выпустили новый проект GitHub, который предоставляет директиву Angular, которую вы можете использовать для украшения таблицы фиксированными заголовками: https://github.com/objectcomputing/FixedHeader

Он полагается только на css и angular, с директивой, которая добавляет некоторые div. Не требуется jQuery.

Эта реализация не так полнофункциональна, как некоторые другие реализации, но если вам нужно просто добавить фиксированные таблицы, мы думаем, что это может быть хорошим вариантом.


1

После двух дней борьбы с Internet Explorer 9 + Chrome + Firefox (Windows) и Safari (Mac) я нашел систему, которая

  • Совместим со всеми этими браузерами
  • Без использования javascript
  • Использование только UNE div и одной таблицы
  • Фиксированный верхний и нижний колонтитулы (кроме IE) с прокручиваемым телом. Заголовок и тело с одинаковой шириной столбца

Результат: введите описание изображения здесь

HTML:

  <thead>
    <tr>
      <th class="nombre"><%= f.label :cost_center %></th>
      <th class="cabecera cc">Personal</th>
      <th class="cabecera cc">Dpto</th>
    </tr>
  </thead>
  <tbody>
    <% @cost_centers.each do |cc| %>
    <tr>
      <td class="nombre"><%= cc.nombre_corto %></td>
      <td class="cc"><%= cc.cacentrocoste %></td>
      <td class="cc"><%= cc.cacentrocoste_dpto %></td>
    </tr>
    <% end %>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3"><a href="#">Mostrar mas usuarios</a></td>
    </tr>
  </tfoot>
</table>

CSS:

div.cost_center{
  width:320px;
  font-size:75%;
  margin-left:5px;
  margin-top:5px;
  margin-bottom: 2px;
  float: right;
  display: inline-block;
  overflow-y: auto;
  overflow-x: hidden;
  max-height:300px;  
}

div.cost_center label { 
  float:none;
  font-size:14px;
}

div.cost_center table{
  width:300px;
  border-collapse: collapse; 
  float:right;
  table-layout:fixed;
}

div.cost_center table tr{
  height:16px;
}
div.cost_center th{
  font-weight:normal;
}

div.cost_center table tbody{
  display: block;
  overflow: auto;
  max-height:240px;
}

div.cost_center table thead{
  display:block;
}

div.cost_center table tfoot{
  display:block;
}
div.cost_center table tfoot td{
  width:280px;
}
div.cost_center .cc{
  width:60px;
  text-align: center; 
  border: 1px solid #999;
}

div.cost_center .nombre{
  width:150px;
}
div.cost_center tbody .nombre{
  border: 1px solid #999;
}

div.cost_center table tfoot td{
 text-align:center;  
 border: 1px solid #999; 
} 

div.cost_center table th, 
div.cost_center table td { 
  padding: 2px;
  vertical-align: middle; 
}

div.cost_center table tbody td {
  white-space: normal;
  font:  .8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: white;
}
div.cost_center table th.cabecera { 
  font:  0.8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: #FFEAB5;
}

Хорошая попытка, но мне не подходит. В этом примере ( jsfiddle.net/5ka6e ) размер заголовка изменяется неправильно. Такая ошибка может в конечном итоге привести к несоответствию данных и заголовка.
darkzangel

1
Вы забываете добавить, div.cost_center table{border-collapse: collapse;}и третья подпись должна соответствовать 60 пикселей (в этом примере)
Альберт Катала

1

Существующие ответы подойдут большинству людей, но для тех, кто хочет добавить тени под фиксированным заголовком и справа от первого (фиксированного) столбца, вот рабочий пример (чистый css):

http://jsbin.com/nayifepaxo/1/edit?html,output

Основная хитрость в том, чтобы заставить это работать, заключается ::afterв добавлении тени справа от каждой из первых tdв каждом tr:

tr td:first-child:after {
  box-shadow: 15px 0 15px -15px rgba(0, 0, 0, 0.05) inset;
  content: "";
  position:absolute;
  top:0;
  bottom:0;
  right:-15px;
  width:15px;
}

Мне потребовалось время (слишком долго ...), чтобы все заработало, поэтому я решил, что поделюсь с теми, кто находится в подобной ситуации.


Вы основали это на чьем-либо ответе и добавили тень?
PussInBoots

1

нужно исправить нижний колонтитул верхнего колонтитула


0

Что-то вроде этого может сработать для вас ... Возможно, вам потребуется установить ширину столбцов для строки заголовка.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Обновить:

Я не уверен, что приведенный вами пример возможен только с использованием CSS. Я хотел бы, чтобы кто-нибудь доказал, что я неправ. Вот что у меня есть на данный момент . Это еще не законченный продукт, но он может стать для вас началом. Я надеюсь, что это укажет вам в полезном направлении, где бы это ни было.


Мне нужен не только заголовок, но и исправлен первый столбец.
panfil

5
Проблема в том, что заголовки теряют ширину. Это выглядит некрасиво с разным размером столбца заголовка и размером столбца данных.
Акаш Кава

0

Другое решение - использовать AngularJS. В модуле AngularUI есть директива, ng-gridкоторая поддерживает функцию закрепления столбцов. Это не 100% чистый CSS, как и другие решения.

http://angular-ui.github.io/ng-grid/#columnPinning


0

Пример чистого CSS:

<div id="cntnr">
    <div class="tableHeader">
        <table class="table-header table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>


    <div class="tableBody">
        <table class="table-body table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>

</div>

#cntnr {
    width: auto;
    height: 200px;
    border: solid 1px #444;
    overflow: auto;
}

.tableHeader {
    position: fixed;
    height: 40px;
    overflow: hidden;
    margin-right: 18px;
    background: white;
}

.table-header tbody {
    height: 0;
    visibility: hidden;
}

.table-body thead {
    height: 0;
    visibility: hidden;
}

http://jsfiddle.net/cCarlson/L98m854d/

Недостаток: фиксированная структура / логика заголовка в значительной степени зависит от конкретных размеров, поэтому абстракция, вероятно, не является жизнеспособным вариантом .


Нужен фиксированный заголовок и фиксированный первый столбец.
panfil

Ах ... спасибо, что указали на это, панфил. Я сделаю правку. Cheers
Cody

0

Position: sticky не работает для некоторых элементов, таких как (thead), в Chrome и других браузерах webkit, таких как safari.

Но он отлично работает с (th)

body {
  background-color: rgba(0, 255, 200, 0.1);
}

.intro {
  color: rgb(228, 23, 23);
}

.wrapper {
  overflow-y: scroll;
  height: 300px;
}

.sticky {
  position: sticky;
  top: 0;
  color: black;
  background-color: white;
}
<div class="container intro">
  <h1>Sticky Table Header</h1>
  <p>Postion : sticky doesn't work for some elements like (thead) in chrome and other webkit browsers like safari. </p>
  <p>But it works fine with (th)</p>
</div>
<div class="container wrapper">
  <table class="table table-striped">
    <thead>
      <tr>
        <th class="sticky">Firstname</th>
        <th class="sticky">Lastname</th>
        <th class="sticky">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>James</td>
        <td>Vince</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>jonny@example.com</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>stuart@example.com</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>eoin@example.com</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>joe@example.com</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>chris@example.com</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>liam@example.com</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>jason@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>jos@example.com</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>ben@example.com</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>jofra@example.com</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>mitchell@example.com</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>aaron@example.com</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>david@example.com</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>steve@example.com</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>glenn@example.com</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>marcus@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>nathan@example.com</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>pat@example.com</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>zampa@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

Или посетите мой пример кода :


-1

Думаю, это вам поможет: https://datatables.net/release-datatables/extensions/FixedHeader/examples/header_footer.html

Вкратце, если вы знаете, как создать dataTable, вам просто нужно добавить эту строку jQuery внизу:

$(document).ready(function() {
    var table = $('#example').DataTable();

    new $.fn.dataTable.FixedHeader( table, {
        bottom: true
    } );
} );

bottom: true // для фиксации нижнего заголовка.


-2

Если вы хотите использовать только чистый HTML и CSS, у меня есть решение вашей проблемы:
в этом jsFiddle вы можете увидеть решение без сценария, которое предоставляет таблицу с фиксированным заголовком. Также не должно быть проблем адаптировать разметку для фиксированного первого столбца. Вам просто нужно создать таблицу с абсолютным позиционированием для первого столбца внутри hWrapper-div и переместить vWrapper-div.
Предоставление динамического контента не должно быть проблемой при использовании заманчивых движков на стороне сервера или на стороне браузера, мое решение хорошо работает во всех современных браузерах и более старых браузерах, начиная с IE8.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.