How can I pop up the contents of a mostly undisplayed element when it is moused over?
Given
Some text.<span class="note">Note contents.</span> Text continues.
I’d like to replace the note with, say, an * (or maybe a block of color). When that is hovered over, the note contents would pop up over the underlying text (over it, not inline).
Something like:
.note {position: absolute;
display: none}
.note::before
{display:inline;
contents: "*"}
.note:hover
{display: inline}
But of course that does not work, since .note {display:none} also hides the ::before child.
I could do this:
.note {font-size: 0}
.note::before
{content: "*";
font-size: initial}
.note:hover
{font-size: initial}
but that expands the note inline and I need it instead to overlay the text that continues after the note.
If I could change the HTML, I could add <span>*</span> before the note, and trigger the pop-up on that. But I can’t change the source HTML.
CSS3 and SASS are OK, but I can’t use Javascript.
Use visibility
.note {
display:inline-block;
white-space:nowrap;
width:5px;
visibility: hidden;
background:#fff;
}
.note::before {
visibility: visible;
content: "*";
}
.note:hover {
visibility:visible;
width:auto;
white-space:normal;
position:absolute;
}
Some text.<span class="note">Note contents.</span> Text continues. Something like:
Related
This is likely something I am just stupidly overlooking, but would you please tell me why hovering over the second division element doesn't cause the background color of the first letter to change to rgb(50,50,50) from rgb(150,150,150)?
Hovering over the first division, which starts out with no styling on the first letter, reacts to the style changes upon hover. But the second division, which starts out with the same styles that the first displays upon hover, does not change to the darker background upon hover.
I'm using the latest version of Firefox developer edition. I see now that it works in Chrome; so must be a Firefox issue.
Thank you.
div > p:before { content: 'This text.'; }
div:nth-child(2) > p::first-letter,
div:first-child:hover > p::first-letter
{
float: left;
padding: 0.5rem;
background-color: rgb(150,150,150);
}
div:nth-child(2):hover > p::first-letter
{
background-color: rgb(50,50,50);
}
<div><p></p></div>
<div><p></p></div>
This snippet works in Firefox. It seems that to get the ::first-letter to be styled both without and with :hover a letter has to be there apart from the content added by :before or :after.
div > p:after { content: 'his text.' }
div > p::first-letter
{
float: left;
padding: 0.5rem;
background-color: rgb(150,150,150);
}
div:hover > p::first-letter
{
background-color: rgb(70,70,70);
color: white;
}
<div><p>T</p></div>
I applied #Sydney Y's solution to the above snippet just to show that it works in Firefox. I don't think it is an isue of the :hover not being recognized because the snippet above recognizes it. It appears to be an issue of not including the text added through :before { content: ... } such that there is a first letter to which to apply the style. But adding no content on :hover using :after seems to alter that and works for variable content.
I realize that this of little interest to anyone who doesn't want to use drop caps and change their style based on hover.
div > p:before { content: 'This text.' }
div > p::first-letter
{
float: left;
padding: 0.5rem;
background-color: rgb(150,150,150);
}
div:hover > p::first-letter
{
background-color: rgb(70,70,70);
color: white;
}
div:hover > p:after { content: ''; }
<div><p></p></div>
Yep, just some mix-ups, your accessors are correct. Each block of CSS needs to apply to both divs:
div > p:before { content: 'This text.'; }
div> p::first-letter {
padding: 0.5rem;
background: red;
}
div:hover> p::first-letter{
background: black;
}
div:hover > p:after { content: ''; }
Thanks for the snippet, that's cool!
Edit: getting closer! Code is updated. Still attempting on Firefox.
Edit: Solved, kind of. It works, but it's kind of a hack. The
issue: In Firefox the hover doesn't trigger a repaint in this specific
instance, so I added an empty bit of content on hover because the
:after or content seem to have a kind of a hook. You may be able to
achieve the same thing with a different hack other than content.
But good news is: this works in both Chrome and Firefox.
Awesome problem. I can't imagine ever coming across this issue again, but it was super interesting to troubleshoot.
There is a bug in firefox that nth-child() is not going to work on syntax that's why it is not working. Anyway if not want the same functionality as first one with different color this can be done with you just need to put hover in front of this code
"div:nth-child(2) > p::first-letter,div:first-child:hover > p::first-letter ". I hope this will help. https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
I am implementing a close button on an element containing text with CSS. The close button is generated content from a pseudo element with content:'X';. I need the cursor to become a pointer on that "X" so I used :
cursor:pointer;
It works fine in Chrome and Firefox but it doesn't seem to work in Internet Explorer (testing on IE11 windows 7).
DEMO (test in IE)
I also tried with cursor:hand; but it doesn't solve the issue. How can I make the cursor a pointer while hovering the "X" but not on the text of the div?
Relevant code :
div{
font-size:2em;
position:relative;
display:inline-block;
}
div::before{
content:'X';
cursor:pointer;
display:block;
text-align:right;
}
<div>some text</div>
--EDIT--
I am aware that making a child or sibling in the markup and applying cursor:pointer; to it will work but I would like to minimize markup and use a pseudo element for the close button as it has no semantic value.
I'm really late to the game, but I just now figured out a solution to this problem.
This solution allows a pointer on the child element, while retaining a default cursor on the parent element.
(See the accepted answer here for a solution that doesn't include keeping the parent element's cursor default: cursor: pointer doesn't work on :after element?)
First of all, for this hacky solution, you have to give up the ability to interact with the parent element using the mouse.
Set the parent element to cursor: pointer.
Then, setting the parent element to pointer-events: none will allow you to "click/hover through" the parent element.
Then, for the pseudo element, just re-enable pointer events with pointer-events: auto.
Voila!
div{
font-size:2em;
position:relative;
display:inline-block;
/* remove ability to interact with parent element */
pointer-events: none;
/* apply pointer cursor to parent element */
cursor:pointer;
/* make it more obvious which is child and which parent for example*/
background: darkred;
}
div::before{
content:'X';
display:block;
text-align:right;
/* restore ability to interact with child element */
pointer-events: auto;
/* make it more obvious which is child and which parent for example*/
width: 30px;
text-align: center;
background: white;
}
<div>some text</div>
I believe that it's not working in pseudo elements in IE,
What I'm use to do is add cursor: ponter to main element.
If you need to add cursor: pointer to pseudo element only, than only way is to add child element
like:
<div><span></span>some text</div>
div{
font-size:2em;
position:relative;
display:inline-block;
}
div > span{
cursor:pointer;
}
div > span::before{
content:'X';
display:block;
text-align:right;
}
But than is no point to using pseudo class...
demo
HTML:
<div>
<div id="closebutton">
X
</div>
some text
</div>
css:
div{
font-size:2em;
position:relative;
display:inline-block;
}
div#closebutton{
cursor:pointer;
display:block;
text-align:right;
}
DEMO
demo
div{
font-size:2em;
position:relative;
display:inline-block;
border:1px solid #000;
margin:20px;
padding:20px;
}
div:after{
cursor:pointer;
display:block;
position:absolute;
height:20px;
width:20px;
top:-10px;
right:-10px;
content:'X';
font-size:15px;
}
<div>
some text
</div>
In order to make IE 7,8,9,10 behave like regular browsers that can deal with pseudo selectors, I always use IE7.js, a JavaScript library to make Microsoft Internet Explorer behave like a standards-compliant browser. It fixes many HTML and CSS issues related to Internet Explorer. An alternative would be modernizr.js which is a good implementation to get pseudo selectors working with IE. I hope, that helps.
To seperate the links in navigation I have set the following
#menu-main li a:after{
content: " * ";
}
The current item gets additional
text-decoration: underline;
my problem now is, that the " * " is also underlined, but shouldn't
I have tried to add
#menu-main li a:after{
text-decoration: none !important;
}
but it has no effect
Does anyone have an idea how to keep the text underlined but not the :after content?
In normal flow, the pseudo element expands the dimensions of the element, and what you see is the underline of the underline of the link itself. Add a:after {text-decoration: line-through;} to verify.
Here's a proposed solution: http://jsfiddle.net/Ronny/Smr38/
Basically, when using position: absolute for the pseudo-elements they no longer affect the dimensions of their parent elements, so the underlines are cut at the right place. You still need to take care of things like pointer events, hover state and focus rings, but I left at least the latter for you to figure out.
if you're in control of markup, you could insert a span in your link
<span>your link</span>
and use this css
a { text-decoration: none }
a span { text-decoration: underline }
doing so, the content injected into the :after pseudoelement won't be underlined
otherwise, you may apply the style to li:after (if it is possibile) like so
#menu-main li:after{
content: " * ";
}
It's an old question, but it's what you find using Google so I thought I'd share my solution when you need the pseudo-element to contribute to the size of the "parent" and absolute positioning is not an option for some reason:
#menu-main li a:after{
content: " * ";
display:inline-block; /* So we can set a width */
width: 0;
margin-left: 10px; /* "Size" of the Pseudo-element */
}
Since the width is 0, it does not display a text-decoration.
This also involves less code and less dependencies among your styles compared to the accepted answer.
In my case i don't even need the width, it just works adding inline-block.
Lets say this markup:
<div id="socialMedia">
<a class="Twitter">Twitter</a>
</div>
What i want is only to be visible the first letter of the text (in this case, just a T)
(Actually I won't end up using it but I am curious about this; sure can be helpfull later)
So this was my a attempt:
#socialMedia .Twitter{
display:none;
}
#socialMedia .Twitter:first-letter {
display: block !important;
}
I was able to check that it won't achieve it. Question is why? and is there some work-around this?
-EDIT-
We are looking for IE=+7/8 version capable solutions..
Salut
Try something like this:
.Twitter {
font-size: 0;
}
.Twitter:first-letter {
font-size: 12px;
}
<div class="Twitter">Twitter</div>
Maybe this is not the best solution, but it works.
Edit: Disclaimer: this does not work according to comments. Please don't use as-is without checking it fits your needs.
If you check the specification for the :first-letter pseudo-element, you'll notice the following:
The :first-letter pseudo-element must select the first letter of the first line of a block, if it is not preceded by any other content (such as images or inline tables) on its line.
The important word here is "block."
You are trying to use the pseudo-element on an <a/> tag with class of Twitter. By default, anchor tags are inline elements (not block level elements).
For your given markup, one solution to your problem would be to style the anchor this way:
.Twitter {
display:block;
visibility:hidden;
}
.Twitter:first-letter {
visibility:visible;
}
I'm not sure exactly what you are going for, but that is good enough for experimental purposes. Check out a demo here: http://jsfiddle.net/H7jhF/.
Another way is to use color: transparent
.twitter{
display: block;
color: transparent;
}
.twitter:first-letter{
color: #000;
}
<div id="socialMedia">
<a class="twitter">Twitter</a>
</div>
JSFiddle
However, this won't work for lte IE8.
References:
IE7 IE8 IE9 color:transparent property
color: transparent is not working in Internet Explorer
What you're doing is like hiding a parent element and trying to show one of its children, it won't work because the parent's style overrides it. The parent element also has to be a block level element for it to work. Like a div or p tag, or display: block; on the a tag.
Here's something using color:
HTML
<div id="socialMedia">
<a class="Twitter">Twitter</a>
</div>
CSS
body {
background-color:#FFF;
}
.Twitter{
display: block;
color:#FFF;
}
.Twitter:first-letter {
color:#000;
}
shoot the content off the page and show the letter using dynamic content:
.twitter{
text-indent:-9999px;
display:block;
position:relative;
}
.twitter:before,.twitter::before{
content:"T";
position:absolute;
width:10px;
height:15px;
z-index:100;
text-indent:9999px;
}
at play in this fiddle:
http://jsfiddle.net/jalbertbowdenii/H7jhF/67/
Why not just use JavaScript and split the string into an array and use the first item in the array. Or charAt()
The pure-CSS answers use visibility and color tricks to hide the remaining letters, but they are still present and affecting layout. It could cause layout issues, e.g. if you wish to float the element and put something beside it.
I found a funny way to do this without hidden elements. The trick is to shrink the entire word down to almost nothing and then blow up just the first letter. It's a bit like OP was trying to do, but it works because it's operating on a continuous spectrum rather than display: none which just shuts down anything inside it. (Kind of an analogue > digital situation.)
Demo
HTML:
<div>Ding Dong</div> and other stuff
CSS:
div {
font-size: 0.0000016px;
float: left;
}
div::first-letter {
color: red;
font-size: 10000000em;
}
Result:
Here's what I do:
.Twitter{
display:block;
width:1ch;
overflow:hidden;
white-space: nowrap;
}
I appear to have found a flaw with CSS3 transitions. Hopefully not though. Here is the dilemma.
.element a span {
display:none;
opacity:0;
position:absolute;
top:-10px;
-webkit-transition-property:top, opacity;
-webkit-transition-duration:500ms;
}
.element a:hover span {
display:inline;
opacity:0.8;
position:absolute;
top:10px;
}
The transition does not work like this at all. If one removes the display:none attribute then it does work, however we need in this case the display:none attribute on our link so that it cannot be interfaced with before hover.
Any ideas?
Marvellous
you could try put overflow: hidden on the a, that way the span should appear invisible, without the need to use display: none; as you have moved it 10px up.
or instead of display:none; try use visibility:hidden;
Changing display:none to display:inline makes the other properties moot as far as transitions are concerned. So separate the display:none/display:block change from the class change, using setTimeout. The browser needs to see them as separate changes in order to apply your transition. Sadly I think this means you can't just use :hover but will need a JS event handler on hover.
Specifically, I would use an inline style attribute of style="display:none" that you add or remove with JS, and take display:none out of the stylesheet.
Then, in JS, after removing display:none (explicitly or via the :hover pseudoclass's style rule), use a setTimeout function that explicitly adds/removes the class. That way the "this is display:inline" change is a discrete, earlier paint-able action from the other style property changes that you want the transition rules applied to.
In the opposite direction, change the class back in an event handler, and use a setTimeout function to set display:none as an inline style. The timeout will need to match the transition duration of course (so that display:none happens after the transition is complete).
or you can try using width or height 0 combined with overflow hidden on the invisible element so it doesn't disturb any of the other elements whilst preserving the transitions.
ie.
.element a span {
overflow: hidden;
height: 0;
width: 0;
opacity:0;
position:absolute;
top:-10px;
-webkit-transition-property:top, opacity;
-webkit-transition-duration:500ms;
}
.element a:hover span {
overflow: visible;
height: ???px;
width: ???px;
opacity:0.8;
position:absolute;
top:10px;
}
I would go with JS. CSS transitions suck with heights.
Here is what I used to make a click expand function, you could change a few things and do the same on a hover
// Dropdown
$(function(){
// Target the ul sibling to keep it generic
var selector = $('.dropdown article > ul').siblings().addClass('selector');
selector.click(function(){
var targetUl = $(this).siblings('ul');
if (targetUl.hasClass('open')) {
targetUl.removeClass('open').slideUp();
} else {
targetUl.slideDown().addClass('open');
}
});
});