Attach CSS triangle to MatTooltip depending on actual positioning? - css

I've been wrecking my brain to figure out a way to attach a little CSS triangle to a MatTooltip in Angular that switches from being at the top when the tooltip is displayed below the host element (default) to being at the bottom when the tooltip is above the host element (e.g. when the host element is too close to the bottom of the viewport).
Am I missing some property that would give me a way to switch the CSS
class? Or is it simply impossible?
Any help would be highly appreciated.

It is possible.
Since MatTooltip controls its positioning via transform-origin, you can make use of it.
For example, .mat-tooltip[style*="transform-origin: left center"] only selects tooltips shown to the right of its parent, so you can display the triangle on the left side of the tooltip.
Values of transform-origin:
Tooltip to the right of its parent: left center
Tooltip to the left of its parent: right center
Tooltip above its parent: center top
Tooltip below its parent: center bottom

Welcome to SO!
Although you can use css to draw pointed triangle to mat-tooltip but you cannot move its position according to View-port/DOM view like above or below, So Its not possible to move the pointed triangle.
Solution:
I have used SAT Popover for styling tooltips. You can give it an
angular component and it will display as you style it.
https://ncstate-sat.github.io/popover/

Step 1 - Add the mat CSS class "matTooltipClass="below"" in HTML control.
Step 2 - Add the below CSS class in you CSS file.
.mat-tooltip {
background-color: white;
border-bottom-color: white;
color: black;
margin: 16px;
border-radius: 3px;
outline: none;
box-shadow: 0 0 10px #9f9fa3;
height: auto;
&::after {
width: 0;
height: 0;
content: "";
position: absolute;
border-left: 0.5rem solid transparent;
border-right: 0.5rem solid transparent;
border-bottom: 0.5rem solid rgb(132, 56, 56);
}
&.below {
overflow: initial;
margin-top: 1rem;
&:after {
top: -0.5rem;
right: calc(50% - 0.5rem);
transform: rotate(0);
}
}
&.below[style*="center bottom"] {
overflow: initial;
margin-top: 1rem;
&:after {
top: calc(100%);
right: calc(50% - 0.5rem);
transform: rotate(180deg);
}
}
}

Related

Absolute position element centered as long as it fits on the screen

I am creating a tooltip system using only CSS that displays tooltips absolute centered below the element you can hover over to see the tooltip. Tooltips must have a minimum width. In my example below, you will see this works fine on the second element. On the first though, the tooltip does not fit on the screen and will be cut off. In this scenario (the tooltip not fitting on screen on the left side) it should just left align. If it were on the right side of the screen, it should align right. I might be pushing the CSS boundaries, but might there be a CSS solution?
Edit: as others have pointed out, this cannot be done purely in CSS. JavaScript can be used with Element.getBoundingClientRect(). Of course, there are also pre-made solutions such as PopperJS.
[data-tooltip] {
padding: 3px 6px;
color: white;
background: red;
position: relative;
margin: 3px;
}
[data-tooltip]::after {
content: attr(data-tooltip);
position: absolute;
left: 50%;
transform: translateX(-50%);
margin: 2em auto;
opacity: 0;
pointer-events: none;
transition: all 0.4s ease-in-out;
padding: 10px;
color: #fff;
background: darkgray;
min-width: 100px;
box-shadow: 2px 2px 1px silver;
}
[data-tooltip]:hover::after {
opacity: 1;
}
<div style="padding: 10px 0px">
<span data-tooltip="This text (or element) will be cut off somewhat on the left side">Hover me
</span>
<span data-tooltip="This tooltip will be completely shown because it is not near any edge">Second one
</span>
</div>

How to auto position my buttons on my website with different screen resolution?

