MrAutoIt
MrAutoIt

Reputation: 795

How to keep a custom cursor from shifting letters?

I have made a custom CSS cursor for a div. I am trying to get it to display like any other standard cursor. It is 99% working but when I move between letters the cursor shifts the other letters. I am sure it can be fixed with absolute positioning but nothing I come up with seems to work right. Any help would be appreciated.

    $("#next-btn").click(function() {
      var text = $("#text").text();
      console.log(text);
      var n = text.indexOf("|");
      text = text.replace("|", "");
      text = text.slice(0, n + 1) + '<span id="cursor">|</span>' + text.slice(n + 1);
      $("#text").replaceWith('<span id="text">' + text + '</span>');
    });
    #text {
      desplay: inline;
      font-size: 1.8em;
      letter-spacing: .05em;
    }
    #start,
    #end,
    #cursor {
      padding: 0;
      margin: 0;
    }
    #cursor {
      -webkit-animation: blink 1.5s infinite;
      animation: blink 1.5s infinite;
      font-weight: bold;
      font-size: 1.2em;
    }
    @-webkit-keyframes blink {
      0%, 49.9%, 100% {
        opacity: 0;
      }
      50%,
      99.9% {
        opacity: 1;
      }
    }
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>demo</title>
  <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>

<body>
  <div>
    <span id="text">H<span id="cursor">|</span>ello world</span>
  </div>
  <p>
    <button id="next-btn">Next</button>
  </p>
</body>

</html>

Upvotes: 2

Views: 495

Answers (5)

yaakov
yaakov

Reputation: 4665

Just use

position:absolute;
margin:-4px

on the #cursor element. This will remove it from the document flow. Update from comment, good point.

Upvotes: 1

shennan
shennan

Reputation: 11656

I'd go for a different approach to the cursor: using a transparent left border that is turned black intermittently by the animation. This requires first splitting the text into characters wrapped in spans, then applying a .cursor class to the appropriate ones:

var cursor = 0;

$('#text').html( '<span class="cursor">' + $('#text').text().split('').join('</span><span>') + '</span>');

$('#next-btn').on('click', function () {
  
  var $characters = $('#text').children();
  var cursorIndex = $characters.filter('.cursor').index();
  
  if (cursorIndex == -1)
    $characters.eq(0).addClass('cursor');
  else
    $characters.removeClass('cursor').eq(cursorIndex + 1).addClass('cursor');
    
  
});
#text {

  desplay: inline;
  font-size: 1.8em;
  letter-spacing: .005em;

}

#text span {

  border-left: .1em solid transparent;
  
}

#text span.cursor {
  -webkit-animation: blink 1.5s infinite;
  animation: blink 1.5s infinite;
}

@-webkit-keyframes blink {
  0%, 49.9%, 100% {
    border-color: black;
  }
  50%,
  99.9% {
    border-color: transparent;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div>
  <span id="text">Hello world</span>
</div>
<p>
  <button id="next-btn">Next</button>
</p>

Upvotes: 1

Patrick Schumacher
Patrick Schumacher

Reputation: 152

The best solution probably is using letter-spacing and margin. Using "position: absolute" might work with some extra css, but might remove the moving along your string.

(edit with suggestion from Roko C. Buljan, thanks for improvement)

  letter-spacing: -1em;
  margin: 0 4px 0 -4px;

https://jsfiddle.net/2ozdm8sr/1/

Upvotes: 3

StateraTv
StateraTv

Reputation: 26

    $("#next-btn").click(function() {
      var text = $("#text").text();
      console.log(text);
      var n = text.indexOf("|");
      text = text.replace("|", "");
      text = text.slice(0, n + 1) + '<span id="cursor">|</span>' + text.slice(n + 1);
      $("#text").replaceWith('<span id="text">' + text + '</span>');
    });
    #text {
      desplay: inline;
      font-size: 1.8em;
      letter-spacing: .05em;
    }
    #start,
    #end,
    #cursor {
      padding: 0;
      margin: 0;
margin-left:-6px;
position:absolute;
width:9px;
overflow:hidden;
    }
    #cursor {
      -webkit-animation: blink 1.5s infinite;
      animation: blink 1.5s infinite;
      font-weight: bold;
      font-size: 1.2em;
    }
    @-webkit-keyframes blink {
      0%, 49.9%, 100% {
        opacity: 0;
      }
      50%,
      99.9% {
        opacity: 1;
      }
    }
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>demo</title>
  <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>

<body>
  <div>
    <span id="text">H<span id="cursor">|</span>ello world</span>
  </div>
  <p>
    <button id="next-btn">Next</button>
  </p>
</body>

</html>

Upvotes: 0

notthehoff
notthehoff

Reputation: 1242

Maybe something like:

letter-spacing: -10px;

on #cursor?

Upvotes: 0

Related Questions