Bootstrap 4 responsive tables won't take up 100% width - css

I am building a web app using Bootstrap 4 and running into some weird issues. I want to utilize Bootstrap's table-responsive class to allow horizontal scrolling of the tables on mobile devices. On desktop devices the table should take up 100% of the containing DIV's width.
As soon as I apply the .table-responsive class to my table, the table shrinks horizontally and no longer takes up 100% of the width. Any ideas?
Here is my markup:
<!DOCTYPE html>
<html lang="en" class="mdl-js">
<head>
<title></title>
<meta charset="utf-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="application-name" content="">
<meta name="theme-color" content="#000000">
<link rel="stylesheet" href="/css/bundle.min.css">
</head>
<body>
<div class="container-fluid no-padding">
<div class="row">
<div class="col-md-12">
<table class="table table-responsive" id="Queue">
<thead>
<tr>
<th><span span="sr-only">Priority</span></th>
<th>Origin</th>
<th>Destination</th>
<th>Mode</th>
<th>Date</th>
<th><span span="sr-only">Action</span></th>
</tr>
</thead>
<tbody>
<tr class="trip-container" id="row-6681470c-91ce-eb96-c9be-8e89ca941e9d" data-id="6681470c-91ce-eb96-c9be-8e89ca941e9d">
<td>0</td>
<td>PHOENIX, AZ</td>
<td>SAN DIEGO, CA</td>
<td>DRIVING</td>
<td><time datetime="2017-01-15T13:59">2017-01-15 13:59:00</time></td>
<td><span class="trip-status-toggle fa fa-stop" data-id="6681470c-91ce-eb96-c9be-8e89ca941e9d" data-trip-status="1"></span></td>
</tr>
<tr class="steps-container" data-steps-for="6681470c-91ce-eb96-c9be-8e89ca941e9d" style="display: none;">
<td colspan="6" class="no-padding"></td>
</tr>
</tbody>
</table>
</div>
</div>
<br>
</div>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="/js/bundle.min.js"></script>
</body>
</html>
If I apply a 100% width to the .table-responsive class, it makes the table itself a 100% wide but the child elements (TBODY, TR, etc.) are still narrow.

The following WON'T WORK. It causes another issue. It will now do the 100% width but it won't be responsive on smaller devices:
.table-responsive {
display: table;
}
All these answers introduced another problem by recommending display: table;. The only solution as of right now is to use it as a wrapper:
<div class="table-responsive">
<table class="table">
...
</table>
</div>

This solution worked for me:
just add another class into your table element:
w-100 d-block d-md-table
so it would be :
<table class="table table-responsive w-100 d-block d-md-table">
for bootstrap 4 w-100 set the width to 100% d-block (display: block) and d-md-table (display: table on min-width: 576px)
Bootstrap 4 display docs

If you're using V4.1, and according to their docs, don't assign .table-responsive directly to the table. The table should be .table and if you want it to be horizontally scrollable (responsive) add it inside a .table-responsive container (a <div>, for instance).
Responsive tables allow tables to be scrolled horizontally with ease. Make any table responsive across all viewports by wrapping a .table with .table-responsive.
<div class="table-responsive">
<table class="table">
...
</table>
</div>
doing that, no extra css is needed.
In the OP's code, .table-responsive can be used alongside with the .col-md-12 on the outside .

None of these answers are working (date today 9th Dec 2018). The correct resolution here is to add .table-responsive-sm to your table:
<table class='table table-responsive-sm'>
[Your table]
</table>
This applies the responsiveness aspect only to the SM view (mobile). So in mobile view you get the scrolling as desired and in larger views the table is not responsive and thus displayed full width, as desired.
Docs: https://getbootstrap.com/docs/4.0/content/tables/#breakpoint-specific

Create responsive tables by wrapping any .table with
.table-responsive{-sm|-md|-lg|-xl}, making the table scroll
horizontally at each max-width breakpoint of up to (but not including)
576px, 768px, 992px, and 1120px, respectively.
just wrap table with .table-responsive{-sm|-md|-lg|-xl}
for example
<div class="table-responsive-md">
<table class="table">
</table>
</div>
bootstrap 4 tables

