Keep tooltip in visible part of the page - css

I have an angular app, where I implemented a simple tooltip that can be more than just text, but is a div that can contain anything:
.tooltip-master {
position: relative;
.tooltip-slave {
visibility: collapse;
position: absolute;
top: 80%;
left: 80%;
}
}
.tooltip-master:hover {
.tooltip-slave {
visibility: visible;
}
}
<div class="tooltip-master">
<div>Element content</div>
<div class="tooltip-slave">Tooltip content</div>
</div>
So whenever someone hovers over the element the tooltip is shown on the right bottom of the element. This works just fine. However for elements on the bottom of the page the tooltip is now mostly outside of the page and so not visible any more.
What I want to achieve is to move the tooltip upward when it would not be shown on the page completely anymore. I'd prefer a solution with pure CSS. Any suggestions?

Its difficult to say without more detail... as you are using top: 80% and left: 80% for a reason I guess.. and you may struggle with a css only solution
So I'd just use ngx bootstrap ... https://valor-software.com/ngx-bootstrap/#/tooltip which will place the tooltip automatically on the default setting ...
unless you have a specific reason for wanting to do it your way of course... in that case have a look and see how they do it

The solution I finally came up with unfortunately doesn't work with plain CSS, but it works.
Depending on whether the tooltip should be shown above or below, the accoriding class tooltip-slave-above or tooltip-slave-below needs to be set additionally:
.tooltip-master {
position: relative;
.tooltip-slave {
visibility: collapse;
position: absolute;
left: 80%;
z-index: 200;
}
.tooltip-slave-below {
top: 80%;
}
.tooltip-slave-above {
bottom: 80%;
}
}
.tooltip-master:hover {
.tooltip-slave {
visibility: visible;
}
}
The master div now listens to the mouseenter event and the tooltip classes are set according to the bound property setTooltipBelow:
<div class="tooltip-master" (mouseenter)="tooltipMasterEnter($event)">
<div>Element content</div>
<div [ngClass]="{
'tooltip-slave': true,
'tooltip-slave-below': setTooltipBelow,
'tooltip-slave-above': !setTooltipBelow
}">Tooltip content</div>
</div>
This property is set in a pretty simpl way:
public tooltipMasterEnter(e: MouseEvent) {
const hBelow = e.view.innerHeight - e.y;
const hAbove = e.view.innerHeight - hBelow;
this.setTooltipBelow = hBelow > hAbove;
}

Related

Can I disable pointer events on a container but still allow it to be scrolled with the mouse?

I think the answer is no and thus I'm going to need a new approach.
Essentially what I'm trying to do is put a group of floating action buttons on top of a leaflet map. There may be a lot of buttons and thus I want to allow the user to scroll through them. So I put the fabs into a container to allow them to be scrollable but this then prevents mouse events from reaching the underlining map.
Does anyone know a way I can allow the containers to be scrollable but not prevent mouse events from reaching the background?
Here's the basic set up I've got:
<div class="container">
<div id="map"></div>
<div class="controls">
<button class="fab">Button</button>
...
</div>
</div>
.container {
position: relative;
}
#map {
position: absolute;
inset: 0;
}
.controls {
overflow: auto;
position: absolute;
left: 0;
top: 0;
bottom: 0;
}
and here's a codepen that shows the problem I've got.
It can be done with the :has pseudo selector.
.scroll-area:not(:has(:hover)) {
pointer-events: none;
}
This selector hasn't been rolled out to all browsers yet though (caniuse.com/css-has) but there is a postcss plugin.

Push Sidebar Nav Menu

I am trying to get a sidebar push navigation that looks like this. I do actually have content in between my center element div. My html looks like:
<div id="mySidenav" class="sidenav">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×
</a>
Home
About
Projects
Hire Me
</div>
<div id = "main">
<span style="font-size:50px;cursor:pointer" onclick="openNav()" id="btnMenu">☰</span>
<div class = "centerElement">
</div>
</div>
I believe its probably because my centerElement class that is not allowing its content to be pushed. If that is true my btnMenu will also have to be changed.
css code here:
.centerElement {
position: absolute;
top: 50%;
left: 50%;
width: 600px;
height: 600px;
margin: -300px 0 0 -300px;
}
#main {
transition: margin-right .5s;
padding: 16px;
}
#btnMenu {
position: absolute;
top: 72px;
right: 128px;
font-size: 18px;
}
javascript is
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginRight = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginRight= "0";
}
I also tried my first fiddle but for some reason my navbar doesn't even open in it. Didn't really care to put the effort to find out why but if this helps here it is.
I got your fiddle working in a code pen, if I understand your question you want to push the content to the side when opening the side nav. I changed a few css properties to achieve this.
you have your centerElement which has position: absolute; this wont allow it to adjust to the side nav when it opens.
same with your btnMenu icon
I created a div around your btnMenu and added
.menuIcon {
text-align: right;
}
which places it on the right side like you had it.
also I removed your btnMenu styles
I also changed your .centerElement class to
.centerElement {
width: 45%;
margin: auto;
}
this centers the content and adjusts when the nav opens.
You may have to play with some other margins and padding to get things to line up, but I think this is what your going for.
https://codepen.io/anon/pen/qjORpO

