简体   繁体   中英

How to change text to invisible, but still show underline?

I made a studying tool using Javascript and PHP. There's a toggle that shows/hides keywords in a paragraph, so the user can mentally "fill in the blanks".

How I've done this so far is that the all the keywords are underlined, and I use a DOM selector to select all innerHTML in u tags.

<p>
  Example sentence, <u>this</u> is a <u>keyword</u>.
</p>
<button onClick='hideKeywords()'>Hide Keywords</button>

<script>
  function hideKeywords() {
    var x = Array.from(document.getElementsByTagName('u'));
    for (var i = 0; i < x.length; i++) {
      x[i].style.visibility = "hidden";
    }
  }
</script>

This works as intended - the "keywords" are blanked out and the flow of the document is unaffected, since the keywords still take up the same space that they would normally take.

One downside is that in paragraphs with particularly long "keywords", the paragraph's line structure is disrupted and it looks like text is just floating randomly in space. This would be fixable if I could somehow change visibility such that the words in the keywords are hidden and the text-decoration (underline) still shows. This retains the line structure.

I thought about using Javascript to replace every character in the keyword with underscores, but two more problems pop up. One thing is that even if the number of characters stay the same, the width might change.. For example, "apple" is not the same physical length as "______". This is not ideal as the document flow would change. A second problem is that I can't think of any way to get the keywords back after converting them into underscores.

One workaround is instead of changing the visibility to "hidden", I could change the background-color to the same color as the text. This blocks out the text, but the line structure and document flow are both preserved. However, I do hope to find a way to implement my original idea, so any suggestion is appreciated!

Update: I would prefer not to add any additional divs to the keywords. The user can add new entries using a rich text editor, so declaring a keyword is as easy as underlining it in the text editor.

You can do it with css adding a pseudo-element and instead of using visibility hidden, using color: transparent, like this:

u{
  position:relative;
}
u::after{
  content: ' ';
  display:block;
  position:absolute;
  bottom:0;
  left:0;
  width: 100%;
  height:1px;
  background-color:#000;
}

And in the script

<script>
  function hideKeywords() {
    var x = Array.from(document.getElementsByTagName('u'));
    for (var i = 0; i < x.length; i++) {
      x[i].style.color = "transparent";
    }
  }
</script>

https://codepen.io/anon/pen/ROoMaM

I would probably implement this using your second method. Set the text colour to the same as the background then add a bottom border to the element. Preserves the spacing and allows you to quickly check if you are right by just highlighting the line. Also, if you give the keyword wrapper element a class you can easily just toggle the color of the hidden text, and retain the underlines so you can see what has changed.

 div { color: black; } span { color: white; text-decoration: none; border-bottom: 2px solid green; }
 <div> This <span>is hidden</span> with an underline </div>

You'd have to find some way to get the div positioned under the hidden text, but you can use the following code to create a div with the width of the text. I might come back later after answering and find a way to position the div.

In your HTML, let's say you have a phrase, foo bar , that you want hidden. You will assign an id to it with the code: <p id="foo">foo bar</p>

Here is the CSS:

#foo {
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap;
}

Then in your Javascript, you can use the following code:

var fontSize = 20;                          //this defines a font size   
var foo = document.getElementById("foo");
foo.style.fontSize = fontSize;              //this sets the style as the font size
var width = (foo.clientWidth) + "px"

var div = document.createElement("div");
div.style.width = width;
div.style.height = 2px;
div.style.background = "red";      //makes the underline visible

document.getElementById("main").appendChild(div);

From here, you could probably just reposition the div how you want so it appears under the text. This way, the div is the exact length of the text.

An alternative solution would be to use a monospace font and then manually calculuate the width.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM