Typewriter Effect

Text generates as if it is being typed on the screen.

The road to freedom starts from here

B u i l d  
a w e s o m e  
a p p s  
w i t h  
A c e t e r n i t y .  

Installation

Install Dependencies

npm i svelte-motion clsx tailwind-merge svelte-inview

Add util file

src/lib/utils/cn.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
        
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}

Copy the source code

src/lib/components/ui/TypewriterEffect/TypewriterEffect.svelte
<script lang="ts">
	import { cn } from '$lib/utils';
	import { Motion } from 'svelte-motion';

	export let words: {
		text: string;
		className?: string;
	}[];
	export let className: string | undefined = undefined;
	export let cursorClassName: string | undefined = undefined;

	const wordsArray = words.map((word) => {
		return {
			...word,
			text: word.text.split('')
		};
	});
</script>

<div class={cn('text-center text-base font-bold sm:text-xl md:text-3xl lg:text-5xl', className)}>
	<Motion
		let:motion
		animate={{
			display: 'inline-block',
			opacity: 1
		}}
		transition={{
			duration: 0.3,
			delay: 0.1,
			ease: 'easeInOut',
			staggerChildren: 0.1
		}}
	>
		<div use:motion class="inline">
			{#each wordsArray as word, idx (`word-${idx}`)}
				<div class="inline-block">
					{#each word.text as char, index (`char-${index}`)}
						<Motion let:motion initial={{}}>
							<span
								use:motion
								class={cn(`hidden text-black opacity-0 dark:text-white`, word.className)}
							>
								{char}
							</span>
						</Motion>
					{/each}
					&nbsp;
				</div>
			{/each}
		</div>
	</Motion>
	<Motion
		let:motion
		initial={{
			opacity: 0
		}}
		animate={{
			opacity: 1
		}}
		transition={{
			duration: 0.8,
			repeat: Infinity,
			repeatType: 'reverse'
		}}
	>
		<span
			use:motion
			class={cn('inline-block h-4 w-[4px] rounded-sm bg-blue-500 md:h-6 lg:h-10', cursorClassName)}
		></span>
	</Motion>
</div>
src/lib/components/ui/TypewriterEffect/TypewriterEffectSmooth.svelte
<script lang="ts">
	import { cn } from '$lib/utils';
	import { text } from '@sveltejs/kit';
	import { Motion } from 'svelte-motion';

	export let words: {
		text: string;
		className?: string;
	}[];
	export let className: string | undefined = undefined;
	export let cursorClassName: string | undefined = undefined;

	const wordsArray = words.map((word) => {
		return {
			...word,
			text: word.text.split('')
		};
	});
</script>

<div class={cn('my-6 flex space-x-1', className)}>
	<Motion
		let:motion
		style={{
			width: 'fit-content'
		}}
		initial={{
			width: '0%'
		}}
		transition={{
			duration: 2,
			ease: 'linear',
			delay: 1
		}}
	>
		<div use:motion class="overflow-hidden">
			<div
				class="lg:text:3xl text-xs font-bold sm:text-base md:text-xl xl:text-5xl"
				style="white-space: nowrap;"
			>
				<div>
					{#each wordsArray as word, idx (`word-${idx}`)}
						<div class="inline-block">
							{#each word.text as char, index (`char-${index}`)}
								<span class={cn(`text-black dark:text-white `, word.className)}>
									{char}
								</span>
							{/each}
							&nbsp;
						</div>
					{/each}
				</div>
				{' '}
			</div>
			{' '}
		</div>
	</Motion>
	<Motion
		let:motion
		initial={{
			opacity: 0
		}}
		animate={{
			opacity: 1
		}}
		transition={{
			duration: 0.8,

			repeat: Infinity,
			repeatType: 'reverse'
		}}
	>
		<span
			use:motion
			class={cn('block h-4 w-[4px]  rounded-sm bg-blue-500 sm:h-6 xl:h-12', cursorClassName)}
		></span>
	</Motion>
</div>
src/lib/components/ui/TypewriterEffect/index.ts
import TypewriterEffect from './TypewriterEffect.svelte';
import TypewriterEffectSmooth from './TypewriterEffectSmooth.svelte';

export { TypewriterEffect, TypewriterEffectSmooth };

Props

TypewriterEffect
Prop Type Description
words {text: string, className?: string} Every word with a className that you can define
className string | undefined The class name of the container component.
cursorClassName string | undefined The className of the cursor component