Vertical text frozen at the top of a table

My goal is to design a table with frozen threads and vertically oriented labels in the header. I have made an attempt at implementing this below, but as a newcomer to CSS, I am facing several challenges.

  1. One issue I've encountered with my solution is that it's not immediately clear that there are more rows to scroll through, as the scrollbar remains hidden until you start scrolling. Is there a way to keep the scrollbar visible at all times?

  2. There is also a large gap above where the party names are displayed in the header. While adjusting the values in "th.vertical" can increase this gap, I'm struggling to eliminate it entirely. How can I make the header only as tall as the text it contains?

  3. Lastly, I would like the vertical text in the header to be centered in relation to the column values, but I haven't been able to achieve this yet. Any suggestions on how I could do this?

  4. Additionally, I want to enable sorting on any column

table thead tr {
  display: block;
}

table th,
table td {
  width: 75px; //fixed width
}

div.vertical {
  margin-left: -100px;
  position: absolute;
  width: 210px;
  transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);
  /* Safari/Chrome */
  -moz-transform: rotate(-90deg);
  /* Firefox */
  -o-transform: rotate(-90deg);
  /* Opera */
  -ms-transform: rotate(-90deg);
  /* IE 9 */
}

th.vertical {
  height: 60px;
  line-height: 14px;
  padding-bottom: 100px;
  text-align: left;
}

table tbody {
  display: block;
  height: 500px;
  overflow: auto;
}
<table class='vrt-header'>
  <thead>
    <tr>
      <th></th>
      <th class="vertical">
        <div class="vertical">Republican</div>
      </th>
      <th class="vertical">
        <div class="vertical">Democrat</div>
      </th>
      <th class="vertical">
        <div class="vertical">Libertarian</div>
      </th>
      <th class="vertical">
        <div class="vertical">Green</div>
      </th>
    </tr>
  </thead>
  <tbody>
    <!-- Data goes here -->
  </tbody>
</table>

Answer №1

I've made some adjustments to your code...

  1. Unfortunately, I couldn't find a better way to always display the scrollbar other than using overflow-y: scroll;.
  2. I tried various styling changes for your headers but struggled with dynamically adjusting their height after applying transform. Ended up using fixed values.
  3. The updated styling should address this issue.
  4. You might want to look into the Stupid Table Plugin for jQuery, it can simplify table sorting.

In addition, I included:

  • Added some hover effects using :hover on the th elements to highlight actions.
  • Implemented row color alternation using the :nth-of-type() selector.

Here's the revised snippet:

// Find documentation here: https://joequery.github.io/Stupid-Table-Plugin/
$("#simpleTable").stupidtable();
table thead,
table tbody {
  display: block;
}

table tbody {
  height: 500px;
  overflow-y: scroll; /* Ensures scrollbar visibility */
}

thead th {
  position: relative;
  cursor: pointer;
  height: 90px;
  background: #ccc;
  border-bottom: 2px solid black;
}

thead th:hover {
  background: #ccf; 
}

thead th p {
  position: absolute;
  bottom: 20px;
  transform: rotate(-90deg);
  text-align: left;
}

table th,
table th p,
table td {
  width: 75px;
}

table td {
  text-align: center;
}

table tr td:first-of-type {
  text-align: left;
}

table tr:nth-of-type(odd) td {
  background: #eee;
}

table tr:nth-of-type(even) td {
  background: #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stupidtable/1.1.3/stupidtable.min.js"></script>

<table id="simpleTable" class='vrt-header'>

  <thead>
    <tr>
      <th data-sort="string"></th>
      <th data-sort="int">
        <p>Republican</p>
      </th>
      <th data-sort="int">
        <p>Democrat</p>
      </th>
      <th data-sort="int">
        <p>Libertarian</p>
      </th>
      <th data-sort="int">
        <p>Green</p>
      </th>
    </tr>
  </thead>

  <tbody>

    <tr>
      <td>
        Alabama
      </td>
      <td>
        65
      </td>
      <td>
        25
      </td>
      <td>
        10
      </td>
      <td>
        0
      </td>
    </tr>

    <!-- Additional rows -->

  </tbody>


</table>

Hope this helps!

Answer №2

1) It seems like this issue is related to using a Mac, which has overlay scrollbars as the default. Chrome and Safari have support for webkit-scroll properties that allow you to make the scrollbar always visible, but it may not be possible to override this behavior in Firefox.

