Сохранение элемента заголовка всегда сверху при прокрутке?

Я читал многочисленные статьи по этой теме и пытался реализовать несколько, но я просто не могу понять, что это правильно. У меня есть простая таблица HTML, в которой сравниваются продукты:

<table>
  <tr>
    <th>Product:</th>
    <th>Product 1</th>
    <th>Product 2</th>
    <th>Product 3</th>
  </tr>
  <tr>
    <td>Features</td>
    <td>Product 1 features</td>
    <td>Product 2 features</td>
    <td>Product 3 features</td>
   </tr>
   and so the list goes on...
 </table>

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

Заранее благодарю вас!

Ответ 1

Простым методом является наличие строки заголовка в отдельном table из фактических данных. В этой таблице заголовков указано, что она находится как fixed, а затем в таблице ниже, которая содержит результаты, она margin-top устанавливает height таблицы заголовков.

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

Основной пример здесь: http://jsfiddle.net/zKDR4/2/

Вы также можете создать фиксированный заголовок с плагинами jQuery. Взгляните на этот http://fixedheadertable.com/, который очень просто реализовать.

Edit

Как упоминал Андерс, если вы спуститесь по предложенному маршруту, вам нужно будет установить ширину элементов th и td. В противном случае они не будут совпадать, поскольку они являются отдельными таблицами.

Ответ 2

У меня возникла проблема при планировании с заголовками строк (часы) и заголовками столбцов (дни). Я хотел сохранить видимость обоих. Приложение отображает содержимое в IFrame, поэтому я создал горизонтальную DIV и вертикальную DIV вне IFrame со стилем "overflow: hidden". Затем я синхронизировал прокрутки с событием "onscroll" IFrame.

Вот мой код для синхронизации заголовков с прокруткой:

window.onscroll = function () {

        try {
            // - Scroll days header (on the top) horizontally
            var offsetX = (document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft; // Source: http://stackoverflow.com/questions/2717252/document-body-scrolltop-is-always-0-in-ie-even-when-scrolling
            var header1Div = window.parent.document.getElementById("EntetesColonnes");
            header1Div.scrollLeft = offsetX;

            // - Scroll hours header (on the left) vertically 
            var offsetY = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop; // Source: http://stackoverflow.com/questions/2717252/document-body-scrolltop-is-always-0-in-ie-even-when-scrolling
            var header2Div = window.parent.document.getElementById("HeaderHoursLeft");
            header2Div.scrollTop = offsetY;
        }
        catch (ex) {
            alert("FrmPlanningChirurgien/window.onscroll: " + ex.message);
        }
    }

Мое решение не так просто, потому что мне пришлось установить "onresize" ширину горизонтального DIV и высоту вертикальной DIV. Затем это вызывает большую сложность, поскольку onResize можно запускать много раз в секунду, и это событие даже срабатывает в IE8 при прокрутке. Поэтому я сделал setTimeout, чтобы слишком часто перерисовывать заголовки:

var PREVIOUS_frameWidth = 0;
var PREVIOUS_frameHeight = 0;
var timerMakeHeaders = null;

window.onresize = function () {
    try {

        var frameWidth = CROSS.getWindowWidth();
        var frameHeight = CROSS.getWindowHeight();

        if (frameWidth != PREVIOUS_frameWidth || frameHeight != PREVIOUS_frameHeight) {

            // - *** Launch headers creation method
            // - If there is another query to redraw, the Timer is stopped and recreated.
            // - The headers are only redrawn when Timer fires.
            if (timerMakeHeaders != null) {
                window.clearTimeout(timerMakeHeaders);
                timerMakeHeaders = null;
            }
            timerMakeHeaders = window.setTimeout(makeHeaders, 50); 

            // - *** Store new values
            PREVIOUS_frameWidth = frameWidth;
            PREVIOUS_frameHeight = frameHeight;
        }
    } catch (e) { alert("Erreur window.onresize/FrmPlanningChirurgien.aspx : " + e.message); }
}

И, наконец, метод makeHeaders() должен изменить размер DIV:

function makeHeaders() {

    // (...)

    var frame = window.parent.document.getElementById("CalendarFrame"); 
    var iframeRect = frame.getBoundingClientRect(); 
    headerDiv.style.width = iframeRect.right - iframeRect.left - 20; // The 20 pixels are here for the vertical scrollbar width
    headerDiv.scrollLeft = frame.scrollLeft;

    // (...)


    var headerHourDiv = window.parent.document.getElementById("HeaderHoursLeft");
    var newHeight = iframeRect.bottom - iframeRect.top - 20 - 7; // The VISIBLE width for the DIV must be equal to IFRAME Width minus the scroll width or height
    headerHourDiv.style.height = newHeight; 
    headerHourDiv.scrollTop = frame.scrollTop;       


}
catch (e) {
    alert("makeHeaders: " + e.message);
}    }

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

С уважением,

Ответ 3

Я создал пример с помощью JSFiddle, который вы можете посмотреть как демонстрацию.

Единственным недостатком является то, что вам нужно будет указать размеры столбцов, как при использовании position: fixed вы теряете ширину в заголовке.

Это CSS для примера, HTML тот же, что и вы.

thead {
    height: 1em;
}

thead tr {
    position: fixed;
    background-color: #FFF;
}

Ответ 4

Вы можете сделать это, сделав div и зафиксировать позицию. или это можно сделать, добавив inline css

<table style="position:fixed;">
  <tr>
     <th>Product:</th>
     <th>Product 1</th>
     <th>Product 2</th>
      <th>Product 3</th>
  </tr>
  <tr>
    <td>Features</td>
     <td>Product 1 features</td>
     <td>Product 2 features</td>
     <td>Product 3 features</td>
   </tr>
  </table>