Slick - the prev/next arrow stay stuck inside the sliding carousel

Using slick: http://kenwheeler.github.io/slick/
HTML
<div class="carsoule" style="overflow:hidden; width: 300px; height: 200px; margin: 0 auto; background:red">
<div>
<img src="http://theheightsanimalhospital.com/clients/15389/images/playful-kitten-6683.jpg" width="250">
</div>
<div>
<img src="http://theheightsanimalhospital.com/clients/15389/images/playful-kitten-6683.jpg" width="250">
</div>
</div>
CSS
.slick-prev, .slick-next {
height: 55px;
width: 55px;
}
.slick-prev {
left: -80px;
/*plan to add button image*/
}
.slick-next {
right: -80px;
/*plan to add button image*/
}
Jsfiddle Demo
Tried to override, but the prev and next buttons stay stuck inside the carousel. Wanted to replace the css with button images and the buttons should be outside the carousel, just like the example on slick website. Couldn't figure where I went wrong.
Help appreciated!
UPDATE : $('.carsoule').slickNext(); won't work anymore.
Use $('.carsoule').slick("slickNext"); instead.
https://github.com/kenwheeler/slick/issues/1613
Looking at the css that this plugin uses, I noticed the parent has overflow:hidden applied to it, so your arrows wont show beyond the parents container.
You can mess with adding a extra overflow !important rule to the container, however, I've looked over at some methods that you can use to trigger next/prev slide, and turns out that you can call on your carousel to change slide, when clicked on a certain class/id outside of the carousel container.
So basically, after your carousel(or anywhere on the page if it helps you out), add two div/button/a/whatever tags, and add either a class or id to call upon the slider to change its slide using: slickNext() or slickPrev()
You can wrap everything in a master container, your carousel and those two extra tags and style them the way you want.
Check out the demo here, and the extra js/markup used bellow:
<div class='next-button-slick'>
next please
</div>
<div class='prev-button-slick'>
prev please
</div>
$('.next-button-slick').click(function(){
$('.carsoule').slickNext();
});
$('.prev-button-slick').click(function(){
$('.carsoule').slickPrev();
});
UPDATE 2
If you want to keep your markup, and not add any extra stuff, you can either remove the inline overflow: hidden rule from the container, or via css with overflow: visible !important, and set those 2 arrows to position absolute, and work you way from there.
Check out the demo here and the css bellow:
/*extra stuff*/
.carsoule{
overflow: visible !important;
}
.slick-prev, .slick-next {
position: absolute;
background: red;
}
<div class='next-button-slick'>
next please
</div>
<div class='prev-button-slick'>
prev please
</div>
$('.next-button-slick').click(function(){
$('#portfolio-carousel').slick("slickNext");
});
$('.prev-button-slick').click(function(){
$('#portfolio-carousel').slick("slickPrev");
});
This should solve your issue,
CSS
body {
background: #d7d7d7;
}
.carsoule {
background: yellow;
margin: 0 auto;
overflow: visible;
width: 250px;
}
.slick-prev,
.slick-next {
height: 55px;
width: 55px;
}
.slick-prev {
left: -80px;
/*plan to add button image*/
}
.slick-next {
right: -80px;
/*plan to add button image*/
}
HTML
<div class="carsoule">
<div>
<img src="http://theheightsanimalhospital.com/clients/15389/images/playful-kitten-6683.jpg" width="250" />
</div>
<div>
<img src="http://theheightsanimalhospital.com/clients/15389/images/playful-kitten-6683.jpg" width="250" />
</div>
</div>
The carsoule had overflow:hidden, so if you positioned it outside it was hidden.
The problem is the hover. Just add the block of code below to it and you'll be just fine.
.slick-next:hover,
.slick-prev:hover {
background-color: red;
color: white;
}
See working example here
You missed out the important slick-theme.css http://kenwheeler.github.io/slick/slick/slick-theme.css. I added this file and meddled with your codes and came up with this solution:
HTML
Re-styling your wrapper to include .slider class with proper margins:
class="carsoule slider"
Modified CSS
.slick-prev:before, .slick-next:before {
color:red;
}
.slick-prev, .slick-next {
height: 55px;
width: 55px;
}
.slick-prev {
left: -80px;
/plan to add button image/
}
.slick-next{
right: -80px;
/plan to add button image/
}
.slider {
margin:0 80px 0 80px;
width: auto;
}

How to move a single block to the left?