For some reason the responsive table in particular doesn't behave as it should. You can patch it by getting rid of display:block;
.table-responsive {
display: table;
}
I may file a bug report.
Edit:
It is an existing bug.

The solution compliant with the v4 of the framework is to set the proper breakpoint. Rather than using .table-responsive, you should be able to use .table-responsive-sm (to be just responsive on small devices)
You can use any of the available endpoints: table-responsive{-sm|-md|-lg|-xl}

That's because the .table-responsive class adds the property display: block to your element which changes it from the previous display: table.
Override this property back to display: table in your own stylesheet
.table-responsive {
display: table;
}
Note: make sure this style executes after your bootstrap code for it to override.

It's caused by the table-responsive class giving the table a property of display:block, which is strange because this overwrites the table classes original display:table and is why the table shrinks when you add table-responsive.
Most likely its down to bootstrap 4 still being in dev. You are safe to overwrite this property with your own class that sets display:table and it won't effect the responsiveness of the table.
e.g.
.table-responsive-fix{
display:table;
}

Taking in consideration the other answers I would do something like this, thanks!
.table-responsive {
#include media-breakpoint-up(md) {
display: table;
}
}

I found that using the recommended table-responsive class in a wrapper still causes responsive tables to (surprisingly) shrink horizontally:
<div class="table-responsive-lg">
<table class="table">
...
</table>
</div>
The solution for me was to create the following media breakpoints and classes to prevent it:
.table-xs {
width:544px;
}
.table-sm {
width: 576px;
}
.table-md {
width: 768px;
}
.table-lg {
width: 992px;
}
.table-xl {
width: 1200px;
}
/* Small devices (landscape phones, 544px and up) */
#media (min-width: 576px) {
.table-sm {
width: 100%;
}
}
/* Medium devices (tablets, 768px and up) The navbar toggle appears at this breakpoint */
#media (min-width: 768px) {
.table-sm {
width: 100%;
}
.table-md {
width: 100%;
}
}
/* Large devices (desktops, 992px and up) */
#media (min-width: 992px) {
.table-sm {
width: 100%;
}
.table-md {
width: 100%;
}
.table-lg {
width: 100%;
}
}
/* Extra large devices (large desktops, 1200px and up) */
#media (min-width: 1200px) {
.table-sm {
width: 100%;
}
.table-md {
width: 100%;
}
.table-lg {
width: 100%;
}
.table-xl {
width: 100%;
}
}
Then I can add the appropriate class to my table element. For example:
<div class="table-responsive-lg">
<table class="table table-lg">
...
</table>
</div>
Here the wrapper sets the width to 100% for large and greater per Bootstrap. With the table-lg class applied to the table element, the table width is set also set to 100% for large and greater, but set to 992px for medium and smaller. The classes table-xs, table-sm, table-md, and table-xl work the same way.

Not sure if helps, but wrap your table responsive in a div and add .responsive-table class to both:
table.table-responsive{
display: block;
overflow: scroll;
}
.table-responsive {
overflow: hidden;
padding: 0px;
margin: 0px;
table-layout: fixed;
width: 100%;
display: table;
}
This gives a 100% expanded surrounding div which scales with the column width, whilst then making the actual table scrollable. The solutions above wouldn't work if I had a side column on the page, as they assume 100% width.

For Bootstrap 4.x use display utilities:
w-100 d-print-block d-print-table
Usage:
<table class="table w-100 d-print-block d-print-table">

It seems as though the "sr-only" element and its styles inside of the table are what's causing this bug. At least I had the same issue and after months of banging our head against the wall that's what we determined the cause was, though I still don't understand why. Adding left:0 to the "sr-only" styles fixed it.

Related

Problems displaying a table on mobile version of my site

