xaksis / vue-good-table

An easy to use powerful data table for vuejs with advanced customizations including sorting, column filtering, pagination, grouping etc
https://xaksis.github.io/vue-good-table/
MIT License
2.16k stars 405 forks source link

Improve fixed header #373

Open VictorCazanave opened 6 years ago

VictorCazanave commented 6 years ago

Issue Type

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.

thenightex commented 6 years ago

+1

xaksis commented 6 years ago

@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!

ChaStPierre commented 6 years ago

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

xaksis commented 6 years ago

@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;
}
VictorCazanave commented 6 years ago

@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?

ChaStPierre commented 6 years ago

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)

OSX - Chrome Chrome (68.0.3440.106)

OSX - Safari (11.1.2)

Hope this helps!

xaksis commented 6 years ago

@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.

manofthefort commented 6 years ago

@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/

VictorCazanave commented 6 years ago

@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.

xaksis commented 5 years ago

@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 :(

VictorCazanave commented 5 years ago

@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.

xaksis commented 5 years ago

@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?

VictorCazanave commented 5 years ago

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 commented 5 years ago

@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.

cmcleese commented 5 years ago

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.

VictorCazanave commented 5 years ago

Unfortunately position: sticky is not well supported 😢

amchconsult commented 4 years ago

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}

aatishnn commented 4 years ago

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

pkovanen commented 3 years ago

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?

benounnas commented 2 years ago

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 :/

emirrozerr commented 1 year ago

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; }

cwilby commented 1 year ago

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

aacassandra commented 1 year ago

this work, when using tailwind

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

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