css tooltip goes off screen - css

I'm using a pure CSS tooltip on this page: http://theroadmap.co/generation/
On small screen, hovering over some longer tooltips on right column causes tooltip to go off screen. Is there any way to get it to wrap when it reaches right end of screen?
Here is code for the tooltip:
/* TOOLTIP TIME */
.tooltip {
position: relative;
text-decoration: none;
}
.tooltip:hover:before {
display: block;
position: absolute;
padding: .5em;
content: attr(href);
min-width: 120px;
text-align: center;
width: auto;
height: auto;
white-space: nowrap;
top: -32px;
background: rgba(0,0,0,.8);
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
color: #fff;
font-size: 1.2em;
z-index: 1000;
}
.tooltip:hover:after {
position: absolute;
display: block;
content: "";
border-color: rgba(0,0,0,.8) transparent transparent;
border-style: solid;
border-width: 10px;
height: 0;
width: 0;
position: absolute;
top: -8px;
left: 1em;
}

var mousex = e.pageX + 20; //Get X coordinates
var mousey = e.pageY + 10; //Get Y coordinates
if((mousey+100)>$(window).height())
{
$('.tooltip')
.css({ top: mousey-100 ,left: mousex })
}
else if((mousex+200)>$(window).width())
{
$('.tooltip')
.css({ top: mousey ,left: mousex-200})
}
else
{
$('.tooltip')
.css({ top: mousey, left: mousex })
}

i had the same problem when i tried to display a file name. seems like the name was too long and there weren't any spaces in it, so i used
word-break: break-all;
in my .tooltip class.
this is my funtion for tooltip:
$('.file_attachments').hover(function () {
var tooltip = '<div class="tooltip"></div>';
// Hover over code
var title = $.trim($(this).attr('title'));
if (title.length > 0) {
$(this).data('tipText', title).removeAttr('title');
$('body').append(tooltip);
$('.tooltip').html(title);
$('.tooltip').fadeIn('slow');
} else {
$('body').append(tooltip);
}
}, function () {
// Hover out code
$(this).attr('title', $(this).data('tipText'));
$('.tooltip').remove();
}).mousemove(function (e) {
var mousex = e.pageX + 20; //Get X coordinates
var mousey = e.pageY + 10; //Get Y coordinates
$('.tooltip').css({top: mousey, left: mousex})
});

Related

Visibility of elements in CSS

I'm writing a React app, but my question I'm thinking is not about React but about CSS. I have a bar from which the user can choose a sort option:
<div className="innerLineVisor">
<div className="sortLine" ref={lineRef}>
{cuisines.map(cuisine =>
<div key={cuisine.id} className="sortButton">{cuisine.value}</div>
)}
</div>
</div>
Here are their styles:
.innerLineVisor {
width: 80%;
height: 40px;
border: #C80303 1px solid;
overflow: hidden;
position: absolute;
box-sizing: border-box;
left: 10%;
bottom: 0;
}
.sortLine {
height: 40px;
background-color: white;
position: absolute;
left: 0;
bottom: 0;
display: inline;
transition: 1s;
}
.sortButton {
float: left;
width: 120px;
padding: 5px 10px;
border: darkgray 1px solid;
border-radius: 10px;
background-color: white;
margin-top: 5px;
margin-left: 5px;
margin-right: 5px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
box-sizing: border-box;
}
Now when one of the buttons does not fit on the left, I can see part of it. And on the right is empty until the button fits completely.
What can I do to see part of the button on the right as well?
This is the arrow code:
function leftMotion() {
setLimitPositions({...limitPositions, right: false})
if (linePosition + step > 0) {
lineRef.current.setAttribute('style', 'left: 0')
setLinePosition(0)
setLimitPositions({...limitPositions, left: true})
return
}
lineRef.current.setAttribute('style', 'left:' + (linePosition + step) + 'px')
setLinePosition(linePosition + step)
if (limitPositions.left && arrowsPressed.left) {
lineRef.current.setAttribute('style', 'left:' + (linePosition + 10) + 'px')
}
}
function rightMotion() {
setLimitPositions({...limitPositions, left: false})
lineRef.current.setAttribute('style', 'left:' + (linePosition - step) + 'px')
setLinePosition(linePosition - step)
const lineVisorWidth = getLineVisorWidth()
if (lineVisorWidth > (lineLength - (Math.abs(linePosition))) - lineVisorWidth) {
const limitRightPosition = lineLength - lineVisorWidth
lineRef.current.setAttribute('style', 'left:' + (-limitRightPosition) + 'px')
setLinePosition(-limitRightPosition)
setLimitPositions({...limitPositions, right: true})
}
}