I've been trying to fix this issue for 10 days now and still i couldn't find any solution.
I have a table that shows perfectly on desktop version but on mobile it gets out of the page area, i tried also #media screen max width 600px to modify the size of the table and overflow hidden but still not working, i will paste the code below:
<style type="text/css">
table {
border-collapse: collapse;
width: 100%;
}
td {
border: 1px solid #d3d3d3;
text-align: center;
white-space: nowrap;
}
th {
background-color: #0288D1;
border: 2px solid #d3d3d3;
text-align: center;
font-size: large;
color: white;
text-transform: uppercase;
}
</style>
<table>
<thead>
<tr>
<th colspan="4" style="background-color:#0277BD"><strong>Some Text Here<strong></th></tr>
<tr>
<th><strong>Some Text Here</strong></th>
<th><strong>Some Text Here</strong></th>
<th><strong>Some Text Here</strong></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a rel="nofollow" target="_blank" href="https://somesite.com/play"><img width="200" height="80" src="https://somesite.com/image.png" alt="Some Text Here"></a>
</td>
<td><strong><font color="green">Some Text Here</font></strong></td>
<td>Some Text Here</td>
<td>
<div>
<button class="playblock" style="display:block;width:150px;height:50px;background-color:#4CAF50;margin-bottom:5px;color:white;font-size:20px;cursor:pointer;text-align:center;" onmouseover="this.style.backgroundColor='green'" onMouseOut="this.style.backgroundColor='#4CAF50'" onclick="window.location.href = 'https://somesitehere.com/play';">PLAY</button>
</div>
<div>
<button class="reviewblock" style="display:block;width:150px;height:50px;background-color:#EB9C12;color:white;font-size:20px;cursor:pointer;text-align:center;" onmouseover="this.style.backgroundColor='orange'" onMouseOut="this.style.backgroundColor='#EB9C12'" onclick="window.location.href = 'https://somesitehere.com/see/';">REVIEW</button>
</div>
</td>
</tr>
This is a common problem with tables on mobile. It is not clear if you are using the table for layout or if you will have more rows of data with Play and Review links.
If you are using it for layout, I would suggest exploring a flexbox layout instead.
If you are planning to have more rows in the table you could wrap the table in a <div> with max-width: 100%; overflow: auto; that would allow the div/table to horizontally scroll but not otherwise affect the layout of the page. Pair this with reduced font-size on smaller screens and, IMO, you get a pretty usable table on mobile.
There are a few methods for modifying how a table is rendered on small screens by using a data attribute (like data-title) on the <td> and <th> that duplicate the column heading so that on small screens you can pull the data attribute using a ::before pseudo element like td::before { content: attr(data-title); } and tell your table elements to all be display: block; and styling them kinda like each row is it's own table.
Here is an example from CSS Tricks: https://css-tricks.com/responsive-data-tables/
You have to decide what it should look like on mobile. The simple fix is to set a min-width on the table but this might make things to small on mobile. You should also be using a media query to make the buttons smaller, they are very large.
table { min-width: 500px; }
Add a container element with overflow-x:auto around the <table>, for example:
<div style="overflow-x:auto;">
<table>
...
</table>
</div>
This table will display a horizontal scroll bar if the screen is too small to display the full content.
Thanks for all your feedback.
I fixed it myself after some testing using:
#media only screen and (max-width: 800px) { ... }

Boostrap responsive table is not responsive inside a "table"

I have a responsive table inside the div that display as table
Example code:
<div class="mytable">
<div class="mycolumn">
<div class="table-responsive">
<table class="table table-bordered">
.....
</table>
</div>
</div>
</div>
<style>
.mytable{
display: table;
width: 90%;
border: 1px solid red;
}
.mycolumn{
display: table-cell;
}
</style>
http://jsfiddle.net/6L6owp7x/
The problem is that the responsive table is not responsive at all when inside the "table" div. How can I get it to be responsive?
One of the quickest ways is to set the td,th { width: 1%} I don't think you are looking for a responsive table inside i think you want a justified table which there are some how tos out there how to do that. Remember bootstrap is setting widths on these at certain break points so the smaller breakpoints won't respond on this without media queries.
I had the same problem. I tried table-responsive class of bootstrap and it worked Here's an example
https://mdbootstrap.com/docs/jquery/tables/responsive/

