英文:
Ignore width of inline element for a CSS / HTML / JS typing animation
问题
我有一个打字动画,它在我的作品集网站的主页上居中对齐。它通过使用JavaScript函数来执行打字和删除文本的动画效果,并使用CSS关键帧使打印光标 '|' 字符在键入的字符串末尾闪烁。
我的问题是,'|' 字符(打印光标)在计算文本行的宽度时被考虑在内。这会导致所有前面的字符略微向左移动,使打字动画文本偏离中心。
带有光标的动画:
不带光标的动画:
代码:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const cursorElement = document.getElementById('cursor');
const textElement = document.getElementById('typed-text');
const texts = ['Software Engineer', 'Programmer', 'Tech Geek', 'Coffee Lover', 'Pasta Connoisseur' ];
let count = 0;
let index = 0;
let currentText = '';
let letter = '';
let isDeleting = false;
(function type() {
if(count === texts.length){
count = 0;
}
currentText = texts[count];
if(isDeleting) {
letter = currentText.slice(0, index--);
} else {
letter = currentText.slice(0, ++index);
}
textElement.textContent = letter;
if(letter.length === currentText.length){
isDeleting = true;
setTimeout(type, 1000);
} else if (isDeleting && index === -1) {
isDeleting = false;
count++;
setTimeout(type, 500);
} else {
setTimeout(type, 100);
}
}());
<!-- language: lang-css -->
@import"https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600&family=Roboto:wght@400;500&display=swap";
:root {
--header-height: 3.5rem;
--first-color: hsl(207, 65%, 65%);
--title-color: hsl(207, 4%, 16%);
--text-color: hsl(207, 4%, 28%);
--text-color-light: hsl(207, 4%, 56%);
--body-color: hsl(207, 4%, 99%);
--container-color: hsl(207, 4%, 95%);
--gradient-color: linear-gradient( 180deg, hsla(190, 48%, 72%, 0), rgb(137, 135, 154) );
--body-font: "Roboto", sans-serif;
--title-font: "Lora", serif;
--biggest-font-size: 1.5rem;
--h1-font-size: 1.5rem;
--h2-font-size: 1.25rem;
--h3-font-size: 1rem;
--normal-font-size: .938rem;
--small-font-size: .813rem;
--smaller-font-size: .75rem;
--tiny-font-size: .625rem;
--font-medium: 500;
--font-semi-bold: 600;
--z-normal: 1;
--z-tooltip: 10;
--z-fixed: 100
}
* {
box-sizing:border-box;
padding:0;
margin:0
}
.main {
overflow:hidden
}
.home__title {
color:var(--title-color);
font-family:var(--title-font);
font-weight:var(--font-medium);
text-align:center;
font-size:var(--biggest-font-size);
letter-spacing:.3px;
margin-bottom:.5rem
}
.typing-effect {
display: flex;
justify-content: center;
align-items: center;
/*position: relative;*/
}
#cursor {
animation: blink 1s infinite;
padding-bottom: 0.05em;
padding-left: 0.03em;
font-family: 'Times New Roman', Times, serif;
white-space: pre;
}
@keyframes blink {
0% {opacity: 1;}
50% {opacity: 0;}
100% {opacity: 1;}
}
<!-- language: lang-html -->
<main class="main">
<section class="home section" id="home">
<div class="home__container container grid section__border" id="maincard">
<div class="home__data grid">
<div id="home__title" class="home__title">Hello World, I'm Dan<br>
<div id="typing-div" class="typing-effect">
<span id="typed-text"></span>
<span id="cursor">|</span>
</div>
</div>
</div>
</section>
</main>
如何使光标宽度在计算键入文本的宽度时被忽略?
英文:
I have a typing animation which is centrally justified for the main page of my portfolio website. It works by animating the typing and deleting of the text using a javascript function and making a pipe '|' character at the end of the typed string blink using CSS keyframes.
My problem is that the '|' character (typing cursor) is accounted for when calculating the width of the line of text. This forces all preceding characters slightly to the left making the typing animation text off center.
Animation with cursor:
Animation without cursor:
Code:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const cursorElement = document.getElementById('cursor');
const textElement = document.getElementById('typed-text');
const texts = ['Software Engineer', 'Programmer', 'Tech Geek', 'Coffee Lover', 'Pasta Connoisseur' ];
let count = 0;
let index = 0;
let currentText = '';
let letter = '';
let isDeleting = false;
(function type() {
if(count === texts.length){
count = 0;
}
currentText = texts[count];
if(isDeleting) {
letter = currentText.slice(0, index--);
} else {
letter = currentText.slice(0, ++index);
}
textElement.textContent = letter;
if(letter.length === currentText.length){
isDeleting = true;
setTimeout(type, 1000);
} else if (isDeleting && index === -1) {
isDeleting = false;
count++;
setTimeout(type, 500);
} else {
setTimeout(type, 100);
}
}());
<!-- language: lang-css -->
@import"https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600&amp;family=Roboto:wght@400;500&ampdisplay=swap";
:root {
--header-height: 3.5rem;
--first-color: hsl(207, 65%, 65%);
--title-color: hsl(207, 4%, 16%);
--text-color: hsl(207, 4%, 28%);
--text-color-light: hsl(207, 4%, 56%);
--body-color: hsl(207, 4%, 99%);
--container-color: hsl(207, 4%, 95%);
--gradient-color: linear-gradient( 180deg, hsla(190, 48%, 72%, 0), rgb(137, 135, 154) );
--body-font: "Roboto", sans-serif;
--title-font: "Lora", serif;
--biggest-font-size: 1.5rem;
--h1-font-size: 1.5rem;
--h2-font-size: 1.25rem;
--h3-font-size: 1rem;
--normal-font-size: .938rem;
--small-font-size: .813rem;
--smaller-font-size: .75rem;
--tiny-font-size: .625rem;
--font-medium: 500;
--font-semi-bold: 600;
--z-normal: 1;
--z-tooltip: 10;
--z-fixed: 100
}
* {
box-sizing:border-box;
padding:0;
margin:0
}
.main {
overflow:hidden
}
.home__title {
color:var(--title-color);
font-family:var(--title-font);
font-weight:var(--font-medium);
text-align:center;
font-size:var(--biggest-font-size);
letter-spacing:.3px;
margin-bottom:.5rem
}
.typing-effect {
display: flex;
justify-content: center;
align-items: center;
/*position: relative;*/
}
#cursor {
animation: blink 1s infinite;
padding-bottom: 0.05em;
padding-left: 0.03em;
font-family: 'Times New Roman', Times, serif;
white-space: pre;
}
@keyframes blink {
0% {opacity: 1;}
50% {opacity: 0;}
100% {opacity: 1;}
}
<!-- language: lang-html -->
<main class="main">
<section class="home section" id="home">
<div class="home__container container grid section__border" id="maincard">
<div class="home__data grid">
<div id="home__title" class="home__title">Hello World, I'm Dan<br>
<div id="typing-div" class="typing-effect">
<span id="typed-text"></span>
<span id="cursor">|</span>
</div>
</div>
</div>
</section>
</main>
<!-- end snippet -->
How can I make it so that the cursor width is ignored when calculating the width of the typed text?
答案1
得分: 1
光标只是一个视觉提示,它可以从DOM中移除。
这可以通过将光标放置在文本本身的伪元素中,使用绝对定位来实现。这样它就不会影响实际文本的宽度。
#typed-text::after {
content: '|';
position: absolute;
animation: blink 1s infinite;
padding-bottom: 0.05em;
padding-left: 0.03em;
font-family: 'Times New Roman', Times, serif;
white-space: pre;
}
这段代码将光标添加到文本的伪元素中,通过CSS实现了光标的闪烁效果。
英文:
As the cursor is just a visual clue it can be removed from the DOM.
This can be done by putting it instead into the after pseudo element of the text itself with position absolute. It then will not affect the width of the actual text.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const cursorElement = document.getElementById('cursor');
const textElement = document.getElementById('typed-text');
const texts = ['Software Engineer', 'Programmer', 'Tech Geek', 'Coffee Lover', 'Pasta Connoisseur'];
let count = 0;
let index = 0;
let currentText = '';
let letter = '';
let isDeleting = false;
(function type() {
if (count === texts.length) {
count = 0;
}
currentText = texts[count];
if (isDeleting) {
letter = currentText.slice(0, index--);
} else {
letter = currentText.slice(0, ++index);
}
textElement.textContent = letter;
if (letter.length === currentText.length) {
isDeleting = true;
setTimeout(type, 1000);
} else if (isDeleting && index === -1) {
isDeleting = false;
count++;
setTimeout(type, 5000);
} else {
setTimeout(type, 1000);
}
}());
<!-- language: lang-css -->
@import"https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600&amp;family=Roboto:wght@400;500&ampdisplay=swap";
:root {
--header-height: 3.5rem;
--first-color: hsl(207, 65%, 65%);
--title-color: hsl(207, 4%, 16%);
--text-color: hsl(207, 4%, 28%);
--text-color-light: hsl(207, 4%, 56%);
--body-color: hsl(207, 4%, 99%);
--container-color: hsl(207, 4%, 95%);
--gradient-color: linear-gradient( 180deg, hsla(190, 48%, 72%, 0), rgb(137, 135, 154));
--body-font: "Roboto", sans-serif;
--title-font: "Lora", serif;
--biggest-font-size: 1.5rem;
--h1-font-size: 1.5rem;
--h2-font-size: 1.25rem;
--h3-font-size: 1rem;
--normal-font-size: .938rem;
--small-font-size: .813rem;
--smaller-font-size: .75rem;
--tiny-font-size: .625rem;
--font-medium: 500;
--font-semi-bold: 600;
--z-normal: 1;
--z-tooltip: 10;
--z-fixed: 100
}
* {
box-sizing: border-box;
padding: 0;
margin: 0
}
.main {
overflow: hidden
}
.home__title {
color: var(--title-color);
font-family: var(--title-font);
font-weight: var(--font-medium);
text-align: center;
font-size: var(--biggest-font-size);
letter-spacing: .3px;
margin-bottom: .5rem
}
.typing-effect {
display: flex;
justify-content: center;
align-items: center;
/*position: relative;*/
}
#typed-text {
position: relative;
}
#typed-text::after {
content: '|';
position: absolute;
animation: blink 1s infinite;
padding-bottom: 0.05em;
padding-left: 0.03em;
font-family: 'Times New Roman', Times, serif;
white-space: pre;
}
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<!-- language: lang-html -->
<main class="main">
<section class="home section" id="home">
<div class="home__container container grid section__border" id="maincard">
<div class="home__data grid">
<div id="home__title" class="home__title">Hello World, I'm Dan<br>
<div id="typing-div" class="typing-effect">
<span id="typed-text"></span>
</div>
</div>
</div>
</section>
</main>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论