elements doesnt stick to the grid, css

help me to achieve the expected result.
i have a grid: the red part.
a nested grid: the blue part.
but im not having lucky implementing this on css. the grid is pretty simple, the roulettes with 50% of the screen, a place to put the numbers with 30% of the screen and a "bank" to store numbers with 20% of the screen.
the problem here is the nested grid. in each side of the nested grid should be a roullete, wheel and spin. they should mantain the 1:1 square aspect ratio and scale with the window. but they arent even sticking to the grid.
here is an image of the expected result:
and here is what i get so far:
const sectors = [{
color: "#f82",
label: "Stack"
},
{
color: "#0bf",
label: "10"
},
{
color: "#fb0",
label: "200"
},
{
color: "#0fb",
label: "50"
},
{
color: "#b0f",
label: "100"
},
{
color: "#f0b",
label: "5"
},
{
color: "#bf0",
label: "500"
},
];
const rand = (m, M) => Math.random() * (M - m) + m;
const tot = sectors.length;
const EL_spin = document.querySelector("#spin");
const ctx = document.querySelector("#wheel").getContext('2d');
const dia = ctx.canvas.width;
const rad = dia / 2;
const PI = Math.PI;
const TAU = 2 * PI;
const arc = TAU / sectors.length;
const friction = 0.991; // 0.995=soft, 0.99=mid, 0.98=hard
let angVel = 0; // Angular velocity
let ang = 0; // Angle in radians
const getIndex = () => Math.floor(tot - ang / TAU * tot) % tot;
function drawSector(sector, i) {
const ang = arc * i;
ctx.save();
// COLOR
ctx.beginPath();
ctx.fillStyle = sector.color;
ctx.moveTo(rad, rad);
ctx.arc(rad, rad, rad, ang, ang + arc);
ctx.lineTo(rad, rad);
ctx.fill();
// TEXT
ctx.translate(rad, rad);
ctx.rotate(ang + arc / 2);
ctx.textAlign = "right";
ctx.fillStyle = "#fff";
ctx.font = "bold 30px sans-serif";
ctx.fillText(sector.label, rad - 10, 10);
//
ctx.restore();
};
function rotate() {
const sector = sectors[getIndex()];
ctx.canvas.style.transform = `rotate(${ang - PI / 2}rad)`;
EL_spin.textContent = !angVel ? "SPIN" : sector.label;
EL_spin.style.background = sector.color;
}
function frame() {
if (!angVel) return;
angVel *= friction; // Decrement velocity by friction
if (angVel < 0.002) angVel = 0; // Bring to stop
ang += angVel; // Update angle
ang %= TAU; // Normalize angle
rotate();
}
function engine() {
frame();
requestAnimationFrame(engine)
}
// INIT
sectors.forEach(drawSector);
rotate(); // Initial rotation
engine(); // Start engine
EL_spin.addEventListener("click", () => {
if (!angVel) angVel = rand(0.25, 0.35);
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-template-rows: 50vh 30vh 20vh;
}
.roulettes {
display: grid;
grid-template-columns: 50fr 50fr;
}
#roulette {
display: inline-block;
position: relative;
overflow: hidden;
}
#wheel {
display: block;
}
#spin {
font: 1.5em/0 sans-serif;
user-select: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 30%;
height: 30%;
margin: -15%;
background: #fff;
color: #fff;
box-shadow: 0 0 0 8px currentColor, 0 0px 15px 5px rgba(0, 0, 0, 0.6);
border-radius: 50%;
transition: 0.8s;
}
#spin::after {
content: "";
position: absolute;
top: -17px;
border: 10px solid transparent;
border-bottom-color: currentColor;
border-top: none;
}
#op_roulette {
display: inline-block;
position: relative;
overflow: hidden;
}
#op_wheel {
display: block;
}
#op_spin {
font: 1.5em/0 sans-serif;
user-select: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 30%;
height: 30%;
margin: -15%;
background: #fff;
color: #fff;
box-shadow: 0 0 0 8px currentColor, 0 0px 15px 5px rgba(0, 0, 0, 0.6);
border-radius: 50%;
transition: 0.8s;
}
#op_spin::after {
content: "";
position: absolute;
top: -17px;
border: 10px solid transparent;
border-bottom-color: currentColor;
border-top: none;
}
<body>
<div class="grid" width="100vw" height="100vh">
<div class="roulettes">
<div id="roulette">
<canvas id="wheel" width="300%" height="300%"></canvas>
<div id="spin">SPIN</div>
</div>
<div id="op_roullete">
<canvas id="op_wheel" width="300%" height="300%"></canvas>
<div id="op_spin">SPIN</div>
</div>
</div>
<div id="operation">=</div>
<div id="bank">BANK</div>
</div>
</body>
PS. (the will is made by https://stackoverflow.com/users/383904/roko-c-buljan) i know that the wheel is draw by js, and it only draws in the wheel element. once i get the grid right i will change the code to draw a wheel on the op_wheel element too, so this is not a problem.

CSS Blobs Animation

Trying to make these gooey CSS moving blobs. The basic setup seems to be that you give the circles blur and then add contrast to their container. The issue is that whenever I do that with custom colors the entire element just disappears. I tried it on these demos and same thing. Does anyone know why or know a workaround?
Here is a tutorial I've been following:
https://css-tricks.com/shape-blobbing-css/
Here is the code:
$(document).ready(function() {
$(".dot").hover(function() {
var cur = $(this);
var dest = cur.position().left;
var t = 0.6;
TweenMax.to($(".select"), t, {
x: dest,
ease: Back.easeOut
})
});
var lastPos = $(".select").position().left;
function updateScale() {
var pos = $(".select").position().left;
var speed = Math.abs(pos - lastPos);
var d = 44;
var offset = -20;
var hd = d / 2;
var scale = (offset + pos) % d;
if (scale > hd) {
scale = hd - (scale - hd);
}
scale = 1 - ((scale / hd) * 0.35);
TweenMax.to($(".select"), 0.1, {
scaleY: scale,
scaleX: 1 + (speed * 0.06)
})
lastPos = pos;
requestAnimationFrame(updateScale);
}
requestAnimationFrame(updateScale);
$(".dot:eq(0)").trigger("mouseover");
})
.text {
position: relative;
left: 110px;
top: 10px;
font-family: 'Baskerville', Georgia, serif;
font-size: 17px;
}
a {
color: inherit;
}
.dots {
list-style-type: none;
background: white;
-webkit-filter: blur(5px) contrast(10);
padding: 0;
margin: 0;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
margin-left: -10px;
padding-right: 10px;
position: relative;
left: 100px;
top: 30px;
}
.dot {
display: inline-block;
vertical-align: middle;
border-radius: 100%;
width: 30px;
height: 30px;
background: black;
margin-left: 5px;
margin-right: 5px;
cursor: pointer;
color: white;
position: relative;
z-index: 2;
}
.select {
display: block;
border-radius: 100%;
width: 40px;
height: 40px;
background: black;
//opacity:0.6;
//transition:transform 300ms ease-in-out;
position: absolute;
z-index: 3;
top: 15px;
left: 0px;
pointer-events: none;
}
<div class="text">
<h1>Gooey pagination</h1>
Based on a dribbble by Kreativa Studio. <br />
Made by Lucas Bebber. <br /> <br />
Hover on the dots bellow
</div>
<ul class="dots">
<li class="select"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.13.1/TweenMax.min.js"></script>
If you go to one of their demos and try changing the color to something like pink or #A0D9A8 you'll see what I mean:
This is really interresting. It seems that to work the color must cause a very strong contrast because of the filter rule used. So you will have to use flashy colors to make them appear. The colors pink or #A0D9A8 aren't flashy enought for the blur that's going to make him disappear. So try to use more flashy colors like #e83ce8 that's like a pink color:
$(document).ready(function() {
$(".dot").hover(function() {
var cur = $(this);
var dest = cur.position().left;
var t = 0.6;
TweenMax.to($(".select"), t, {
x: dest,
ease: Back.easeOut
})
});
var lastPos = $(".select").position().left;
function updateScale() {
var pos = $(".select").position().left;
var speed = Math.abs(pos - lastPos);
var d = 44;
var offset = -20;
var hd = d / 2;
var scale = (offset + pos) % d;
if (scale > hd) {
scale = hd - (scale - hd);
}
scale = 1 - ((scale / hd) * 0.35);
TweenMax.to($(".select"), 0.1, {
scaleY: scale,
scaleX: 1 + (speed * 0.06)
})
lastPos = pos;
requestAnimationFrame(updateScale);
}
requestAnimationFrame(updateScale);
$(".dot:eq(0)").trigger("mouseover");
})
.text {
position: relative;
left: 110px;
top: 10px;
font-family: 'Baskerville', Georgia, serif;
font-size: 17px;
}
a {
color: inherit;
}
.dots {
list-style-type: none;
background: white;
-webkit-filter: blur(5px) contrast(10);
padding: 0;
margin: 0;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
margin-left: -10px;
padding-right: 10px;
position: relative;
left: 100px;
top: 30px;
}
.dot {
display: inline-block;
vertical-align: middle;
border-radius: 100%;
width: 30px;
height: 30px;
background: #e83ce8;
margin-left: 5px;
margin-right: 5px;
cursor: pointer;
color: white;
position: relative;
z-index: 2;
}
.select {
display: block;
border-radius: 100%;
width: 40px;
height: 40px;
background: #e83ce8;
position: absolute;
z-index: 3;
top: 15px;
left: 0px;
pointer-events: none;
}
<div class="text">
<h1>Gooey pagination</h1>
Based on a dribbble by Kreativa Studio. <br />
Made by Lucas Bebber. <br /> <br />
Hover on the dots bellow
</div>
<ul class="dots">
<li class="select"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.13.1/TweenMax.min.js"></script>
Check what it says on the entire page over on CSS tricks, about brightness especially.
You just need to change the following and you will see pink blorbs.
.dots{
...
-webkit-filter: blur(5px) contrast(10) brightness(-50);
...
}
.dot {
...
background: /* black */ pink;
...
}
.select { /* EDIT */
...
background: /* black */ pink;
...
}
EDIT: I used a CSS variable in this fiddle:
https://jsfiddle.net/p97qxzew/

Is there a CSS way to automatically set the width of an element based on the size of text strings?

I’m creating a styled select menu in which I’m styling an unordered list that is replacing my select element.
<div class="select">
<select name="distance" id="distance" class="select-hidden">
<option value="5.0 5"><font><font>5 mi</font></font></option>
<option value="6.0 4">6 km</option>
<option value="10.0 4" selected="selected"><font><font>10 km</font></font></option></select><div class="select-styled">10 km</div><ul class="select-options" style="display: none;"><li rel="5.0 5"><font><font>5 mi</font></font></li><li rel="6.0 4"><font><font>6 km</font></font></li><li rel="10.0 4"><font><font>10 km</font></font></li></ul>
</div>
I then have this style
.select {
cursor: pointer;
display: inline-block;
position: relative;
font-size: 16px;
color: #000000;
width: 220px;
height: 42px;
}
Right now I’m hard-coding the width (220px) and my question is can I build this in a less rigid way such that the width will automatically be the width of the longest element name? Here is the Fiddle that illustrates my dilemma — https://jsfiddle.net/n73ao02h/13/ .
How about that: https://jsfiddle.net/n73ao02h/14/
A select-box without any width will always style according to its options. So we use that...
First step is to remove the fixed width.
We get the width in JS before we add display:none to it.
We then generate a temporary element styled-select with zero width to automatically get the padding defined in CSS without hardcoding it.
We then have all we need to calculate the new width of your styled select-box:
/* ... */
var $paddingCalculator = $('<div />', {
'class' : "select-styled test"
}).css({
width : 0,
visibility : "hidden"
}).appendTo("body");
var paddingWidth = $paddingCalculator.outerWidth();
$paddingCalculator.remove();
var selectWidth = $this.width() + paddingWidth;
$this.addClass('select-hidden');
if ( !$this.parent().hasClass('select') ) {
var $wrapper = $("<div />", {
'class' : "select"
}).css({
width : selectWidth
});
$this.wrap( $wrapper );
} // if
/* ... */
 
little addendum:
Keep in mind that both - the original select box and your styled div - need to have the same font-size (and anything text-styling related, such as font-family, font-weight, letter-spacing, ...) so that the calculated dimensions will be correct.
Don't set the width and don't set display:none on the select, plus set white-space:nowrap on your div.select-styled :
$(function() {
$('select').each(function(){
styleSelectMenu($(this));
});
});
// This method applies the styles to our select menu
function styleSelectMenu(selectMenu)
{
var $this = $(selectMenu), numberOfOptions = $(selectMenu).children('option').length;
$this.addClass('select-hidden');
if ( !$this.parent().hasClass('select') ) {
$this.wrap('<div class="select"></div>');
} // if
if ( !$this.next().hasClass('select-styled') ) {
$this.after('<div class="select-styled"></div>');
} // if
var $styledSelect = $this.next('div.select-styled');
$styledSelect.text($this.children('option').eq(0).text());
if ( $styledSelect.parent().find('ul').length > 0 ) {
$styledSelect.parent().find('ul').remove();
} // if
var $list = $('<ul />', {
'class': 'select-options'
}).insertAfter($styledSelect);
for (var i = 0; i < numberOfOptions; i++) {
$('<li />', {
text: $this.children('option').eq(i).text(),
rel: $this.children('option').eq(i).val()
}).appendTo($list);
}
var $listItems = $list.children('li');
// This is the event when someone opens the list
$styledSelect.unbind('click')
$styledSelect.click(function(e) {
e.stopPropagation();
$('div.select-styled.active').each(function(){
$(this).removeClass('active').next('ul.select-options').hide();
});
$(this).toggleClass('active').next('ul.select-options').toggle();
});
// This is the event when someone actually selects something from the list
$listItems.unbind('click.selectStyledItem')
$listItems.bind('click.selectStyledItem', function(event) {
clickListItem($styledSelect, $this, $(this), $list);
});
$(document).click(function() {
$styledSelect.removeClass('active');
$list.hide();
});
var selectedIndex = $this[0].selectedIndex;
if (selectedIndex > 0) {
var name = $this.attr("name")
var selectedText = $( "select[name='" + name + "'] option:selected" ).text();
selectItemFromStyledList($styledSelect, $this, selectedText, $list);
} // if
}
// This is the method that will select an item from the styled list
function selectItemFromStyledList(styledSelect, selectMenu, selectedText, listToHide)
{
$(styledSelect).text(selectedText).removeClass('active');
$(selectMenu).val($(selectMenu).attr('rel'));
$(listToHide).hide();
// Select option in the underlying list so that the form gets submitted
// with the right values
selectedOption = $(selectMenu).find("option").filter(function () { return $(this).html() == selectedText; });
$(selectMenu).find("option[selected='selected']").removeAttr("selected");
$(selectedOption).attr("selected","selected");
} // selectItemFromStyledList
// Called when someone clicks an item from the styled list
// The event data should contain the following parameters:
// styledSelect - the <div> element that contains the styled menu
// selectMenu - the actual form element that contains the items
// listItemClicked - the item that was clicked.
// list - THe <UL> element containig the <li> options
function clickListItem(styledSelect, selectMenu, listItemClicked, list)
{
var $styledSelect = $(styledSelect);
var $selectMenu = $(selectMenu);
var $listItem = $(listItemClicked);
var $list = $(list);
event.stopPropagation();
var selectedText = $listItem.text();
selectItemFromStyledList($styledSelect, $selectMenu, selectedText, $list)
} // clickListItem
#statSearchFields {
vertical-align: top;
font-size: 90%;
}
.selectMenu {
font-family: 'Oxygen', sans-serif;
font-size: 20px;
height: 50px;
-webkit-appearance: menulist-button;
}
.select-hidden {
visibility: hidden;
padding-right: 10px;
}
.select {
cursor: pointer;
display: inline-block;
position: relative;
font-size: 16px;
color: black;
height: 42px;
}
.select-styled {
white-space: nowrap;
}
.select-styled {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: gray;
padding: 11px 12px;
#include transition(all 0.2s ease-in);
&:after {
content:"";
width: 0;
height: 0;
border: 7px solid transparent;
border-color: black transparent transparent transparent;
position: absolute;
top: 16px;
right: 10px;
}
&:hover {
background-color: darken(gray, 2);
}
&:active, &.active {
background-color: darken(gray, 5);
&:after {
top: 9px;
border-color: transparent transparent $select-color transparent;
}
}
}
.select-options {
display: none;
position: absolute;
top: 100%;
right: 0;
left: 0;
z-index: 999;
margin: 0;
padding: 0;
list-style: none;
background-color: darken(gray, 5);
overflow: scroll;
li {
margin: 0;
padding: 12px 0;
text-indent: 15px;
border-top: 1px solid darken(gray, 10);
#include transition(all 0.15s ease-in);
&:hover {
color: gray;
background: black;
}
&[rel="hide"] {
display: none;
}
}
}
#statSearchContainer {
padding: 10px;
font-family: "Calibre", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
background-color: tan;
display: table;
}
#statSearchContainer h1 {
margin: 5px 0;
font-size: 1.0em;
}
#stat-search-form {
display: block;
padding: 0px;
}
#stat-search-form form input {
vertical-align: middle;
}
#statSearchFields {
vertical-align: top;
font-size: 90%;
}
.searchField {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="statSearchContainer">
<div class="searchField">
Distance<br/>
<select name="distance" id="distance"><option value="5.0 5">5 mi</option>
<option value="6.0 4">6 km</option>
<option selected="selected" value="10.0 4">10 km</option></select>
</div>
<input alt="Search" type="image" src="/assets/magnifying-glass-0220f37269f90a370c3bb60229240f2ef2a4e15b335cd42e64563ba65e4f22e4.png" class="search_button">
</div>
</div>

jQplot with tooltip for the peak value?

Is there a way to display a tooltip or bubble as per the image below to show the highest value in the line graph? It should be visible at all time not just when roll over with the mouse.
Does jQplot support this? If not, is there any other graphing librabry that does this?
Many thanks.
With jqplot, this is possible using the pointLabels plugin:
JS:
$(document).ready(function(){
var line1 = [[0,14,null],[1,32,null], [2,41,null], [3,44,'Hello World!'], [4,40,null], [5,47,null], [6,53,null], [7,67,null]]; // Only the 'Hello World' will have a label
var plot1 = $.jqplot('chart1', [line1], {
title: 'Chart with Point Labels',
seriesDefaults: {
showMarker:false,
pointLabels: { show:true }
}
});
});
CSS for bubble (from here):
#chart1 .jqplot-point-label {
width: 100px;
height: 25px;
padding: 0px;
background: #CC857E;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
text-align: center;
padding-top: 10px;
margin-bottom: 8px;
}
.jqplot-point-label:after
{
content: '';
position: absolute;
border-style: solid;
border-width: 15px 10px 0;
border-color: #CC857E transparent;
display: block;
width: 0;
z-index: 1;
bottom: -10px;
left: 40px;
}
Produces this (fiddle here):
In the highstock you can use flags like this
Other options is using renderer to add custom shapes: http://api.highcharts.com/highstock#Renderer

Resources