I am working on my website and new to it. I have lots of buttons in my website but there position changes when the screen resolution is minimized. I have also provided my CSS code. Please help me what to do to make my buttons positioned automatically with different screen resolution.
/* Set a style for the submit/send button */
.form-container .btn{
background-color: #009900;
color: white;
border: none;
cursor: pointer;
opacity: 0.8;
}
.form-container .send{
margin-top: 38.5%;
margin-right:-17.5%;
padding: 5px 52px;
}
/* Add a red background color to the cancel button */
.form-container .cancel {
background-color: red;
padding: 5px 10px;
margin-top: -10px;
margin-bottom: 6.5px;
width: 48%;
}
Click here to see the snapshot!
use position:relative for parent div. after, use position:absolute and top, bottom, left, right values for children. position:relative positioning according to itself.
try this
/* Set a style for the submit/send button */
.form-container {
position:relative;
}
.form-container .btn{
background-color: #009900;
color: white;
border: none;
cursor: pointer;
opacity: 0.8;
}
.form-container .send{
position:absolute;
top: 38.5%;
right:-17.5%;
padding: 5px 52px;
}
/* Add a red background color to the cancel button */
.form-container .cancel {
background-color: red;
padding: 5px 10px;
position:absolute;
top: -10px;
bottom: 6.5px;
width: 48%;
}
Few things that could be fixed.
First, you should use position:absolute for children elements of .formContainer. This helps in calculating position of the children(button in your case) based on the parent.
Secondly, using -ve margin creates more problems than it solves. Its better to use top, left, etc to position your elements.
.cancel{
position:absolute,
right: -10px,
width: 5%
}
This would ensure that the btn does not go beyond your form container and always renders 10 pixels to the right border of the container.

CSS background image outside container

I'm having trouble with my worpdress/bootstrap navigation to highlight current page.
I'm trying to find the best workaround, here is what's my method for now, but not working
Make bottom-border on link
Have a margin or padding or any kind of space on container and add background image at the bottom of it
unfortunately the image won't display as soon as it should overlap the border.
Do you have any quick fix or other approach for this ?
Maybe I thought in order to expand the container, is to fix both link and container height and have them placed how I want...
Triangle must be provided as absolute block. It can use :after.
Also for triangle you can use css(not image)
ul{
list-style:none;
}
li{
display: inline-box;
width: 50px;
padding: 20px;
float: left;
}
.active{
position: relative;
border-bottom: 3px solid red;
}
/*triangle absolute position and centred*/
.active:after{
content:"";
position: absolute;
width: 0;
height: 0;
left: 50%;
bottom: -10px;
margin-left: -10px;
border-style: solid;
border-width: 10px 10px 0 10px;
border-color: #ff0000 transparent transparent transparent;
}
https://codepen.io/flinius/pen/XgyLba

Control which border position sets the corner pixels in CSS

Imagine the following CSS:
#foo {
border: 1px solid black;
border-right: 1px solid blue;
}
In this case, at least under Chrome, the top and bottom right corner pixels of the element are blue, not black. Is it possible to make them black?
You can't do it with the normal CSS border options, but if you want to, you can still have a pure CSS solution:
Basically, what you are going to do is create two pseudo elements with CSS, and cover the corners:
#foo {
border: 100px solid black;
border-right: 100px solid blue;
height:300px;
position:relative;
}
#foo:after, #foo:before{
content:'';
background:black;
width:100px;
height:100px;
display:block;
position:absolute;
}
#foo:after{
bottom:-100px;
right:-100px;
}
#foo:before{
top:-100px;
right:-100px;
}
It might be a little messy, but it works. Set the :after and :before elements width height and position to the width of the border.
And that gives this effect:
JSFiddle Demo
I hope my crappy photoshop skills explain borders to you.
If you look in the 4 corners of the square you can see little lines, thats where one border starts and the next one begins.
This will always be in issue :P
You could either make it a background image (crappy way)
or you can use other divs to make the borders (crappy as well)
The first solution would be using a pseudo-element, which you will position absolutely to cover the right border. In order to ensure that it covers the border entirely, you will have to offset its top, bottom and right positions by the negative value of the border width. In this case I have used a width of 5px to better illustrate the example:
#foo {
background-color: #eee;
border: 5px solid grey;
width: 100px;
height: 100px;
position: relative;
}
#foo::before {
content: '';
position: absolute;
top: -5px;
bottom: -5px;
right: -5px; /* move by border width */
background-color: blue;
width: 5px;
}
<div id="foo"></div>
Alternatively, you can use CSS box shadow:
#foo {
background-color: #eee;
box-shadow: inset 0 0 0 5px grey;
width: 100px;
height: 100px;
position: relative;
}
#foo::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 5px;
background-color: blue;
}
<div id="foo"></div>
As others have pointed out, your problem is how borders are drawn in CSS.
<div id="foo">Problem</div>
#foo {
border: 30px solid black;
border-right: 30px solid blue;
}
The simplest way to work around this is to use a pseudo element. Since this workaround is entirely dependent on the value of the border-width, I’ll show an example using an SCSS variable to help make it clear where that width value is coming in.
Note: You don’t need SCSS to solve this problem, using a variable just helps readability/maintainability.
HTML:
<div id="foo"></div>
SCSS:
/* Set SCSS variable */
$border-width: 30px;
#foo {
border: $border-width solid black;
position: relative; /* anchor the absolute positioned ::after element */
}
#foo:after {
content: '';
background: blue;
width: $border-width;
height: 100%;
position: absolute;
right: -$border-width;
}
Demo: http://jsbin.com/cimaxe/6
Hopefully it’s clear that everywhere you see $border-width you can replace it with a value like 30px.

