// --- General styling --- .table.b-table { // Table fixed header width layout &.b-table-fixed { // Fixed width columns table-layout: fixed; } // Disabled border-collapse // Mainly for use with sticky headers and columns &.b-table-no-border-collapse { border-collapse: separate; border-spacing: 0; } // Table busy styling &[aria-busy="true"] { opacity: $b-table-busy-opacity; } // Details row styling > tbody > tr.b-table-details > td { border-top: none !important; } // Caption positioning > caption { caption-side: bottom; } &.b-table-caption-top { > caption { caption-side: top !important; } } // Re-declare `table-active` class here so that it can take // precedence over row variants when used on selectable rows // Class can only be applied to rows and not individual cells > tbody > .table-active { &, > th, > td { background-color: $table-active-bg; } } // Add special hover styling for `table-active` row variant &.table-hover > tbody > tr.table-active:hover { td, th { color: $table-hover-color; // `$table-hover-bg` default is a very transparent black // We overlay it over the background color to achieve the // same color effect while keeping the background solid background-image: linear-gradient($table-hover-bg, $table-hover-bg); background-repeat: no-repeat; } } // Add in missing `bg-active` class for table tbody rows // Bootstrap v4.3 is missing this for dark tables // `bg-active` class cannot be applied to individual cells > tbody > .bg-active { &, > th, > td { // Important is needed to override the standard `bg-variants` // as the also use `!important` background-color: $table-dark-active-bg !important; } } // Add special hover styling for `bg-active` row variant (dark tables) &.table-hover.table-dark > tbody > tr.bg-active:hover { td, th { color: $table-dark-hover-color; // `$table-dark-hover-bg` default is a very transparent white // We overlay it over the background color to achieve the // same color effect while keeping the background solid background-image: linear-gradient($table-dark-hover-bg, $table-dark-hover-bg); background-repeat: no-repeat; } } } // --- Table sticky header styling --- @if $bv-enable-table-sticky { .b-table-sticky-header, .table-responsive, [class*="table-responsive-"] { // Move the table bottom margin to the wrapper margin-bottom: $spacer; > .table { // Reset `margin-bottom` to we don't get a space after // the table inside the scroll area margin-bottom: 0; } } .b-table-sticky-header { overflow-y: auto; // Annoyingly, when overflow-y is set, browsers convert // 'overflow-x: visible' to 'overflow-x: auto' - so it becomes // responsive in the x axis automatically // Default `max-height` before a scrollbar will show // We don't use `height` as table could be shorter than this value max-height: $b-table-sticky-header-max-height; } @media print { // Override any styles (including inline styles) // when printing .b-table-sticky-header { overflow-y: visible !important; max-height: none !important; } } @supports (position: sticky) { // Positioning of sticky headers .b-table-sticky-header > .table.b-table > thead > tr > th { // Header cells need to be sticky on top position: sticky; top: 0; z-index: 2; } // Positioning of sticky columns // Sticky columns only work when table has sticky // headers and/or is responsive .b-table-sticky-header, .table-responsive, [class*="table-responsive-"] { > .table.b-table { > thead, > tbody, > tfoot { > tr > .b-table-sticky-column { position: sticky; left: 0; } } > thead { > tr > .b-table-sticky-column { // z-index needs to be higher than sticky columns and // sticky headers for correct layering z-index: 5; } } > tbody, > tfoot { > tr > .b-table-sticky-column { // z-index needs to be lower than sticky header that // is also a sticky column z-index: 2; } } } } // Default theme color background for table cells that are sticky // Applied only when no variant is applied to the rows, or no head-variant // Needed because Bootstrap v4 does not have table child elements set up // to inherit their background color from parent element by default // // An issue made at twbs/bootstrap repo for table // background color inheritance: // https://github.com/twbs/bootstrap/issues/29244 // If implemented, would negate the need for all the below SCSS .table.b-table { > thead, > tbody, > tfoot { > tr > .table-b-table-default { // Default cell color color: $table-color; // `$table-bg` is null by default in Bootstrap v4 variables // but could have a value set by the consumer background-color: if($table-bg, $table-bg, $body-bg); } } &.table-dark { > thead, > tbody, > tfoot { > tr > .bg-b-table-default { // Default cell color in table dark mode color: $table-dark-color; // Default cell background color in table dark mode background-color: $table-dark-bg; } } } // Handle case of zebra striping &.table-striped { // "fake" zebra striping via use of a transparent background image > tbody > tr:nth-of-type(#{$table-striped-order}) > .table-b-table-default { // `$table-accent-bg` (used for striping) default is a very transparent black // We overlay it over the background color to achieve the same color // effect while keeping the background solid. background-image: linear-gradient($table-accent-bg, $table-accent-bg); background-repeat: no-repeat; } &.table-dark { > tbody > tr:nth-of-type(#{$table-striped-order}) > .bg-b-table-default { // `$table-dark-accent-bg` (used for striping) default is a very transparent white // We overlay it over the background color to achieve the same color // effect while keeping the background solid. background-image: linear-gradient($table-dark-accent-bg, $table-dark-accent-bg); background-repeat: no-repeat; } } } // Handle case of hover &.table-hover { // "fake" hover via use of a transparent background image > tbody > tr:hover > .table-b-table-default { color: $table-hover-color; // `$table-hover-bg` default is a very transparent black // We overlay it over the background color to achieve the same color // effect while keeping the background solid. background-image: linear-gradient($table-hover-bg, $table-hover-bg); background-repeat: no-repeat; } &.table-dark { > tbody > tr:hover > .bg-b-table-default { color: $table-dark-hover-color; // `$table-dark-hover-bg` default is a very transparent white // We overlay it over the background color to achieve the same color // effect while keeping the background solid. background-image: linear-gradient($table-dark-hover-bg, $table-dark-hover-bg); background-repeat: no-repeat; } } } } } } // --- Header sort styling --- // Bootstrap v4.4 will include this variable as `$escaped-characters` // But if we want to preserve backwards compatibility with v4.3, we leave this in $bv-escaped-characters: (("<", "%3c"), (">", "%3e"), ("#", "%23")); // Bootstrap v4.4 will include this method as `escape-svg` // But if we want to preserve backwards compatibility with v4.3, we leave this in // See https://codepen.io/kevinweber/pen/dXWoRw @function bv-escape-svg($string) { @if str-index($string, "data:image/svg+xml") { @each $char, $encoded in $bv-escaped-characters { $string: str-replace($string, $char, $encoded); } } @return $string; } .table.b-table { > thead, > tfoot { > tr { > [aria-sort] { cursor: pointer; background-image: none; background-repeat: no-repeat; background-size: $b-table-sort-icon-bg-width $b-table-sort-icon-bg-height; &:not(.b-table-sort-icon-left) { // Default is icon on the right background-position: right calc(#{$table-cell-padding} / 2) center; padding-right: calc(#{$table-cell-padding} + #{$b-table-sort-icon-bg-width}); } &.b-table-sort-icon-left { // Left aligned sort icon background-position: left calc(#{$table-cell-padding} / 2) center; padding-left: calc(#{$table-cell-padding} + #{$b-table-sort-icon-bg-width}); } } > [aria-sort="none"] { background-image: bv-escape-svg($b-table-sort-icon-bg-not-sorted); } > [aria-sort="ascending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-ascending); } > [aria-sort="descending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-descending); } } } // Sort icons for dark tables, headers, footers &.table-dark > thead > tr, &.table-dark > tfoot > tr, > .thead-dark > tr { > [aria-sort="none"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-not-sorted); } > [aria-sort="ascending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-ascending); } > [aria-sort="descending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-descending); } } // Sort icons when header cell has `table-dark` class > thead > tr > .table-dark, > tfoot > tr > .table-dark { &[aria-sort="none"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-not-sorted); } &[aria-sort="ascending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-ascending); } &[aria-sort="descending"] { background-image: bv-escape-svg($b-table-sort-icon-bg-dark-descending); } } // Padding and position adjustment for small tables &.table-sm { > thead, > tfoot { > tr > [aria-sort] { &:not(.b-table-sort-icon-left) { // Default is icon on the right background-position: right calc(#{$table-cell-padding-sm} / 2) center; padding-right: calc(#{$table-cell-padding-sm} + #{$b-table-sort-icon-bg-width}); } &.b-table-sort-icon-left { // Left aligned sort icon background-position: left calc(#{$table-cell-padding-sm} / 2) center; padding-left: calc(#{$table-cell-padding-sm} + #{$b-table-sort-icon-bg-width}); } } } } } // --- Selectable rows --- .table.b-table { &.b-table-selectable:not(.b-table-selectable-no-click) { & > tbody > tr { cursor: pointer; } &.b-table-selecting { // Disabled text-selection when in range mode when // at least one row selected &.b-table-select-range > tbody > tr { user-select: none; } } } } // --- Stacked tables --- @if $bv-enable-table-stacked { .table.b-table { &.b-table-stacked { @each $breakpoint in map-keys($grid-breakpoints) { $next: breakpoint-next($breakpoint, $grid-breakpoints); $infix: breakpoint-infix($next, $grid-breakpoints); &#{$infix} { @include media-breakpoint-down($breakpoint) { display: block; width: 100%; // Convert to blocks when stacked > caption, > tbody, > tbody > tr, > tbody > tr > td, > tbody > tr > th { display: block; } // Hide when stacked > thead, > tfoot { display: none; > tr.b-table-top-row, > tr.b-table-bottom-row { display: none; } } // Caption positioning > caption { caption-side: top !important; } > tbody { > tr { // Turn cells with labels into micro-grids > [data-label] { // Cell header label pseudo element &::before { content: attr(data-label); width: $b-table-stacked-heading-width; float: left; text-align: right; overflow-wrap: break-word; font-weight: bold; font-style: normal; padding: 0 calc(#{$b-table-stacked-gap} / 2) 0 0; margin: 0; } // Add clearfix in-case field label wraps &::after { display: block; clear: both; content: ""; } // Cell value (we wrap the cell value in a div when stacked) > div { display: inline-block; width: calc(100% - #{$b-table-stacked-heading-width}); // Add "gap" between "cells" padding: 0 0 0 calc(#{$b-table-stacked-gap} / 2); margin: 0; } } // Dont show the fixed top/bottom rows &.top-row, &.bottom-row { display: none; } // Give the top cell of each "row" a heavy border > :first-child { border-top-width: (3 * $table-border-width); } // Give any cell after a rowspan'ed cell a heavy top border > [rowspan] + td, > [rowspan] + th { border-top-width: (3 * $table-border-width); } } } } } } } } }