0

I have a form with text inputs and a tooltip should show up whenever an input is clicked (or better yet, focused), and it should disappear whenever something else is clicked. I know that I should probably use JavaScript's getElementById and attach a click event listener but my knowledge stops there. I'm not sure how to toggle the CSS code I have which is currently working but on hover. I am not looking for :active pseudo-class.

HTML:

<p>
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vitae consequat dui, ut ultricies tortor. Fusce imperdiet augue sit amet magna lobortis eleifend. Sed gravida consectetur magna vitae luctus. Suspendisse potenti. Cras luctus porttitor viverra. Aenean ac magna ullamcorper, ullamcorper sem non, mattis felis. Morbi ultricies pretium dui, quis posuere sapien tristique sit amet. Sed et velit tincidunt, convallis enim sed, imperdiet lectus. In quis diam aliquet, pharetra nisi et, interdum eros. Nullam rutrum lectus at est lacinia facilisis. Nullam eu gravida felis. Suspendisse ut magna id nisi fringilla venenatis. Cras facilisis tellus at erat fermentum congue. Nullam dapibus varius nibh, eu pharetra leo vehicula nec.
</p>
<label>Username</label>
<div data-tip="Only A-Z">
  <span></span>
  <input id='username-input' type="text">
</div>
<label>Password</label>
<div data-tip="8 characters minimum">
  <span></span>
  <input id='password-input' type="text">
</div>
<label>Email</label>
<div data-tip="E-mail is only for registration">
  <span></span>
  <input id='email-input' type="text">
</div>

CSS:

[data-tip] {
    position: relative;

}

[data-tip]::before {
    content: '';
    display: none;
    border-left: 15px solid transparent;
    border-right: 15px solid transparent;
    border-top: 15px solid #ccc;
    position: absolute;
    top: -10px;
    left: 15px;
    z-index: 10;
    font-size: 1em;
    line-height: 2em;
    width: 0;
    height: 0;
}

[data-tip] > span {
  display: none;
  border-left: 16px solid transparent;
    border-right: 16px solid transparent;
    border-top: 16px solid black;
    position: absolute;
    top: -9px;
    left: 14px;
    z-index: 7;
    font-size: 1em;
    line-height: 2em;
    width: 0;
    height: 0;

}

[data-tip]::after {
    display: none;
    content: attr(data-tip);
    position: absolute;
    top: -54px;
    left: 0px;
    border: 1px solid black;
    padding: 10px 20px;
    background-color: #ccc;
    color: black;
    z-index: 9;
    font-size: 0.75em;
    height: 4em;
    text-align: center;
    vertical-align: middle;
    line-height: 2em;
    -webkit-border-radius: 0.5em;
    -moz-border-radius: 0.5em;
    border-radius: 0.5em;
    box-sizing: border-box;
    white-space: nowrap;
    word-wrap: normal;
}

[data-tip]:hover > span,
[data-tip]:hover::before,
[data-tip]:hover::after {
    display: block;
}

JavaScript:

input = document.getElementById('email-input');
input.addEventListener('click', function() {
    /* toggle CSS code */
});

jsfiddle link

Laczkó Örs
  • 1,082
  • 1
  • 18
  • 38
adder
  • 3,512
  • 1
  • 16
  • 28

3 Answers3

1

You're right that you should handle this with Javascript:

var inputs = document.querySelectorAll('.tooltip');
inputs.forEach(function(el){
  el.addEventListener("click", function(e){
      inputs.forEach(function(el2){
        el2.classList.remove("active");
      });
      this.classList.add("active");
  });

});
[data-tip] {
    position: relative;

}

[data-tip]::before {
    content: '';
    display: none;
    border-left: 15px solid transparent;
    border-right: 15px solid transparent;
    border-top: 15px solid #ccc;
    position: absolute;
    top: -10px;
    left: 15px;
    z-index: 10;
    font-size: 1em;
    line-height: 2em;
    width: 0;
    height: 0;
}

[data-tip] > span {
  display: none;
  border-left: 16px solid transparent;
    border-right: 16px solid transparent;
    border-top: 16px solid black;
    position: absolute;
    top: -9px;
    left: 14px;
    z-index: 7;
    font-size: 1em;
    line-height: 2em;
    width: 0;
    height: 0;

}

[data-tip]::after {
    display: none;
    content: attr(data-tip);
    position: absolute;
    top: -54px;
    left: 0px;
    border: 1px solid black;
    padding: 10px 20px;
    background-color: #ccc;
    color: black;
    z-index: 9;
    font-size: 0.75em;
    height: 4em;
    text-align: center;
    vertical-align: middle;
    line-height: 2em;
    -webkit-border-radius: 0.5em;
    -moz-border-radius: 0.5em;
    border-radius: 0.5em;
    box-sizing: border-box;
    white-space: nowrap;
    word-wrap: normal;
}

.tooltip.active > span,
[data-tip].active::before,
[data-tip].active::after {
  display: block;
  }
