I have a table with two columns. I want the first column to be scrollable, so that my table can stay at a fixed height and not expand continuously. I only want it to be scrollable vertically though: Horizontally the overflowing parts should still be visible (In my case, the overflowing parts are on-hover tooltips which are getting hidden and add a horizontal scrollbar...), without having to scroll horizontally. My CSS/HTML looks like this:
<table class"tab1">
<td class="td1"><div class="container"><!-- Many, many, many floating elements here --></div></td>
<td></td>
</table>
CSS:
.tab1 {
table-layout: fixed;
width: 100% /*100% of the parent node*/
height: 20em;
}
.td1.container {
overflow-y: scroll;
}
2 Problems:
The height of 20em gets ignored. Even though the first column now gets a scrollbar, it still expands to its own needs.
When hovering over one of my elements, which generates a div with position:absolute, a horizontal scrollbar appears and the part of the tooltip that overflows gets hidden.
How can I fix this?
PS: The code is simplified of course, but I hope that it still illustrates my problem well.
PPS: Here is a JSFiddle: jsfiddle.net/pg0cLpjd
This question is even more difficult than I thought...
But here is a partial solution:
table-layout: fixed; only applies to the table itself and its columns; not the height. A table will always grow with its content. But there are a couple workarounds:
Set your table to display: block;, give it a specified height and set its overflow-y: scroll; (This also might solve your second problem, depending on your needs)
Place a div with a specified height around your table and set overflow-y: scroll;. The table still grows inside the div but you have a scrollbar.
Place a div in your columns with a specified height and set overflow-y: scroll;. This differs from the first attempt only in the position of the scrollbars and you can scroll every cell independently. But this has one huge disadvantage, which I am going to explain now:
As this answer says: If you set one overflow direction to something else than visible, the other overflow direction will automatically set to auto. (it's a feature, not a bug). And this is exactly where the second problem lies. Your code has the right logic, but it's just not possible. There are solutions using a wrapper div, (it didn't work for me) but you could give it a try.
I'd recommend having a look on how to make tooltips with JavaScript. There are plenty tutorials out there on the internet.
Related
i have a table that looks like this:
<table id="navbar" border="1" style="background-color:navy;height:150px;position:sticky;top:0px;right:0px;left:0px;border-style: solid;border-color:black;max-width:999999px; width:100%; background-image: none;">
the style for all tables:
table{
text-align:center;
width:30%;
left:25%;
/*font-size:larger;*/
}
the psoition sticky should make it so that the table will always remain at the top of the screen, even on horizontall scroll. yet it doesn't work. the only way i found for it to work was by adding another table above and giving both the display:inline-table attribute, but it is not the solution i am looking for.
anyone knows the reason for why it doesn't work?
edit-i need to use position:sticky. it works pefectly for vertical scroll, but not for horizontal scroll. that is the problem i need to fix
Sorry it took so long for someone to answer you #Erel.
So you don't have to read my ramblings if you just want code, I'll start with the demo: https://codepen.io/NerdyDeeds/pen/oNYVLpB
There's a couple things to note here, for the behavior you're after:
Much like the whole height:100% thing, for this to work, the measurements need to go all the way down to the :root. That is to say, every DOM node hierarchy needs to know the actual limits of its bounding box (don't worry: it'll become more clear below).
When an object is positioned sticky, it basically has TWO sets of coordinate limitations: those of the viewport, AND those of its parent. If the parent is 500px wide and you scroll 1500px off screen to the right, the sticky element will stop at the edge of its parent, not continue to tag along. Which brings us nicely to the most important aspect:
The <body> tag is simply another block-level container object, only it gets an implicit min-width:100vw; min-height:100vh. That said, if the one of IT'S children that's necessitating the horizontal scroll is, say, 250vw wide, it will expand to contain that element, but it's measurement width remains the same; it's children still think papa's only 100vw wide. Likewise, were you to explicitly tell it that it's "ACTUAL" width is really only 100vw, it too, will slide off-screen when scrolling, carrying its sticky child (aren't they all?) with it.
The same thing applies to all the ancestral containers of your sticky element. They DON'T automatically get the min-width, so you need to explain to them they're to take up that full space. If you want that done dynamically, you need to explain that to the <body>, so they can inherit the "real" 100% of the page. If any ancester is throttled in its movement or its dimensions, that will cascade all the way down-chain to your element, sticky or not.
The simplest way to tackle this I've found is to simply add:
body {
width: max-content;
}
...to you CSS. This tells the body "you're actually as wide as your widest contents... pass it on!" The "cascading" portion of the CSS will take hold and carry they measurement all the way up to your sticky element, provided none of the parent nodes between it and the body themselves are constrained (like if you set a width:100vw in there somewhere. 100% will work fine, but again: only if none of IT'S ancestors is smaller).
Check out the attached CodePen. I tried to make it as self-explanatory as I could.
And again: sorry nobody got back to you sooner. That's a frustrating feeling that stinks. I hope you already found your solution, but if not, this may help who comes googling after. Hope this helped.
Use fixed position:
<table id="navbar" border="1" style="background-color:navy;height:150px;position:fixed;top:0px;right:0px;left:0px;border-style: solid;border-color:black;max-width:999999px; width:100%; background-image: none;">
position: fixed always fixates an element to some position within its scrolling container or the viewport. No matter how you scroll its container, it will remain in the exact same position and not affect the flow of other elements within the container.
position: sticky basically acts like position: relative until an element is scrolled beyond a specific offset, in which case it turns into position: fixed, causing the element to "stick" to its position instead of being scrolled out of view.
As pictured in this Fiddle, I have a three tables on a page. I want to be able to scroll the body of "Leaderboard" and "Queue," leaving the caption and table header alone. Preferably without absolute positioning.
Somewhat related, I also need the table (not including the caption to have a little bit of padding on the sides (but not between individual cells).
Add overflow: scroll; to your divs and include a height. If you only want to scroll in one direction, instead you could do overflow-x for horizontal scrolling and overflow-y for vertical scrolling. For detecting if the div even needs to be scrollable, use overflow: auto;.
Add overflow: auto; to the surrounding DIVs you want to scroll. You may want to set explicit heights, depending on your layout — you don't have to but it won't scroll if you don't. You could try setting a max-height if you want it to stretch only to a point. If you only want it to scroll vertically, some browsers support overflow-y: auto, but not all.
Since the <caption> is in the table, you can't set the padding or margin on the table. You can either:
Take the caption out of the table and make it a simple header like h2, then adding a margin to the table, or
You can set padding-left on the left table cells/column and padding-right on the other side. Not real clean, but lets you keep the <caption> semantic if you want.
A web site of mine has tables nested within absolutely-positioned draggable dialogs that show/hide based on some user interactions. It's worth mentioning that these tables have table-layout: auto; and width: auto;. A problem arose where a table had so many rows that it went off the bottom edge of the screen. This caused issues with the dragging since we have limited the dragging to the edges of the viewport. To fix the issue, I wrapped the table in a <div> and set max-height: 400px; overflow: auto; on it. This gives the user a nice vertical scroll bar whenever the table exceeds the max-height. That works, but for some reason the browser (both IE and Chrome) is not taking the width of the scroll bar into consideration, so anytime the height of the table exceeds the max and triggers an overflow, the table gets scrunched over to the left and some cells in the first column have a very ugly word-wrap applied to them. Without the overflow/max-height combination, the table width is calculated correctly and there is no overflow.
Live Demo on jsFiddle
I found two ways around this, both of which are not feasible...
Explicitly set the width on each of the cells (or use table-layout: fixed)
Use overflow-y: scroll; instead of auto which causes the scroll bar to always appear, even when it is not needed. What makes this worse is that overflow-y is a CSS3 property.
There must be a better solution! How can I get a vertical scrollbar on the parent of my table without any word-wrapping?
You can try applying white-space: nowrap; to your table, but you'll probably need to adjust div.dialog's width explicitly if you don't want the horizontal scrollbars to appear.
Figured it out, thanks in part to kei's answer. Using white-space: nowrap; does indeed prevent the text from wrapping, but it causes a horizontal scrollbar to appear (demo). To remove the horizontal scrollbar, I just applied 18px of right padding to the table parent and now everything works perfect (demo). Thanks to all who helped!
div.dialogBody {
overflow: auto;
padding-right: 18px;
max-height: 400px;
}
div.dialogBody table td,
div.dialogBody table th {
white-space: nowrap;
}
I have a div which pops up into the middle of the screen and is populated with some arbitrary content. I need it to scroll if the content added doesn't fit within the space available.
The basic styling is left: 25%; width: 50%; max-height: 70%
If the screen is big enough it all works fine. In Firefox, if there's not enough space, it also works nicely, adding a vertical scrollbar to the division. But in IE, it adds an annoying and unrequired horizontal scrollbar, and I can't figure out a way to get rid of it.
You can see some screenshots of what I mean here:
http://dl.dropbox.com/u/15633144/popup.html
Sorry I can't post the actual HTML, which certainly doesn't make this any easier! But I'm hopeful this is a standard problem which people have worked around before.
The usual solution posted on here plenty of times is overflow-x / overflow-y. But in some cases the div contents do actually need to scroll horizontally, so I can't use this technique.
First IE don't support max-height CSS property.
And the horizontal scrollbar will show up if some elements inside your container have a width overflowing. You probably have some elements inside with a width:100%. As IE adds random borders/margins here and there, the width of inside elements become larger than its container.
try looking here
CSS div element - how to show horizontal scroll bars only?
I'm afraid that because you said that sometimes you need to scroll then you will need horizontal scrollbars. Which if you hid them by overflow-x: hidden; wouldn't allow you to scroll. You could work a jQuery If statement and say if window.width was more than the width of your content, show the scrollbar, if not, then hide it!
i have a that contains a HORIZONTAL menu. the menu consists of an unordered list.
i would like the div to get a horizontal scroller whenever the menu exceeds the width of the <div>.
i tried using these CSS definitions for my <div>:
position: absolute;
width: 380px;
overflow: auto;
overflow-y: hidden;
height: 30px;
but than realized that since the menu is LIST, the different list items break the line whenever they reach the width of the <div> and move on to the next line, thus the browser doesnt see the need for a horizontal scroller (it doesnt display a vertical one as well because of the overflow-y: hidden; line)
any ideas how i can create a 1 line horizontal menu which will scroll horizontally only?
thank you all so much.
You might be able to use the white-space property to prevent wrapping. It's hard to know if it's applicable in your case without more code.
For your div, try:
white-space: nowrap;
As far as I know, there's no CSS-based workaround for this. However, you can use Jquery to solve it.
I made a little test for you to see:
http://sotkra.com/stackoverflow/cssdilemma/cssdilemma.html
The first example has 6 or so li's which exceed the width of the container div which means you DON'T need a scrollbar.
The second example has 8-9 li's which DO exceed the width of the container div which means you DO NEED a scrollbar.
Basically, you use Jquery to count the number of li's inside your div using size(). If they exceed X number, in my example's case 6 (the limit before scroll is needed), then a class is added to the ul to extend its width (.longer) so that there's no line break and the horizontal scrollbar appears.
It also adds another class (.taller) that increases the height to accomodate the scrollbar itself.
Cheers
G.Campos
You need to put one massive horizontal div inside the parent div with overflow: auto;
This will allow the to float left without wrapping to the next line, and it will only scroll when the boundary of the parent div is crossed.