2) The problem could also be caused by the UA style sheet's 'th' entry: 'td, th { padding: 1px; }'. You can try overriding it with 'th { padding: 0px; }'

3) The desired behavior of the table should actually be the default, but there are two main reasons why it might not be working. This could be a challenging issue to address without using an existing component. Instead of trying to solve it from scratch, consider finding a ready-made solution such as a jQuery plugin or Angular component. Implementing all these features in a cross-browser compatible way would likely require writing a significant amount of JavaScript code.

The first reason for the issue is that setting 'div.vertical { position:absolute }' removes the elements from the normal flow, causing alignment issues with the header columns.

The second reason is that inadvertently creating three tables due to 'tr { display:block }' and 'tbody {display:block}' settings enables scrolling. The layout interprets them as regular 'div' elements, resulting in nested tables within each other.

Even if you were able to address the first issue, the multiple nested structures would still pose a challenge.

Chrome's layout tree provides insight into the structure, showing how each element is rendered within the table.

Answer №3

Following your instructions, I successfully implemented all four tasks using primarily CSS.

I even managed to style the third question using only CSS! By setting the height with padding and a wrapping div for 'th', like so:

th.vertical {
  height: 0;
  vertical-align: bottom;
  text-align: left;
  cursor: pointer;
}
div.verticalWrapper {
    height: 0;
    padding-top: 100%;
    position: relative;
}

Note the importance of padding-top: 100%

1) To achieve this effect, I created a container div for the table.

.tableContainer {
  height: 400px;
  width: 500px;
  overflow: scroll;
}

Regarding iOS compatibility, it's simply about personal preference:

2) As we're rotating the element, the height should match the width. I solved this using CSS, and more details can be found in this answer: here

3) The transformation was done through CSS.

4) I followed the same approach as mentioned by @takit-isy

Answer №4

Completing this task will require some effort. I recommend using divs instead of tables.

I created a sample to demonstrate how it could be structured:

<div class='table'>
  <div class='header'>
    <div><p class="vertical first">&nbsp;</p></div>
    <div><p class="vertical">Republican</p></div>
    <div><p class="vertical">Democrat</p></div>
    <div><p class="vertical">Libertarian</p></div>
    <div><p class="vertical">Green</p></div>
  </div>
  <div class='scroller'>
    <div class='content'>
      <div>
        <div>Alabama</div>
        <div>65</div>
        <div>25</div>
        <div>10</div>
        <div>0</div>
      </div>

      (Other states and data entries)

    </div>
  </div>
</div>

.table{
  height:300px;
  width:500px;

}
.vertical{
  transform: rotate(-90deg);
  width:56px;
  margin:0px;
}
.first{
  padding-right: 268px;
}
.header{
  height:150px;
  width:500px;
  display:flex;
}
.header>div{
  display:flex;
}
.scroller{
 height:calc(100% - 50px);
 overflow-y:scroll;
}
.content{
  width:100%;
  display:table;
}
.content>div{
  display:table-row;
  width:500px;
}
.content>div>div{
  display:table-cell;
}

http://jsfiddle.net/xjhun7zf/6/`

(Please note that this is a quick demonstration created in 20 minutes)

If you separate the content into two containers - one for the header and one for the body, you can fix the position and height of the header while allowing the body to occupy the rest of the space;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to duplicate an image on both sides in a vertical manner?