<p>
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vitae consequat dui, ut ultricies tortor. Fusce imperdiet augue sit amet magna lobortis eleifend. Sed gravida consectetur magna vitae luctus. Suspendisse potenti. Cras luctus porttitor viverra. Aenean ac magna ullamcorper, ullamcorper sem non, mattis felis. Morbi ultricies pretium dui, quis posuere sapien tristique sit amet. Sed et velit tincidunt, convallis enim sed, imperdiet lectus. In quis diam aliquet, pharetra nisi et, interdum eros. Nullam rutrum lectus at est lacinia facilisis. Nullam eu gravida felis. Suspendisse ut magna id nisi fringilla venenatis. Cras facilisis tellus at erat fermentum congue. Nullam dapibus varius nibh, eu pharetra leo vehicula nec.
</p>
<label>Username</label>
<div class="tooltip" data-tip="Only A-Z">
  <span></span>
  <input id='username-input' type="text">
</div>
<label>Password</label>
<div class="tooltip" data-tip="8 characters minimum">
  <span></span>
  <input id='password-input' type="text">
</div>
<label>Email</label>
<div class="tooltip" data-tip="E-mail is only for registration">
  <span></span>
  <input id='email-input' type="text">
</div>
symlink
  • 11,984
  • 7
  • 29
  • 50
1

You don't need javascript to handle this, css input comes with focus pseudo,

I have modified your code, you can run the snippet below:

label { display: inline-block; }

div {
 position: relative;
}

input ~ span {
  display: none;
 position: absolute;
 bottom: 30px; 
}

input ~ span span {
  display: block;
  position: relative;
  border: 1px solid black;
  z-index: 3;
  background-color: #ccc;
  font-size: 1em;
 line-height: 2em;
  border-radius: 0.5em;
  box-sizing: border-box;
  white-space: nowrap;
 word-wrap: normal;
 color: black;
 height: 4em;
  text-align: center;
  vertical-align: middle;
 -webkit-border-radius: 0.5em;
 -moz-border-radius: 0.5em;
  padding: 10px 20px;
}

input ~ span::before {
 content: '';
 display: none;
 border-left: 15px solid transparent;
 border-right: 15px solid transparent;
 border-top: 15px solid #ccc;
 position: absolute;
 bottom: -10px;
  left: 14px;
 z-index: 9;
 font-size: 1em;
 line-height: 2em;
 width: 0;
 height: 0;
}

input ~ span::after {
 content: '';
 display: none;
 border-left: 16px solid transparent;
 border-right: 16px solid transparent;
 border-top: 15px solid black;
 position: absolute;
  bottom: -11px;
  left: 13px;
 z-index: 1;
 font-size: 1em;
 line-height: 2em;
 width: 0;
 height: 0;
}

input:focus ~ span::before,
input:focus ~ span::after,
input:focus ~ span {
 display: block;
}
<p>
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vitae consequat dui, ut ultricies tortor. Fusce imperdiet augue sit amet magna lobortis eleifend. Sed gravida consectetur magna vitae luctus. Suspendisse potenti. Cras luctus porttitor viverra. Aenean ac magna ullamcorper, ullamcorper sem non, mattis felis. Morbi ultricies pretium dui, quis posuere sapien tristique sit amet. Sed et velit tincidunt, convallis enim sed, imperdiet lectus. In quis diam aliquet, pharetra nisi et, interdum eros. Nullam rutrum lectus at est lacinia facilisis. Nullam eu gravida felis. Suspendisse ut magna id nisi fringilla venenatis. Cras facilisis tellus at erat fermentum congue. Nullam dapibus varius nibh, eu pharetra leo vehicula nec.
</p>
<label>Username</label>
<div>
  <input id='username-input' type="text">
  <span><span>Only A-Z</span></span>
</div>
<label>Password</label>
<div>
  <input id='password-input' type="text">
  <span><span>8 characters minimum</span></span>
</div>
<label>Email</label>
<div >
  <input id='email-input' type="text">
  <span>
    <span>E-mail is only for registration</span>
  </span>
</div>
max li
  • 2,417
  • 4
  • 30
  • 44
0

Okay so I went and played a bit with your code and my conclusions are: You over-complicated yourself without a need when decided to build your tooltip with the pseudo-elements ::before and ::after. If you could simply work with a main <div> container for your tooltip and inside it all your other <div> elements that compose its pieces that would be best for you and prevent such issues.

In regards to your question, there is a way to modify pseudo-class in Javascript but it requires quite a bit of coding and seems very overly complicated for the relatively simple challenge you are facing, any way you can check the solution here

I would kindly advise you though to build your tooltip with <div>s and save yourself all this hassle.

You can then do the following to your tooltip. First set a .tooltip{...} class to the tooltip container and its visibility: hidden or display: none depends on your preference and app needs.

If you go with visibility: hidden you can toggle the property like so on click like you desired:

CSS

.tooltip {
   visibility: hidden;
}

JavaScript

document.querySelector("tooltip").classList.add('hidden-tooltip');

To later remove the same class, you could use:

document.getElementById("tooltip").classList.remove('hidden-tooltip');

If you decide to go with display property over the visibility just toggle its values from none to block or flex depends on your needs in that layout. Enjoy

greensin
  • 472
  • 5
  • 8