Fix DIV to bottom right corner

I have used html and body attributes to have a gradient background and a flower background for my website.
I have also used a div to have the bottom right hand flower where it is. Works great, but not when scrolling. How do i get the bottom right hand corner image to stick to the bottom of the screen ?
You will want to set position: fixed; instead of position: absolute;.
Here's more info on the Position Property.
.bottomright {
position: fixed;
bottom: 0px;
right: 0px;
}
.demo {
background-color: HotPink;
padding: 20px;
margin: 5px;
}
Hello<br>
<div class="demo bottomright">
I'm a Div!
</div>
there
if you put the flower inside a div and position it absolute bottom and right this will stick it there.
For example, something like this will work
#mystylename{
position:absolute;
bottom:0;
right:0;
}
you may need to tweak it to get it sat where you want and also maybe add a z-index
If you require animation, set you div as absolute before the animation and then after the animation re set it to fixed as the below example.
$('.mydiv').animate({
opacity: 1,
right: "50px",
bottom: "50px",
height: "toggle"
}, 1000, function() {
// Animation complete.
}).css('position','fixed');
css for the above div is below as well.
.mydiv {
text-align: center;
background: #00DD88;
background: -moz-linear-gradient(center top , #00DD88 0%, #00CC00 100%) repeat scroll 0 0 transparent;
border-radius: 30px 30px 30px 30px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
margin: 5px 0 10px 15px;
position: absolute;
right: -980px;
width: 200px;
height: 50px;
display: none;
z-index: 100;
}
I know this is old but it will definitely help someone :)
A css-only trick for this old post is to put a after the div and position the top -1.2em so it overlaps the bottom of the element above it.
html:
<textarea class="no-whitespace-right">This is a test resize it.</textarea>
<span class="float-lower-left">length could go here</span>
css:
.no-whitespace-right {
/* any whitespace to the right and the overlap trick fails */
width: 100%;
}
.float-lower-left {
position: relative;
float: right;
right: 1em;
top: -1.2em;
/* push it up into the element before it. This is a trick for bottom-right */
right: 1em;
z-index: 200;
opacity: 0.5;
font-weight:bolder;
}
https://jsfiddle.net/qwm3pu8d/
You might need to use JavaScript to accomplish this task. Such techniques will accomplish the effect you desire, but they tend not be animate very smoothly. When scrolling, such a "stuck" object will tend to skip and stutter. I found an example here but have not tried it myself. I recommend searching for a few examples and trying out the one that looks cleanest and most modern.
You will want to set position: fixed; instead of position: absolute;

Resources