I've successfully implemented a background image on the left side of the website, however, I'm facing difficulty in replicating the same effect on the right side of the webpage. <style> body { background-image: url('background. ...

What is the reason behind frameworks and similar tools choosing to deprecate functions rather than simply updating them?

Take, for instance, the deprecation of jQuery's .live() in favor of .on(), and the transition from mysql_* to mysqli in MySQL. Why do frameworks and programming languages choose to phase out old functions rather than simply updating them? Apologies if ...

An error occurred when attempting to hide or show a jQuery loading animation

Here is the HTML code I am using: <div id="success_message" style="display:none"> <p>Good job!</p> </div> <div id="my-form"> <form> <input>....... (lots of inputs) <input id="my-btn" ...

Reinvent the AJAX functionality

Is there a way to create a custom function that changes the default ajax functionality? I currently have this ajax function implemented: $.ajax({ type: "POST", url: "http://" + document.location.host + '/userajax', data: 'type= ...

The ng-click event is not triggering the Controller Function as expected

This is the Code for My View <div ng-controller="signupCtrl"> <ul class="list-group" > <li class="list-group-item"> <div class="form-group"> <input type="text" ng-model="signupCtrl.firstName"> ...

What is the preferred convention for defining AngularJS directives as "attributes" versus "elements"?

When creating Angular directives, I've noticed that some directives could also be defined as either an HTML element or an attribute. I'm curious to know what the community convention is for choosing between the two, and the reasons behind it. Fo ...

Iterate through the classes for updates rather than focusing on individual id fields

I am currently working on creating a function that can refresh data with an AJAX call for multiple instances of a class within a single page. The function functions perfectly when there is only one instance on the page: $(document).ready(function() { ...

Using two modal popups while passing an identifier

UPDATE: In my investigation, I discovered that a plain input tag without MVC RAZOR works as expected: <input type="text" class="hiddenid2" /> //WORKED However, when using the following code, it does not work: @Html.Editor("id", "", new { htmlAtt ...

What is the best way to include a string in formData when making an ajax request

Is there a way to include the id when sending formdata? I need help modifying my code for better understanding. $(document).ready(function() { $("#profile_photo_form").on('submit', (function(e) { e.preventDefault(); var id = $("#update ...

Is there a way to display the contents of a zipped file using an HTML IFrame?

Can I display the contents of a zipped file in an HTML iframe? For example: My_File.pdf.zip contains My_File.pdf. I currently have something like this <iframe src="/path of the folder/My_File.pdf.zip" /> The src attribute points to the zipped file ...

As you scroll, the opacity gradually increases, creating a dynamic visual

Struggling to replicate a feature on a website where images gain opacity as you scroll down? Check out this site for reference: . While my current code somewhat achieves this effect, I'm having trouble figuring out how to apply a darker opacity gradua ...

Aligning a div in relation to the background image

I am seeking guidance on how to center a Div Box and make it responsive relative to the background image. The div box should be contained within the white box, similar to the example shown here: body{ font-family: 'Roboto Mono', monospace; ...

Change the default content of the jQuery menu with a content changer

After sharing some base code for a webpage to dynamically change its content based on menu selections, I wanted to showcase the code. Take a look below: HTML: <!DOCTYPE html> <html> <head> <link rel='stylesheet' type=&apos ...

Is it possible to refresh HTML content using jQuery?

Currently, I am attempting to iterate through response data and integrate the values into the HTML of my webpage. It's crucial for me to clear any existing values in the HTML so that only the new ones are displayed, keeping it up-to-date. The structu ...

Executing a mouse click on a dynamic button using Selenium IDE

I am facing an issue where the button I need to click on my website has a changing ID suffix every time I visit the site. To tackle this problem, I have saved the suffix in a variable and attempted to combine it with the prefix so that I can click the butt ...

Using the OR selector in a complex selector with jQuery

I am currently working on modifying a selector that locates every 6th product_tile element, then drills down to the child div with the tile_back class, and finally targets the select box with the name crust. However, I now need this selector to also includ ...

I would like to retrieve my data using my personal API and have them displayed as checkboxes

https://i.sstatic.net/qPSqe.jpgHere is an excerpt of the progress I have made main.html (it's actually a form) <div class="form-group form-check-inline"> <input class="form-check-input" type="radio" name=& ...

Eliminate the prior click action from the document object model

I am working with a set of elements that each have unique IDs and contain a span tag with the same image. For example: Under each element, there is a save icon. When a user clicks on it, the icon changes to a non-save icon. The issue arises when I click ...

Restricting the height of the grid list in Vuetify

Lately, I've been working with Vue.js and the Vuetify framework, and I encountered a challenge that has me stumped. In certain instances, I need to present data in a grid layout using the vuetify grid component. After examining the code, I decided t ...

Selenium - How to effectively obtain hyperlinks?

There are numerous web elements similar to this example <a data-control-name="browsemap_profile" href="/in/quyen-nguyen-63098b123/" id="ember278" class="pv-browsemap-section__member ember-view"> <img widt ...