vue-good-table icon indicating copy to clipboard operation
vue-good-table copied to clipboard

Improve fixed header

Open VictorCazanave opened this issue 6 years ago • 23 comments

Issue Type

  • [x] Enhancement Request

Specs

What version are you using? 2.13.1

What browser? Last 2 versions, IE >= 10, Safari >= 7

Expected Behavior

What did you expect to happen? The fixed header should perfectly match the columns and show a scrollbar in the table body.

Actual Behavior

What actually happened? The header and columns are not aligned (it probably depends on OS and browser). The top of the scrollbar is not visible.

Solution

In my project I implemented a solution based on this copeden and it works well on different browers (Chrome, Firefox, IE 11) and OS (Windows 10, MacOS). If you agree with this enhancement, I may have time to make a PR.

VictorCazanave avatar Aug 27 '18 08:08 VictorCazanave

+1

thenightex avatar Aug 29 '18 11:08 thenightex

@VictorCazanave clever! However, there are a few things that I think will be tough to solve for with this approach.

  1. the divs within th assume that the wrapper is the relatively positioned element and not the th and as a result, each div actually spans the full length of the wrapper... the reason we don't actually see this is because luckily the next column div is drawn on top of the first one. If you want to see the issue, just make the header text longer.
  2. As you can imagine, positioning the sort indicator would be a challenge on the right (given that each div spans the whole length of the table)
  3. Think about the second header row which contains the filters. It wouldn't work because it'd show up directly above the row before (absolutely positioned relative to parents. Try adding another header row to your codepen to see this. We could try positioning it below the first row by using some js magic but given that row height is variable depending on the length of the label - so this will be a mess.
  4. Now lets say we figure out where to absolutely place these divs. How will you make sure that the length of the input elements do not span the whole table?

If we can solve for above, I'd be very happy to review a PR!

xaksis avatar Aug 30 '18 16:08 xaksis

I'm also experiencing this issue and a scrollbar issue when using the max-height. Not sure if this should be another ticket.

Using the max-height we loose the top arrow scroll button. You can actually see it in action in the documentation and here's a codepen https://codepen.io/cspx99/pen/pONXoO

2018-08-30_14-59-00

ChaStPierre avatar Aug 30 '18 19:08 ChaStPierre

@ChaStPierre this is a windows only issue that happens because the scrollbar occupies actual space there. here's a fix suggested by @manofthefort in an earlier reported ticket.

/* Vue Good Table OVERRIDES */
/* ################################################################# */
table.vgt-table.vgt-fixed-header {
    position: relative !important;
}

table.vgt-table.vgt-fixed-header th:last-child {
    /* Offset for the scrollbar, you may have to adjust this */
    width: calc(100% + 17px) !important;
}

table.vgt-table:not(.vgt-fixed-header) > thead {
    /* Collapse the first row which is the un-fixed table header */
    visibility: collapse !important;
}

xaksis avatar Aug 30 '18 19:08 xaksis

@xaksis Thanks for your detailed feedback! You're right, I tried this solution on a simple use case: no filters row and no sort indicator. By curiosity I will try to solve this issue on a more complex example, but now it looks much harder than I thought 🤔 😄

Maybe it would be interesting to add @manofthefort fix in the documentation?

VictorCazanave avatar Aug 31 '18 02:08 VictorCazanave

Wow, never realized that the OS had an impact on browser rendering. I've tested the workaround in both environments (OSX and Windows and browsers) and get really different results.

Windows - Chrome (68.0.3440.75)

  • fixed scrollbar and column are aligned however, do not resize the browser. Column misalignment's reappear. Windows - IE 11
  • fixed scrollbar and but columns are still misaligned. Resizing browser worsen column alignments Windows Firefox (60.1.0esr)
  • perfect, but don't resize browser. Same issue

OSX - Chrome Chrome (68.0.3440.106)

  • OK however you do not know there's a scrollbar. resizing is OK

OSX - Safari (11.1.2)

  • OK however you do not know there's a scrollbar. resizing is OK
  • FYI, applying the workaround adds an extra blank row just after the header.

Hope this helps!

ChaStPierre avatar Aug 31 '18 15:08 ChaStPierre

@VictorCazanave I haven't added the fix in the documentation because the workaround actually breaks the styles on macs :(

@ChaStPierre thank you for the detailed report. I'll continue looking for a better way to solve this.

xaksis avatar Sep 04 '18 00:09 xaksis

@ChaStPierre @xaksis @VictorCazanave

Here is a solution that will play nicer with window resizing. Add these CSS classes to your project. This uses webkit so Safari should not break (need someone to confirm) and Chrome + Windows works well (tested myself). Really the only issue here is that overlay could lay on top of the column content. If that happens in your case then you can either narrow the scroll bar or increase opacity. Also you could toggle the display with :hover. For the example below I have :hover commented out and simply use opacity which looks decent.

/* Scrollbar */
/* ################################################################# */    
.overlay {
    overflow-y: overlay;
}

.overlay.custom:hover::-webkit-scrollbar {
    /*display: initial;*/
}

.overlay.custom::-webkit-scrollbar {
    display: initial;
}

/* custom webkit scrollbars */
.custom::-webkit-scrollbar {
    width: 15px;
}

.custom::-webkit-scrollbar-track {
    background-color: white;
    border-width: 0;
}

.custom::-webkit-scrollbar-thumb {
    border-radius: 20px;
    background-color: rgba(0, 0, 0, .25);
    border-style: solid;
    border-color: transparent;
    border-width: 3px;
    background-clip: padding-box;
}

/* hidden elements */
.custom::-webkit-scrollbar-button,
.custom::-webkit-scrollbar-track-piece,
.custom::-webkit-scrollbar-corner,
.custom::-webkit-resizer {
    display: none;
}

Apply the .overlay and .custom classes to the div.vgt-responsive element in the mounted function of the component that holds the table.

mounted () {
        let grid = document.querySelector('div.vgt-responsive')

        grid.classList.add('overlay')
        grid.classList.add('custom')
}

Here is a screenshot from my project:

image

Credit of CSS to: http://jsfiddle.net/t4q7o36r/297/

manofthefort avatar Sep 20 '18 13:09 manofthefort

@manofthefort Thanks! I didn't know this property. Unfortunately I think the browsers support is not good enough 😢 However it can be a good workaround for people who only need to support Chrome/Safari.

VictorCazanave avatar Sep 21 '18 02:09 VictorCazanave

@VictorCazanave @ChaStPierre I added a few fixes last night. Can you guys confirm if this resolves some of the issues observed earlier (specially with resizing)? I don't have access to a windows machine and the simulators are all acting up :(

xaksis avatar Oct 12 '18 12:10 xaksis

@xaksis Thanks for still working on it! I'm too busy recently.

Here is how the examples of the documentation look on Windows (10) + Chrome (69):

image 😞

Even with a normal table:

image 😩

Maybe the horizontal scrollbar is only in the doc, I'll try with the code examples later.

VictorCazanave avatar Oct 15 '18 02:10 VictorCazanave

@VictorCazanave oh yea, don't worry about the documentation right now... Vue press adds some classes to table element that I'd need to override to make documentation look good. Have you tried one of the js fiddle examples in windows?

xaksis avatar Oct 15 '18 03:10 xaksis

Sorry for the late reply! Here is how this codepen looks on Windows (10) + Chrome (69):

image

2 headers are visible and the columns are not aligned from beginning 😞

Did you use only CSS for these fixes? Maybe some JS is necessary to calculate the columns size and be MacOS/Windows compatible 🤔

VictorCazanave avatar Oct 18 '18 02:10 VictorCazanave

@xaksis I updated this codepen to fix some issues you mentionned in your 1rst comment (there are still problems). I had to add some JS to calculate the width of the scrollbar and set the width of the columns. I agree it's not ideal and I would prefer to have a CSS solution but I think it's impossible 😢 The JS isn't very complicated, so maybe something similar could be added to your last fixes.

VictorCazanave avatar Oct 22 '18 02:10 VictorCazanave

Not sure if this works in your situation but perhaps some css styles could be a useful solution. Applying the solution here seems to show promise: stackoverflow

.vgt-table{ 
  overflow-y: auto; height: 100px; 
}
.vgt-table th { 
  position: sticky; top: 0; 
}

See fiddle example.

cmcleese avatar Nov 20 '18 14:11 cmcleese

Unfortunately position: sticky is not well supported 😢

VictorCazanave avatar Nov 26 '18 02:11 VictorCazanave

I got around and fixed the css width, from 100% to 99.4%

.vgt-fixed-header{position:absolute;z-index:10;width:100%;overflow-x:auto}

for:

.vgt-fixed-header{position:absolute;z-index:10;width:99.4%;overflow-x:auto}

amchconsult avatar Dec 09 '19 14:12 amchconsult

I ran into this issue in Chrome on Linux as well. Any workarounds?

aatishnn avatar Jul 17 '20 03:07 aatishnn

I would like to turn on fixed headers and max height, but I have quite a lot of rows in the table and have enabled the sorting field, which causes the vertical scroll bar not be shown at all in the topmost position. Vue good table version 2.21.10, browser is Windows Chrome. Is there a stable fix for this issue?

pkovanen avatar Apr 29 '21 05:04 pkovanen

i know my comment wouldn't be related to this issue at 100%, but may it helps, i was Vue3 and i wanted the overflow to be visible (i had a dropdown) so

onMounted(() => {
  ....
  let table: any = document.querySelector('div.vgt-responsive')
  table.style.overflowX = 'visible'
})

i tried to target it with css selectors & scoped, it didn't work so :/

benounnas avatar Jul 31 '22 09:07 benounnas

I had the same issue and tried several solutions mentioned above. Finally this worked for me: .vgt-table:not(.vgt-fixed-header){ position:relative; z-index:15; overflow-x:auto; }

emirrozerr avatar Jan 30 '23 13:01 emirrozerr

Happy to report that using position: sticky as recommended by @cmcleese works great!

Let me know if anybody else gets this working, or if it is a fluke with my setup.

<template>
    <vue-good-table 
      max-height="500px"
      :fixed-header="false"  <!-- note this is false -->
    />
</template>

<style>
/** 
  Applying `border-collapse: separate` on the table container prevents the first 
  table header row's border from being applied elsewhere when it is sticky.
*/
.vgt-table {
  border-collapse: separate !important;
  border-spacing: 0;
  border-top: 0 !important;
}

/**
    Applying `position: sticky` here to make it sticky.
*/
.vgt-table thead {
  position: sticky
  top: 0
}

/**
    We removed the top border from .vgt-table to apply it here instead
*/
.vgt-table thead tr:first-child th {
  border-top: 1px solid #dcdfe6 !important
}

/**
    Applying `border-collapse: separate` doubled the cell border width visually.
    Setting this to a fractional value fixed the issue.
*/
.vgt-table th, .vgt-table td {
  border-width: .5px !important
}
</style>

References: https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element

cwilby avatar Mar 10 '23 21:03 cwilby

this work, when using tailwind

.vgt-table thead {
    @apply bg-base-100 relative z-20;
}

.vgt-table tbody {
    @apply relative z-10;
}

aacassandra avatar Jun 03 '23 17:06 aacassandra