We are using some code to make a tooltip appear while hovering over text or an icon. Using a transform we are then able to center the tooltip, no matter what size it is, so we can have the size scale with the content of the tooltip: http://jsfiddle.net/z8wxdjzu/4/
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
background: orange;
display: none;
text-align: center;
max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
right: auto;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0%);
}
.abbr:hover .tooltip {
display: inline-block;
}
<div class="position-me">
<span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet.</span>
</span>
</div>
The problem is that even when providing a larger maximum width, a new line is added in the tooltip after every word. Instead we want the tooltip to fill the entire width (provided with max-width) before moving to a second line.
We don't want to set a fixed width, because some tooltips are rather short and we don't want a lot of empty space in the tooltip. How can we prevent the line breaks from happening?
EDIT: The max-width is actually important, since some of the tooltips are long enough to span several lines, so just removing it and using a whitespace: nowrap is going to be insufficient, unless we do manual line breaks, which I'd rather prevent.
The problem is that your tooltip span wants to have it's width be less or equal to the parent's width, in this case the span.abbr.
So to fix it we can add another div around the tooltip that is a bit larger but outside the flow of the other text, and it works.
Edit: I edited the snippet to center the tooltip. I also left in the red background for the surrounding div to show the trick that I apply here.
Example snippet:
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.abbr div {
position: absolute;
top: 0;
left: 50%;
background-color: red;
width: 200px;
height: 2px;
}
.tooltip {
background: orange;
display: none;
text-align: center;
max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.abbr:hover .tooltip {
display: inline-block;
}
<div class="position-me">
Bla bla bla
<span class="abbr">
HOVER ME
<div><span class="tooltip">Lorem ipsum dolor sit amet.</span>
</div></span>
some more text here.
</div>
Here the fixed fiddle: Fiddle
You need to remove position:absolute and then add width:auto on .tooltip class and add display:inline-block; to .abbr:hover .tooltip
You can't prevent breaking (which you can do) without losing the max-width.
Just adding white-space:nowrap will stop the text breaking but will cause overflow of the span. So remove the max-width and all is good.
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
background: orange;
/*display: none; */
/* disabled for demo */
text-align: center;
white-space: nowrap;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.abbr:hover .tooltip {
display: block;
}
<div class="position-me"> <span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet.</span>
</span>
</div>
i changed your css file this way and it worked !
.position-me {
margin: 10%;
}
.abbr {
//position: relative;//notice here
}
.tooltip {
background: orange;
display: none;
text-align: center;
//max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-100%, 200%);//notice here !!!
}
.abbr:hover .tooltip {
display: block;
}
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
max-width: 200px;
padding: 3px 8px;
color: #ffffff;
text-align: center;
text-decoration: none;
background-color: #000000;
border-radius: 4px;
display:none;
}
.abbr:hover .tooltip {
display:block;
}
<div class="position-me"> <span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet. rerterte rtertertert</span>
</span>
</div>
This should be the solution: http://jsfiddle.net/z8wxdjzu/7/
Related
I have an image that has a hover state that changes two things: it darkens the image and it displays absolute positioned text over the image. The issue I'm having is when I hover over the text the image is no longer showing darkened. I've tried adding a hover state to the text as well. The image and hover text are siblings so I tried using the ~ following-sibling combinator like this: .hovertext:hover ~ .hoverimg but obviously I'm not using it correctly.
Code
.wrapper {
position: relative;
text-align: center;
}
.hovertext {
display: none;
color: white;
font-size: 30px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.wrapper:hover .hovertext {
display: block;
}
.hoverimg:hover,
.hovertext:hover~.hoverimg {
filter: brightness(50%);
}
<div class="wrapper">
<img class="hoverimg" src="https://loremflickr.com/320/240">
<div class="hovertext">HOVER TEXT</div>
</div>
Is there a way to show both hover states with CSS only?
Use pointer-events:none to the text if there is no hover or click event on text
Stack Snippet
.wrapper {
position: relative;
text-align: center;
}
.hovertext {
display: none;
color: white;
font-size: 30px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
pointer-events: none;
}
.wrapper:hover .hovertext {
display: block;
}
.hoverimg:hover,
.hovertext:hover~.hoverimg {
filter: brightness(50%);
}
<div class="wrapper">
<img class="hoverimg" src="https://loremflickr.com/320/240">
<div class="hovertext">HOVER TEXT</div>
</div>
And if you are planning to add event on the text then you can change img and text properties on .wrapper class hover
.wrapper {
position: relative;
text-align: center;
}
.hovertext {
display: none;
color: white;
font-size: 30px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.wrapper:hover .hovertext {
display: block;
}
.wrapper:hover .hoverimg {
filter: brightness(50%);
}
<div class="wrapper">
<img class="hoverimg" src="https://loremflickr.com/320/240">
<div class="hovertext">HOVER TEXT</div>
</div>
There is no way of selecting the previous element i.e. changing the styling of previous element using CSS as you are trying using sibling selector .hovertext:hover ~ .hoverimg, to make use of sibling selector here you need to make some changes in your html markup as below,
.wrapper {
position: relative;
text-align: center;
}
.hovertext {
display: none;
color: white;
font-size: 30px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
z-index: 9;
}
.wrapper:hover > .hovertext {
display: block;
}
.hoverimg:hover,
.hovertext:hover ~ .hoverimg {
filter: brightness(50%);
}
<div class="wrapper">
<div class="hovertext">HOVER TEXT</div>
<img class="hoverimg" src="https://loremflickr.com/320/240">
</div>
In the above codes I have changed your HTML markup, thus now .hoverimg is sibling of targeted element i.e. .hovertext, so now every-time when you hover .hovertext or .hoverimg it adds assigned styling.
Hey guys I had to create simple dots on a carousel like so:
And hence I used the following method:
.banner-nav-dots > li > a {
position: relative;
}
.banner-nav-dots > li.active > a:after {
content: '';
background: #6e2c91;
height: 5px;
width: 5px;
display: inline-block;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
-o-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
border-radius: 50%;
}
Now that should have really centered the dot , but as can be seen on THIS LINK, they are not exactly aligning in the center. Why? Why are they not aligning in the center?
Below is a MVCE:
.circle {
position: relative;
box-sizing: border-box;
display: inline-block;
border: 2px solid #6e2c91;
border-radius: 50%;
height: 15px;
width: 15px;
}
.circle:after {
position: absolute;
content: '';
display: inline-block;
height: 5px;
width: 5px;
top: 50%;
left: 50%;
border-radius: 50%;
background: #6e2c91;
transform: translate(-50%, -50%);
}
<div class='circle odd-numbered'></div>
I am more interested in the WHY part. Can somebody explain please?
P.S. this absolute position method combined with transform has always worked for me, but just on this instance its caused this issue and I don't know why. Checked both in FF and Chrome.
The problem seems to be due to a combination of odd numbered dimensions for parent container (height: 15px, width: 15px) and the 50% value for positioning attributes on child (top: 50%, left: 50%). This means that the actual calculated value will be 5.5px ((15px - 4px) / 2) for left and top (15px - 4px due to box-sizing: border-box also being applied on the parent).
When such fractional values are encountered, it looks like the browsers round-off the value. I couldn't find anything about this in the specs (whether it should be a round-up or down) and there aren't many recent articles on the net also about this particular thing. However, I did manage to find this old article which says that each browser treats them differently. Some round it down whereas others round it up. Either ways, the child element is not going to at the exact center.
The fix for this case seems to be to set an even-numbered value for the parent's dimensions.
.circle {
position: relative;
box-sizing: border-box;
display: inline-block;
border: 2px solid #6e2c91;
border-radius: 50%;
}
.odd-numbered {
height: 15px;
width: 15px;
}
.even-numbered {
height: 16px;
width: 16px;
}
.circle:after {
position: absolute;
content: '';
display: inline-block;
height: 5px;
width: 5px;
top: 50%;
left: 50%;
border-radius: 50%;
background: #6e2c91;
transform: translate(-50%, -50%);
}
<h4>Odd Numbered Dimensions - PROBLEM </h4>
<div class='circle odd-numbered'></div>
<h4>Even Numbered Dimensions - NO PROBLEM </h4>
<div class='circle even-numbered'></div>
I currently have an ng-repeat that looks like this:
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}"/>
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
Here is the CSS pulled from this codePen:
.corner-ribbon{
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky{
position: fixed;
}
.corner-ribbon.shadow{
box-shadow: 0 0 3px rgba(0,0,0,.3);
}
.corner-ribbon.bottom-right{
top: auto;
right: -50px;
bottom: 25px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green{background: #2c7;}
I am trying to figure out how to get the ribbon to be restricted to the wrapper class. Does anyone know how I can do that? so I'm still using the same ribbon, but instead of being in the bottom right of the screen, it is at the bottom right of the image for which it applies?
you need to use relative/absolute position and reset display of .wrapper to shrink on image. Then add overflow:hidden to cut off edges of ribbon:
.corner-ribbon {
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky {
position: absolute;
}
.corner-ribbon.shadow {
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
}
.corner-ribbon.bottom-right {
top: auto;
right: -50px;
bottom: 30px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green {
background: #2c7;
}
.wrapper {
position: relative;
display: table-cell;/* or inline-block or float */
overflow: hidden;
}
img {
display: block;
}
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}" src="http://lorempixel.com/300/200" />
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
The class has fixed positioning.
.corner-ribbon.sticky{
position: fixed;
}
So for exact css you may not be able to attach ribbon to each img, rather ribbon would go to specific place in window only. However, you can adjust css a bit. Make wrapper class relative, and .corner-ribbon.sticky absolute position. Then adjust your css fot top/bottom/left/right properties to align them.
.wrapper{
position: relative;
}
.wrapper .corner-ribbon.sticky{
position: absolute;
/* put top/bottom/left/right values here*/
}
I have a design for a top-of-the-page dashboard in HTML that has the following requirements:
Everything should be vertically centered within the dashboard.
It should have a button in the exact center.
It should have text centered at the 25% and 75% marks.
It should have one last group of text all the way to the left.
Like this, but not with horrible colors:
I was able to achieve the top three goals (or very close to it) using display: flex and giving appropriate sizes to everything, like so:
HTML:
<div class="header">
<span class="left-text">LEFT TEXT</span>
<button class="button">BUTTON</button>
<span class="right-text">RIGHT TEXT</span>
</div>
CSS:
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.button {
height: 26px;
width: 100px;
order: 2;
flex-grow: 0;
}
.left-text {
order: 1;
flex-grow: 1;
text-align: center;
}
.right-text {
order: 3;
flex-grow: 1;
text-align: center;
}
This last requirement, though, is really throwing me for a loop; without everything being nice and centered, I feel like flex is going to need some ugly adjustments. I feel like this would be much easier if I could layer div or span elements on top of each other however I liked, but something tells me I can't. Are there any good solutions for this problem? Am I close?
EDIT: added image of mockup.
Hopefully this will work for you, basically it adds the more-left class and positions it relative to the header, and you move it to the left as necessary, whatever is fitting.
HTML
<div class="header">
<span class="more-left">MORE LEFT</span>
<span class="left-text">LEFT TEXT</span>
<button class="button">BUTTON</button>
<span class="right-text">RIGHT TEXT</span>
</div>
CSS
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.button {
height: 26px;
width: 100px;
order: 2;
flex-grow: 0;
}
.left-text {
order: 1;
flex-grow: 1;
text-align: center;
}
.right-text {
order: 3;
flex-grow: 1;
text-align: center;
}
.more-left {
position: relative;
left: 15%; /* adjust as neccessary */
}
I ended up ditching Flexbox entirely, going with absolute positioning and translate in order to get the results I wanted. Here's the final code:
HTML
<div class="header">
<span class="more-left v-center">MORE LEFT</span>
<span class="left-text abs-center">LEFT TEXT</span>
<button class="button abs-center">BUTTON</button>
<span class="right-text abs-center">RIGHT TEXT</span>
</div>
CSS
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
}
.v-center {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
.h-center {
position: absolute;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
.abs-center {
position: absolute;
top: 50%;
-webkit-transform: translate(-50%,-50%);
-moz-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
-o-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
.button {
height: 26px;
width: 100px;
left: 50%;
}
.more-text {
left: 10px;
}
.left-text {
left: 25%;
}
.right-text {
left: 75%;
}
EDIT: it occurred to me that you can't really combine v-center and h-center, because one of the transform entries will completely overwrite the other, instead of combining them. Hence the abs-center class.
I'm trying to center an inner element using CSS, and for some reason the inner element is centering based on the top left corner, rather than its center: http://codepen.io/anon/pen/WvxeEo
HTML:
<div class="topic">
<span class="title-box">hello!</span>
</div>
CSS:
.topic {
background-color: #84BACE;
border: 1px solid #e8e8e8;
width:500px;
height:500px;
position: relative;
}
.title-box {
background-color: #000;
color: #fff;
font-size: 60px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);"
}
Is there a way to set it so that it's properly centered? The inner element will be of unknown width/height, as it's dynamic text.
Thanks!
Try this — http://codepen.io/sergdenisov/pen/ZGOzrr:
.topic {
background-color: #84BACE;
border: 1px solid #e8e8e8;
width:500px;
height:500px;
position: relative;
}
.title-box {
background-color: #000;
color: #fff;
font-size: 60px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
I made one simple change to your code here.
I hope this is what you were asking. The reason "hello" was centered in the blue instead of the page was that that span was inside the blue div. I simply moved the span outside of the div.
<div class="topic"></div>
<span class="title-box">hello!</span>