div with 100% width inside div with 90% width doesn't work

I made an image slider for my forum homepage but the content is comming out of the wrapper.
How can I make sure the content will always be 100% width of the wrapper?
HTML:
<div id="wrapper">
<table>
<tbody>
<tr>
<td>
<div class="rg-content">
//image slider code
</div>
</td>
</tr>
</tbody>
</table>
</div>
CSS:
#wrapper {
margin: 0 auto;
max-width: 980px;
width: 90%;
background: linear-gradient(#fefefe, #e7e7e7);
}
.rg-content {
width: 100%;
background: #101010;
}
Screenshot:
What's Going On
It looks like your #wrapper doesn't have overflow set to hidden. Personally I tend to stay away from tables and use either float'd block elements or inline-block elements. I recently built a slider using figure for the outside wrap, ul for the fixed width inner wrap, and lis for each item. I had to set the figure to overflow:hidden for it to hide everything that wasn't supposed to be visible. Try adding that.
Code
#wrapper {
overflow:hidden;
}
Just add
<table style="width:100%;">
http://jsfiddle.net/jzLN6/
EDIT:
according to your jsfinddle and your comments I made some modifications to get this result
http://jsfiddle.net/bB9tQ/4/embedded/result/
is not fully functional but maybe its a basic idea of what you want to do
so if you want the layout to be fluid you will have to do some changes
remove de px of your ul and change your display to inline-block because if you have
display: block
this will make your li elements to lose the normal flow on the page and you won't be able to use % to stretch the content
<ul style="width: 100%; display: inline-block; margin-left: ;">
after that you should use % on each li tag instead of px.
if this is an approach to what you need, please let me know to give you a better elaborated example

How do I get rid of this horizontal scrollbar in Chrome and Safari?

How do i get rid of the horizontal scrollbar on this code: codepen? I'm seeing it in Safari and Chrome, but not Firefox.
I'm using bootstrap, and I've got roughly the following markup:
<div class="container">
<div class="row">
<div class="messages span6 offset1">
<table class="table">
<tbody>
<tr>
<td class=timestamp>[2:22 PM]</td>
<td>echo|</td>
<td>zot: Got a paste or gist of the code?</td>
</tr>
<!-- many more rows… -->
</tbody>
</table>
</div>
</div>
</div>
And styling:
.messages {
height: 200px;
overflow: auto;
}
.messages .timestamp {
min-width: 75px;
}
The problem seems to be the min-width constraint, but I need that to keep the first column from wrapping. I also need to limit the height of messages to 200 pixels. I can't set overflow-x: hidden on .messages because it'll cut off content.
How about this:-
Use word-break on the last column to avoid it cut off.
word-break
Demo
.messages {
height: 200px;
overflow-y: auto;
}
.messages .timestamp {
min-width: 75px;
}
.messages td:nth-child(3) {
word-break:break-all; /* or use word-break:normal; if you don't want to get the word cut in between*/
}
This will adjust the word-break based on the width available, without hiding the contents.
Use the following css:
.messages {
height: 200px;
overflow-y: scroll;
overflow-x: hidden;
}
.messages .timestamp {
min-width: 75px;
}
You could change the height property for .messages to "auto" instead of 200px.
You could increase the width of the table by changing its span6 to a span7, or use a span class to force a width on the message tds that is consistent with the Twitter bootstrap grid structure context.
I couldn't tell you exactly why this is necessary; I actually don't know much about how tables get laid out. But this seems like a solution you could deploy.
A completely alternate thought: why are you using tables to do this? You're not laying out tabular data; you have some semantically related pieces, but they're not tabular in their relationship. Given that, you're breaking one of the cardinal rules: don't use tables for layout! It looks to me like you could probably make this work much more sensibly using div elements, using either float or inline-block with specified widths on them. In that case, your markup would look something like this:
<div class="container">
<div class="row">
<div class="messages span6 offset1">
<div class="message">
<span class="timestamp">[2:22 PM]</div>
<span class="author">echo|</div>
<span class="messageContent">zot: Got a paste or gist of the code?</div>
</div>
<!-- many more rows… -->
</div>
</div>
</div>
Then, your CSS would be fairly straightforward, since you've defined the width value for the span6 (I looked at the actual CSS on the CodePen):
.message {
display: block;
clear: both;
}
.timestamp, .author, .messageContent {
display: inline-block;
vertical-align: top;
}
.timestamp, .author {
width: 75px;
}
.messageContent {
400px; /* You'd obviously need to tweak this down to account for any padding */
}
You shouldn't have the nasty overflow problems, and the divs should fill up their heights in perfectly normal ways. You can also bound them. And there's no overflow issue anymore.
(Perhaps you're where you are because it's something that bootstrap defaults to, in which case: UGH. Break it, or do whatever is necessary to get away from using tables for layout. It will always, always be more pain than it's worth, and it's unsemantic to boot.)