On my Drupal 7 website, I'm having three blocks in an environment, called 'Topbar links', with the following layout: http://jsfiddle.net/Jeroen94/54L57/1/.
Mind that the first and third block are Nice Menus. I don't provide all the code, because most of it isn't relevant, but the layout should be maintained. The three blocks are displayed at the right, but now, I'd like to display 'Nice Menu 1' to the left and keep 'My Profile' and 'Nice Menu 2' to the right. I thought
.menu-1 {
left: 0;
}
would do the trick, but that doesn't work, because I couldn't overwrite the right. Maybe right: ...px could do the trick for 'Nice Menu 1', but I don't find that a nice solution, because the width from 'Topbar links' can still change in the future, causing a layout break.
How can I solve this?
I'd go about this using float, like this
.topbar-links {
position: absolute;
right: 0;
top: 0;
vertical-align: top;
width: 100%;
}
.topbar-links div {
float:right;
clear:right;
}
#block-1 {
float:left;
}
http://jsfiddle.net/Y7mwW/
The problem is that you are positioning the parent div to the right and not setting a width - the children of the div can only be positioned within the constants of the parent div
You can also use the :first-child selector to select the first and this will eliminate the need for a separate class.
Try
<div class="topbar-links">
<div id="block-1">Some content</div>
<div id="block-2">Some content</div>
<div id="block-3">Some content</div>
</div>
.topbar-links {
position: absolute;
right: 0;
top: 0;
vertical-align: top;
width: 100%;
}
.topbar-links div {
float: right;
}
.topbar-links div:first-child {
float: left;
}
JSFiddle http://jsfiddle.net/JC9ac/
Another solution to stop the switching around of elements that you mentioned jsfiddle.net/JC9ac/2
Update your css with following code:
.topbar-links{
text-align: right;
}
.block-1{
float: left;
}
If you need to view blocks inline add
#block-1,
#block-2,
#block-3{
display: inline;
}
fiddle

Background image hover effect outside of containing element

I am trying to apply a background image hover effect on each row in my css table but need it to appear to the left of the containing element.
View image http://www.weiserwebworld.com/images/view.gif
Any ideas?
JS:
$(function() {
$(".table-row").hover(function() {
$(this).addClass("highlight");
}, function() {
$(this).removeClass("highlight");
})
})
CSS:
#container {
width: 660px;
margin: 20px auto;
}
div .table {
display: table;
border: 1px red solid;
}
div .table-row {
display: table-row;
}
div .table-cell {
display: table-cell;
width: 145px;
padding: 10px;
vertical-align: top;
}
.highlight {
cursor: pointer;
background-image: url('click-to-view.png');
background-position: 0 center;
background-repeat: no-repeat;
}
HTML:
<div id="container">
<div class="table">
<div class="table-row">
<div class="table-cell">Ralph Kramden</div>
<div class="table-cell">Truck Driver</div>
<div class="table-cell">8/17/2010</div>
<div class="table-cell">N/A</div>
</div>
<div class="table-row">
<div class="table-cell">Ralph Kramden</div>
<div class="table-cell">Truck Driver</div>
<div class="table-cell">8/17/2010</div>
<div class="table-cell">N/A</div>
</div>
</div>
</div>
First, throw away this:
$(function() {
$(".table-row").hover(function() {
$(this).addClass("highlight");
}, function() {
$(this).removeClass("highlight");
})
})
It is an abomination.
Then change the CSS selector .highlight to .table-row:hover. As you clearly don't care about IE6 (where :hover only worked on a elements), there's nothing wrong with using :hover.
Now to the rest of the problem.
The technique that I would use for this is the before or after pseudo-element. Something like this:
.table-row {
position: relative; /* So that the position: absolute on the "click to view" makes it relative to the table row */
}
.table-row:hover:after {
position: absolute;
left: -80px; /* Adjust as desired */
content: url(click-to-view.png); /* This makes it an image */
}
There's plenty of tweaking that can be done with this, but that's the general idea. No demo on jsfiddle as I can't be bothered doing the table structure or getting an image for it.
You can do this in pure CSS.
This is quick and dirty, you'll have to tweak it to how you want, but the general idea is:
If you give your row an id () you can add a CSS styles like this:
.overlay {
display: none;
position: absolute;
left: -30px; //makes it appear left of box, even though it's technically "in" box.
}
#table-row1:hover .overlay {
display; block; //Causes div to appear.
}
Now, simply add with the image you want, that will appear as you roll over the row.
Note that the class=overlay div MUST be placed INSIDE of the id=table-row1 div or the hover-appear will not work!
I would also recommend redoing this using tags with the same :hover approach, as your current method of divs with table properties could get unwieldy very fast.
You need to put your image in a DIV, then position the DIV relative to the row. Backgrounds cannot go outside the boundary of their container.

Resources