Tooltip gets cut off when a table container has overflow-x auto - html

I have found a lot of issues related to this one, but not one that matches the exact same problem and I was also not able to resolve my problem with other "related" issues. Below you can see two screenshots, one with overflow-x: auto and one without.
With overflow-x: auto
[[With overflows-x][]1]
Without overflow-x: auto
[[Without overflows-x][]1]
So overflow-x auto is cutting off my tooltip when it overflows vertically. I do not know why it behaves this way, even if I put overflow-y visible on it, it does not work.
Reason I am using overflow-x: auto
I am using overflow-x: auto to make my table responsive on resize. This will give me a scrollbar when the content does not fit. I see that many people use this to make their tables responsive.
Important code parts that I am currently using
HTML
<div key={uniqueKey} className={'table-container'}>
<table>
<thead>
<tr>
<th scope='col'>Id</th>
<th scope='col'>Name</th>
</tr>
</thead>
<tbody>
{someList.map((item, index) => {
return (
<tr key={index}>
<td data-label='Id'>{id}</td>
<td data-label='Name'>{name}</td>
<td data-label='Actions'>
<div className={'actions-container'}>
// EXISTING TOOLTIP COMPONENT HERE, I WILL SHOW THE CSS.
</div>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
CSS
.table-container {
overflow-x: auto;
border-collapse: separate;
table-layout: fixed;
table {
width: 100%;
tr {
height: 40px;
}
td {
height: auto;
}
th {
min-width: 175px;
padding: 8px;
}
}}
CSS Tooltip
.tooltip{
width: 300px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px;
border-radius: 6px;
position: absolute;
z-index: 100;
word-break: normal;
opacity: 0;
visibility: hidden;
transition: opacity 0.5s;
transition-delay: 0.4s;}
Other notes
I can not modify the tooltip too much since it is a existing component within our company, we would have to change it on lots of places. Also it works as expected on other places.
If there is any information missing, just let me know and I will respond as soon as possible.
Any insights are welcome at this point!

We had faced similar issue. The way we solved this is add a support to render the tooltip view in a react portal instead.
You'll need a component change but you don't need to change a lot of existing code.
Add a portal component:
const Portal = (props) => {
const { children, target = document.body } = props;
return ReactDOM.createPortal(children, target);
};
Add a usePortal prop that'll render the view in portal instead. Otherwise the view will be rendered as it is currently.
You'll have a viewDom that renders your tooltip view, use the Portal component:
const { usePortal } = props;
const viewDom = <span> Your view dom </span>;
if (usePortal) {
return (
<Portal>
{ viewDom }
</Portal>
)
}
// otherwise return the default dom without portal
return viewDom;

I’m not sure if this would solve the issue or not, but I noticed that the visibility is set to hidden and that will hide everything that doesn’t fit within that specific div. You might want to try setting that to visible to see if it fixes this cut off issue. I have no idea if that is the fix to this, but I wanted to try and help ha ha.

If your tooltips have a max-height, you can add padding/margin top to the table to clear that height.
So if
.tooltip {
...
max-height: 3em;
}
table {
margin-top: 3em;
}

Haven't tested it but your tr only has 40px height and will cut off the overflow on auto, because your three lines of text will take more than 40px space at all.
You should try to set the tr to position:relative and the tooltip to position:absolute for positioning and forget about the overflow;

Related

CSS in Angular project: position: fixed not always functioning as expected

I am having issues with my sticky table header in my angular 6 project.
I have a condition in my .ts file that applies the 'sticky' class only when the user scrolls towards a certain point in the page. That part works great. The issue is that when the position: fixed class is applied, it only works if top:0.
The css looks like this:
.sticky
{
position: fixed;
top:0;
width: 100%;
background-color: #fff;
padding-right: 20px!important;
}
But if I change top:0 to top:100, too account for the header of the webpage (that is build on another component) then the top:100 attribute won't apply and be considered invalid.
The html is a little tricky but looks a little like this
child.component.html
<div>
<navigation></navigation>
<div>
</div>
<div class="table-responsive " >
<table id="tabletop" #tabletop class="table scroll">
<thead #stickyMenu [class.sticky]="sticky">
<tr id="content" class="row1">
<tr id="content" class="row2">
<tr id="content" class="row3">
</thead>
</table>
</div>
</div>
app.component.html
<header></header>
<app-child></app-child>
<footer></footer>
I want the thead to stick right underneath the header that lives on a parent component, so it is still visible.
Why is that, and how can I get my position:fixed attribute to actually keep something at the top of the page?
Any help is greatly appreciated!
I wanted to post this by comment, but looks like I need at least 50 reputation to do so. So, here it goes:
But if I change top:0 to top:100 {...}
The unit of the top seems to be missing. You probably wanted to set it to 100px? Probably the 0 value confused you as it is allowed with or without a unit.
One more thing, the id of each element must be unique, but you have 3 id="content" there.
Alternative solution
You can use position: sticky css property on your thead element (and also on the respective th child elements). This way, you wouldn't need to handle the scroll event by yourself and let the css do the job for you.
Example:
I only include the scss part here, since the code snippets make the post unnecessarily long. You can see full example on stackblitz.com.
thead {
position: sticky;
top: 0px;
tr {
position: sticky; top: 0;
/* the top value can be adjusted according to <header>'s height */
&:nth-child(1) th { position: sticky; top: 110px; }
&:nth-child(2) th { position: sticky; top: 132px; }
}
}

Ionic 4: how to hide ScrollBar in ion-content

I'm trying to hide the scroll-bar in ion-content (Ionic 4)
there's no ion-scroll on ionic 4 so I used the ion-content
but I can't find any css attribute to hide it (most of them not work)
I do want to scroll but I don't want to see the scrollbar
::-webkit-scrollbar,
*::-webkit-scrollbar {
display: none;
}
I've tried it but it doesn't work in ion-content.
Because of Ionic use shadow DOM for ion-content, should disable scroll in element on shadow DOM and after that make ion-content his own scroll and then hide scroll bar for ion-content. The result's ion-content with the hidden working scroll bar.
Need to use CSS Custom Properties. Add styles to global scope.
ion-content {
// overwrite inline styles
--offset-bottom: auto!important;
--overflow: hidden;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
}
In Ionic 4 you must use following, because Ionic use shadow DOM:
global.scss
.no-scroll {
--overflow: hidden;
}
and in page
<ion-content class="no-scroll">
::-webkit-scrollbar,
*::-webkit-scrollbar {
display: none;
}
ion-content {
--offset-bottom: auto!important;
--overflow: hidden;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
}
::-webkit-scrollbar, *::-webkit-scrollbar {
display: none;
overflow: hidden;
}
ion-content {
overflow: hidden;
--overflow: hidden;
}
.scroll-content {
overflow: hidden;
}
ion-infinite-scroll.md.infinite-scroll-enabled.hydrated {
overflow: scroll!important;
height: 100%!important;
}
The <ion-content> is a custom element with shadom DOM. There's something called the ::part pseudo element to target an element in a shadom DOM element.
If you look at the shadow dom, you will see this:
Take notice of the part="scroll". Ionic did add parts to their elements that we can use via the ::part pseudo element to target this and apply our custom css to hide the scrollbar:
ion-content::part(scroll)::-webkit-scrollbar {
display: none;
}
Tested this on iOS and Android successfully. I'm not getting it to work on Chrome though.
Try this, seems to work fine so far while preserving all functionality in Ionic 5.
// variables.scss
ion-content {
width: calc(100% + 15px);
}
ion-content::part(scroll) {
padding-right: 15px;
}
I have confirmed the following solution works in Ionic 5 although i do believe this should work in Ionic 4 as well.
As others here have noted, the scrollbar which controls the scrolling of content inside of an ion-content component exists in the shadow DOM within it and thus you need to target the scrollbar using ::part() CSS pseudo-element.
In your global style sheet add the following css declarations which will hide the scrollbar while retaining the ability to scroll:
/* chrome, safari */
ion-content::part(scroll)::-webkit-scrollbar {
display: none;
}
/* firefox */
ion-content::part(scroll) {
scrollbar-width: none;
}
Thank you #rostislav
Your solution even don't suggested by WebStorm and draw yellow underline in the meaning of warning, but work for me and work, it's awesome :)
solution: add these lines to both global.scss and variables.scss:
::-webkit-scrollbar, *::-webkit-scrollbar {
display: none;
overflow: hidden;
}
ion-content {
overflow: hidden;
--overflow: hidden;
}
.scroll-content {
overflow: hidden;
}
NOTIC: then clear browser cache and refresh page, it's great!
but don't forget that scroll disabled in all pages, add this code to only .sccs file of pages that don't need to be scrolled!
Refactored #Sergey Oleynikov solution and it worked perfectly for me
ion-content {
// overwrite inline styles
// --offset-bottom: auto !important;
--overflow: hidden;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
}
Here is a hack? https://github.com/ionic-team/ionic/issues/17685
<ion-content>
<div style="background-color: #f2f2f2 !important; height: 100vh; overflow: auto;">
# content here
</div>
</ion-content>
I couldn't find a reliable way to do this using the previously mentioned methods, they either didn't work or stopped the scrolling all together. My approach was to make the ion-content window wider than the screen.
.noscroller {
left: -10px;
width: calc(100% + 20px);
}
if you want to remove the scroll dynamically. You can use the approach of removing the scroll-y class from shadowDOM at <main class="inner-scroll scroll-y"></main> within <ion-content></ion-content>.
Firstly, import { Renderer2 } from '#angular/core' in your constructor(renderer: Renderer2)
To reach this, in your your-component.component.ts at event cycle ngAfterViewInit or onward.
This will remove the scroll from the page activated in your app.
for(let el of Array.from(document.querySelectorAll(".ion-page:not(.ion-page-hidden) ion-content")))
{
this.renderer.removeClass(el.shadowRoot.querySelector("main[part=scroll]"), "scroll-y");
}
This will add the scroll from the page activated in your app.
for(let el of Array.from(document.querySelectorAll(".ion-page:not(.ion-page-hidden) ion-content")))
{
this.renderer.addClass(el.shadowRoot.querySelector("main[part=scroll]"), "scroll-y");
}
The Code from spicemix worked! I pasted the code in global.scss and not in variables.scss
/* global.scss */
ion-content {
width: calc(100% + 15px);
}
ion-content::part(scroll) {
padding-right: 15px;
}
For me it works after adding the no-scroll class in the <IonContent> element, as mentioned above, and after adding the following lines
useEffect(() => {
const style = document.createElement("style");
style.innerHTML = ".inner-scroll.scroll-y.overscroll { overflow: initial; }";
ionContent.current.shadowRoot.appendChild(style);
}, []);
Then in the render <IonContent ref={ionContent} className="no-scroll">...</IonContent>
The thing is that in these classes inner-scroll and scroll-y there is a overflow: hidden; style so we just have to override it.
I believe you can use
slot="fixed"
to make the element fixed thus removing the scroll bar by default for you.
Refer ionic documentation

How to eliminate unwanted horizontal scroll-bar on re-sizing window by media queries?

i have problem with this code and the problem is that before 1200px everything is OK but after re-sizing to 1200px and more ( before width of scroll bar, for example chrome scroll-bar width is 17px ) before 1218px, we will see unwanted horizontal scroll-bar annoying us.
i want to solve this problem but i don't know how.
anybody knows how? so please guide me.
link of my codes and online test:
https://codepen.io/mostafaeslami7/pen/xZePXq?editors=1100
my html:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="header">
<div class="inner-header">header</div>
</div>
<div class="body">body</div>
<div class="footer">
<div class="inner-footer">footer</div>
</div>
</body>
</html>
my css:
*{
box-sizing: border-box;
margin: 0;
padding: 0;
color: white;
font-size: 30px;
text-align: center;
}
body{
background-color: orange;
}
.header{
border-bottom: 1px solid black;
}
.inner-header{
background-color: black;
}
.body{
height: 3000px;
background-color: blue;
}
.footer{
border-top: 1px solid black;
}
.inner-footer{
background-color: green;
}
.header,
.footer{
width: 100%;
height: 100px;
}
.inner-header,
.inner-footer{
height: 100%;
}
.inner-header,
.body,
.inner-footer{
width: 1000px;
margin: 0 auto;
}
#media screen and (min-width: 1200px){
.inner-header,
.body,
.inner-footer{
width: 1200px;
}
}
I know it a old question. but i had like to share this, Hopping someone will find it useful and will save someone's day.
So, There is no quick way, You will have to do some digging and find yourself the element which is causing overflow. Thus, creating unwanted horizontal scroll and pain in your ass. Normally one way would be to just write
body {
overflow-x: hidden;
}
and hope that overflow-x on body will remove that horizontal scroll bar but some times you have to apply overflow:hidden to you main container of the site. Which likely works all the time or most of the times. like,
.main_container {
overflow: hidden;
}
There are some tricks that can help you find those overflow elements such as using below JavaScript script, just open console and execute it there
var docWidth = document.documentElement.offsetWidth;
[].forEach.call(
document.querySelectorAll('*'),
function(el) {
if (el.offsetWidth > docWidth) {
console.log(el);
}
}
);
OR you could execute jQuery one,
$.each( $('*'), function() {
if( $(this).width() > $('body').width()) {
console.log("Wide Element: ", $(this), "Width: ", $(this).width());
}
});
or you can use this little jquery snippet. It will logging out the elements directly in console along the elements width, which can help you to easily highlight them on hover in your console (at least in Chrome).
$.each($('*'), function() { if ($(this).width() > $('body').width()) { console.log($(this).get(0)); } }).length;
or if you still can't find that particular element use this below trick,
//Open inspector -> “New Style Rule”:
* {
outline: 1px solid red;
}
You can always add: opacity: 1 !important; visibility: visible !important; if you think you might have a hidden element but usually the above works without extra effort.
Hope it helps someone. Happy digging.
I can't really recommend it but you can use overflow-X:hidden on the body element (not the element with a class of .body*). It's not as though you need to see anything outside of the sides of your container anyway...right?
* you should really not use that name for a class, it's unnecessarily confusing.
#media screen and (min-width: 1200px) {
body {
overflow-X: hidden;
}
.inner-header,
.body,
.inner-footer {
width: 1200px;
}
}
Ideally, you should adjust the design to allow for this though. Different browsers treat the scrollbars differently when it comes to calculating the viewport width.
Codepen Demo
You can change your .inner-footer from width: 1000px to max-width: 1000px; and that will fix the issue.
Here you change code like that. overflow-x: hidden; is hidden the horizontal scroll bar.
body{
background-color: orange;
overflow-x: hidden;
overflow-y: scroll;
}
You could solve this in quite a few ways - one of which is changing your width: 1000px to max-width: 1000px
Another might be simply styling / hiding the scroll bar with some -webkit prefixes. Wouldn't recommend this route for multiple UX reasons but if you want to read up on styling scrollbars - check out this resource.
Lastly you could specifically target the x-axis scroll bar with overflow-x and remove / hide it by setting this to hidden. Again - this method is not the best. How would a user know content is off the page without the scroll bar?
i solve it very easy. if you define min-width media queries = width + scroll-bar width ( for example in chrome is 17px or in opera is 15px but for sure we say 20px ) the problem will be solve.
new link of code:
codepen.io/mostafaeslami7/pen/JGVLdK?editors=1100

Issues with touch scroll on iOS when focusing inputs

I am having some issues with a scrollable div on iOS. When trying to scroll by touching outside an input, it scrolls ok without any problem but when I try to scroll and I touch an input to start scrolling (there are a lot of chances that it happens because it is a div with a lot of inputs) it scrolls the whole window instead scrolling the div. I don't have that problem either in desktop or Android. I found a similar question (iOS HTML Input Tag Stops Scrolling in Scrollable Element) but it doesn't have any answer either. While I don't find any good solution, I decided to prevent the event touchmove when the user touches an input, but it is not exactly what I want.
Maybe someone already faced this problem and can help. I would really appreciate it, thanks in advance.
To get native momentum scrolling on iOS 5+, you'll need:
div {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
Source: Overflow
Maybe you also need:
div > * {
-webkit-transform: translateZ(0px);
}
Source: Similar question in Stack Overflow
Source 2: Another similar question
This stuff made me crazy too, after testing everything, I found the following answer from Thomas Bachem here working and made it simpler in jquery.
Just add a class scrollFix to the inputs and you are ready to go. (or directly apply that js to any inputs/textarea using$('input, textarea')
Now when you touch and scroll on an input on iOS 8+, the input get all its "pointer-events" disabled (including the problematic behavior). Those "pointer-events" are enabled when we detect a simple touch.
$('.scrollFix').css("pointer-events","none");
$('body').on('touchstart', function(e) {
$('.scrollFix').css("pointer-events","auto");
});
$('body').on('touchmove', function(e) {
$('.scrollFix').css("pointer-events","none");
});
$('body').on('touchend', function(e) {
setTimeout(function() {
$('.scrollFix').css("pointer-events", "none");
},0);
});
Hacky workaround, but by doing this I was able to make scrolling work even on form inputs. The JS forces a reflow in the rendering engine, which is where the bug in iOS8 Safari lies. Changing the height to auto also improved scrolling when focused on a form element, since scrolling is forcibly handled by the browser when focused.
Markup:
<div class="modal-backdrop-container">
<div class="modal-backdrop">
<div class="modal> <!-- Content --> </div>
</div>
</div>
CSS:
.modal-backdrop-container {
z-index: 10;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 100%;
}
.modal-backdrop {
z-index: 10;
height: 100%;
background-color: rgba(255,255,255,0.5);
overflow: auto;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.modal {
position: relative;
width: 400px;
max-width: 100%;
margin: auto;
background-color: white;
}
JS:
// reflow when changing input focus
$modalInputs = $('.modal').find(':input');
modalInputs.on('focus', function() {
var offsetHeight = modal.$backdrop[0].offsetHeight;
modal.$backdropContainer.css({
'height': 'auto'
});
});
modalInputs.on('blur', function() {
var offsetHeight = modal.$backdrop[0].offsetHeight;
modal.$backdropContainer.css({
'height': ''
});
});
Not sure of the var offsetHeight = modal.$backdrop[0].offsetHeight; line is needed, since both this and changing the height value should force a reflow.

PhoneGap/Cordova: Prevent horizontal scrolling

I have an app built on Cordova and on some of my pages I am able to scroll horizontally out of my content into white space.
This is weird as I have nothing there that extends beyond my #wrapper, which is set to width: 100%.
So I was wondering if there was a way I could disable horizontal scrolling in the app altogether?
UPDATE:
Code on page as requested:
body {
background-color: #fff;
font-family:Arial, Helvetica, sans-serif;
color: #b7b8b9;
height: 100%;
width: 100%;
}
iframe{
border: none;
width: 100%;
/*margin-top: 50px;*/
}
#header{
height: 50px;
width: 100%;
}
<body>
<div id="wrapper">
<div id="header">
<div class="headerback">Home</div>
<div class="headerrefresh"><script>var pathname = window.location.pathname;</script><script>document.write('Refresh')</script></div>
<div class="headertitle"><h2>Get the Look</h2></div>
</div><!--HEADER-->
<iframe src="http://www.mbff.com.au/getthelook"></iframe>
</div>
</body>
Try to debug your page in Chrome (webkit) with the exact dimensions of your device. This solves most rendering issues for me.
I do not know the specific issue here, but it looks like one of your elements is flowing outside of the wrapper. You could for example try this in your css:
div.wrapper { overflow: hidden; width: inherit; }
Although it might be a better idea to find out why your page is expanding horizontally?
I was looking for the solution to this problem for a long time.
Finally I solved it in the following way.
I set style for bodyand html tags:
position: fixed;
width: 100%;
height: 100%;
overflow: hidden;
After that I've added div to body and set the style for it:
overflow-y: auto;
height: 100%;
So, I have got fixed body, which contains div with vertical scroll bar.
// Phone Gap disable only horizontal scrolling in Android.
// Add this code in your Phone Gap Main Activity.Initially Declare the variable
private float m_downX;
//Then add this code after loadUrl
this.appView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
// save the x
m_downX = event.getX();
}
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// set x so that it doesn't move
event.setLocation(m_downX, event.getY());
}
break;
}
return false;
}
});
Try adding the following code to your .html file:
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
For the sake of completeness, I thought the answer which makes use of the official method of doing such a thing via the preference tag should be added:
<preference name="DisallowOverscroll" value="true"/>
Supported by Android and iOS according the documentation.
Default: false
Set to true if you don't want the interface to display any feedback when users scroll past the beginning or end of content. On iOS, overscroll gestures cause content to bounce back to its original position. on Android, they produce a more subtle glowing effect along the top or bottom edge of the content.
In my case it was broken styling like below
<body>
<div style="margin-left:5%; width:100%">Content</div>
</body>
which cause div to became horizontally bigger than body. I could see scroll when app run in browser. Set width to 90% (as it was initially intended) fixed the problem.
Generally, as it already pointed out here, enough to find element with wrong style which makes your page expanding horizontally and fix it.
BTW DisallowOverscroll was not helpful in above case.