Modern way to markup 100% height layout in HTML5 and CSS3

I've been away from marking up sites for some time. So, now we have HTML5 and a lot of new features in CSS. I have a common site layout with fixed size header and footer. And of course main content area in between. By default page should take 100% of window height (i.e. content area expands). And if content is long page vertical scrollbar appears and all like usual.
Usually I used to do it by something like this:
<body>
<table id="main" ...>
<tr>
<td id="header-and-content">
<div id="header">contains logo, nav and has fixed height</div>
<div id="content">actual content</div>
</td>
</tr>
<tr>
<td id="footer">
fixed size footer
</td>
</tr>
</table>
</body>
And accompanying css:
html, body { height:100% }
table#main { height:100% }
td#footer { height:123px }
So, it's obsolete. You, who keeps abreast of new markup techniques, how it is done by now in 2011?
UPD People, issue not about semantic markup or using divs. I know what it does mean. Issue now in - how do I tell footer to stay at bottom even while content is empty or short. When content is long enough footer just go down as it would do in other case. Absolute and fixed is not the solution (at least at its basic form)
SOME SUMMARY UPDATE
I've tried method with usage of display:table and display:table-row and it works: little content, more content
Method Make the Footer Stick to the Bottom of a Page was adviced by Andrej. It works also: little content, more content
Some disappointment though I feel: first method is just those tables but without table tag. The second is really old, I've avoided to use it because it resembles hack. My god, nothing new :)
Well, first of all in 2011 we dont use tables for layout anymore!
If I were you, I would write the markup like so:
<body>
<div id="main" role="main">
<header>
contains logo, nav and has fixed height
</header>
<div class="content"> /*use <article> or <section> if it is appropriate - if not sure what to use, use a div*/
actual content
</div>
<footer>
fixed size footer
</footer>
</div>
</body>
And the CSS would be the same except the changed selectors
html, body { height:100% }
#main { height:100% }
footer { height:123px }
For a fixed footer, I would suggest to use position:absolute or maybe position:fixed - it depends how you want it to behave (scroll with page or always stay at bottom).
To make a "sticky" footer, that will be at the bottom of the page but move with the content, this method will do the trick.
In 2013 there is still nothing that beats a decent table that has respectively thead/tfoot/tbody.
The below (valid HTML5 page) is a fixed header and footer, 100% height and NOT ANY resize trouble.
<!DOCTYPE html>
<meta charset="utf-8" />
<title>valid HTML5 / fixed header and footer / nada CSS sizing trouble</title>
<style type="text/css">
html, body, table { height: 100% }
th { height: 80px }
#f { height: 40px }
table { width: 1000px }
html, body { margin: 0 }
table { margin: 0 auto }
td { text-align: left }
html, body { text-align: center } /* important for old browsers */
th { text-align: right }
html, body { background-color: rgb(148,0,211) }
#m { background-color: #f39 }
#m { -webkit-border-radius: 25px;
-khtml-border-radius: 25px;
-moz-border-radius: 25px;
-ms-border-radius: 25px;
-o-border-radius: 25px;
border-radius: 25px; }
</style>
<table>
<thead><tr><th> head</th></tr></thead>
<tfoot><tr><td id="f">foot</td></tr></tfoot>
<tbody><tr><td id="m">main</td></tr></tbody>
</table>
As you asked for "modern"... anno 2016 I have maybe a better answer than in 2013:
use the 100vh solution in CSS3. vh is a new unit and stands for ViewPort height.
html, body { height: 100% }
header { height: 100px }
footer { height: 50px }
main { height: calc(100vh - 150px); }
html, body { width: 100% }
header, main, footer { width: 1000px }
html, body { margin: 0 }
header, main, footer { margin: 0 auto }
html, body { padding: 0 }
html, body { text-align: center }
body { background-color: white }
header { background-color: yellow }
main { background-color: orange }
footer { background-color: red }
<!DOCTYPE html>
<meta charset="utf-8" />
<title>test</title>
<header>bla</header>
<main>bla</main>
<footer>bla</footer>
But if you wish to be compatible with old browsers, use the code in my 2013 answer.
Today, you would do like this (not much different really)
http://jsfiddle.net/5YHX7/3/
html, body { height: 100%; width: 100%; margin: 0; }
div { height: 100%; width: 100%; background: #F52887; }
and
<html><body><div></div></body></html>
Technically you could probably still get away with laying out your page with table tags but it is now considered bad practice. It is considered good practice to use "semantic" web markup which means using tags for their intended purposes so a table tag should be used to represent table data and not invisible design. DIVs are intended for use designing your invisible page layout. A list apart is a great website resource for understanding these concepts.
This article is good for understanding semantic markup: http://www.alistapart.com/articles/12lessonsCSSandstandards
So all that said, here is a sample page that does what you want:
http://peterned.home.xs4all.nl/examples/csslayout1.html
As asking for "modern" AND "compatible" is a contraction anyway, the grid method wasn't mentioned so far, and maybe is too modern right now, but with some adaptions might be a solution.
This article (and pointers) -with more complex use- is great to read:
https://developers.google.com/web/updates/2017/01/css-grid
Now the code looks nice, however browsers don't... - so I added some forcing.
https://jsfiddle.net/qLcjg6L6/1/
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
height: 100%;
min-height: 100vh;
margin: 0;
padding: 0 }
body { display: grid;
grid-template-rows: minmax(auto, min-content) auto minmax(auto, min-content);
grid-template-columns: 100% }
header { background: red }
main { background: pink }
footer { background: purple }
/* as this code is yet far from well-supported, here's a brute force... */
header { height: 70px }
footer { height: 60px }
main { height: calc(100vh - 130px); }
/* 130px being the sum of header/footer - adapt to your desired size/unit */
</style>
</head>
<body>
<header>hdr</header>
<main>main</main>
<footer>foot</footer>
</body>
</html>
Let me add my contribution by adding 3 columns to your header / main / footer layout:
http://jsfiddle.net/ESrG9/
<!DOCTYPE html>
<table>
<thead>
<tr id="header">
<th colspan="3">head</th>
</tr>
</thead>
<tbody>
<tr>
<td id="left">main</td>
<td id="main">main</td>
<td id="right">main</td>
</tr>
</tbody>
<tfoot>
<tr>
<td id="footer" colspan="3">foot</td>
</tr>
</tfoot>
</table>
So far nobody mentioned the flex-box method
https://jsfiddle.net/55r7n9or/
<!DOCTYPE html>
<html>
<head>
<style>
html, body, div {
height: 100%;
margin: 0;
padding: 0 }
div { display: flex;
flex-direction: column }
main { flex: 1 }
header { background: red }
main { background: pink }
footer { background: purple }
</style>
</head>
<body>
<div>
<header>hdr</header>
<main>main</main>
<footer>foot</footer>
</div>
</body>
</html>

Resources