Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <aside
       id="sidebar"
       class="fixed left-0 top-0 bottom-0 flex flex-col max-h-screen w-80 md:w-96 max-w-full bg-neutral-950 text-neutral-500 transform-gpu motion-safe:transition-transform -translate-x-full z-10">
    <button
            type="button"
            class="size-10 absolute -right-10 top-4 bg-blue-500 pr-0.5 text-blue-100 [&>svg]:m-auto rounded-r-xl"
            onclick="toggleSidebar()"
            aria-controls="sidebar"
            aria-expanded="false"
            aria-label="toggle sidebar to generate text wall">
        <svg
             xmlns="http://www.w3.org/2000/svg"
             width="24"
             height="24"
             viewBox="0 0 24 24"
             fill="none"
             stroke="currentColor"
             stroke-width="2"
             stroke-linecap="round"
             stroke-linejoin="round"
             aria-hidden="true">
            <path d="m9 18 6-6-6-6" />
        </svg>
    </button>

    <h1 class="px-4 py-5 text-2xl text-neutral-100 bg-blue-500 text-center">
        Generate your TextWall
    </h1>

    <section
             class="grid gap-8 [&_div]:grid [&_label]:text-neutral-200 [&_label]:font-semibold py-8 px-4 [&_input]:text-xs [&_select]:text-xs [&_select]:p-2 [&_select]:text-neutral-800 [&_label]:mb-2 [&_input]:p-2 [&_input]:text-neutral-800 overflow-y-auto max-h-full">
        <div>
            <label for="words">Words</label>
            <input
                   id="words"
                   type="text"
                   value="You, miss, 100%, of the, shots, YOU, don’t, take" />
            <p><small>Seperated word for each line by comma.</small></p>
        </div>

        <div>
            <label for="colors">Colors</label>
            <input
                   id="colors"
                   type="text"
                   value="#fff, #F22B29, #fff, #474748, #fff, #F22B29, #fff, #F22B29" />
            <p><small>Seperated colors for each line by comma.</small></p>
        </div>

        <div>
            <label for="font-size">Font Size</label>
            <input
                   id="font-size"
                   type="number"
                   min="12"
                   value="20" />
            <p>
                <small>Set the minimal font-size for the TextWall (in px).</small>
            </p>
        </div>

        <div>
            <label for="letter-spacing">Letter Spacing</label>
            <input
                   id="letter-spacing"
                   type="number"
                   min="0"
                   value="16" />
            <p>
                <small>Set the letter-spacing for the TextWall (in px).</small>
            </p>
        </div>

        <div>
            <label for="font-weight">Font Weight</label>
            <select
                    id="font-weight"
                    name="font-weight">
                <option value="light">Light</option>
                <option value="normal">Normal</option>
                <option value="medium">Medium</option>
                <option value="semibold">SemiBold</option>
                <option
                        value="bold"
                        selected>
                    Bold
                </option>
                <option value="extrabold">ExtraBold</option>
                <option value="black">Black</option>
            </select>
        </div>

        <div>
            <label for="text-transform">Text Transform</label>
            <select
                    id="text-transform"
                    name="text-transform">
                <option
                        value="uppercase"
                        selected>
                    Uppercase
                </option>
                <option value="lowercase">Lowercase</option>
                <option value="capitalize">Capitalize</option>
                <option value="none">None</option>
            </select>
        </div>

        <div>
            <label for="linegap">Line Gap</label>
            <input
                   id="linegap"
                   type="text"
                   value="0.5rem" />
            <p>
                <small>This option sets the spacing between each line.</small>
            </p>
        </div>

        <div class="my-4 space-y-4">
            <button
                    type="button"
                    class="ring-2 ring-blue-500 text-blue-500 hover:bg-blue-500 rounded-lg hover:text-blue-100 p-2"
                    onclick="generateTextWall()">
                Generate TextWall
            </button>
            <button
                    type="button"
                    class="ring-2 ring-neutral-500 text-neutral-500 hover:bg-neutral-500 rounded-lg hover:text-neutral-100 p-2"
                    onclick="toggleModal()"
                    aria-controls="modal">
                Get Code
            </button>
        </div>
    </section>
</aside>

<div
     id="wordwall"
     class="grid place-items-center bg-gradient-to-t from-neutral-900 to-neutral-800 text-center h-full [&>ul]:p-0 [&>ul]:opacity-0">
    <p
       id="textwall"
       class="flex flex-col items-center [&>span]:leading-none"></p>
</div>

<!-- Modal -->
<div
     id="modal"
     class="hidden bg-neutral-950/75 backdrop-blur-sm fixed inset-0 items-center justify-center z-50 text-neutral-200">
    <div
         class="bg-neutral-900 rounded-xl ring-1 ring-neutral-800 max-w-full w-96 p-4 shadow-md">
        <h2 class="text-neutral-100 mb-4 font-semibold text-xl">
            The generated TextWall output
        </h2>
        <pre
             id="output"
             class="overflow-auto border border-neutral-700 w-full p-2 text-sm text-neutral-400 whitespace-pre block"></pre>

        <div class="flex flex-wrap gap-4">
            <button
                    type="button"
                    class="ring-2 ring-blue-500 text-blue-500 hover:bg-blue-500 rounded-lg hover:text-blue-100 p-2 mt-4 inline-flex items-center gap-2 [&>svg]:size-5"
                    onclick="copyToClipboard()">
                <svg
                     xmlns="http://www.w3.org/2000/svg"
                     width="24"
                     height="24"
                     viewBox="0 0 24 24"
                     fill="none"
                     stroke="currentColor"
                     stroke-width="2"
                     stroke-linecap="round"
                     stroke-linejoin="round"
                     aria-hidden="true">
                    <rect
                          width="14"
                          height="14"
                          x="8"
                          y="8"
                          rx="2"
                          ry="2" />
                    <path
                          d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
                </svg>
                <span>Copy to Clipboard</span>
            </button>

            <button
                    type="button"
                    class="ring-2 ring-rose-500 text-rose-500 hover:bg-rose-500 rounded-lg hover:text-rose-100 p-2 mt-4 inline-flex items-center gap-2 [&>svg]:size-5"
                    onclick="toggleModal()">
                <svg
                     xmlns="http://www.w3.org/2000/svg"
                     width="24"
                     height="24"
                     viewBox="0 0 24 24"
                     fill="none"
                     stroke="currentColor"
                     stroke-width="2"
                     stroke-linecap="round"
                     stroke-linejoin="round"
                     aria-hidden="true">
                    <path d="M18 6 6 18" />
                    <path d="m6 6 12 12" />
                </svg>
                <span>Cancel</span>
            </button>
        </div>
        <p
           id="succsess"
           class="hidden items-center gap-2 text-green-500 mt-4 pt-2 border-t border-neutral-800 w-full">
            <svg
                 xmlns="http://www.w3.org/2000/svg"
                 width="1em"
                 height="1em"
                 viewBox="0 0 24 24"
                 fill="none"
                 stroke="currentColor"
                 stroke-width="2"
                 stroke-linecap="round"
                 stroke-linejoin="round"
                 aria-hidden="true">
                <path d="M20 6 9 17l-5-5" />
            </svg>
            <span>Code has been copied to clipboard.</span>
        </p>
    </div>
</div>
              
            
!

CSS

              
                html,
body {
    height: 100%;
}
              
            
!

JS

              
                const wordwall = document.getElementById('wordwall');
const textWall = document.getElementById('textwall');
const icon = document.querySelector('button > svg');
const sidebar = document.getElementById('sidebar');
const modal = document.getElementById('modal');

let sidebarOpen = false;
let showOutput = false;

// generate text wall
function generateTextWall() {
	// Settings
	const wall = {
		fontSize: +document.getElementById('font-size').value,
		lineGap: document.getElementById('linegap').value,
		fontWeight: document.getElementById('font-weight').value,
		letterSpacing: +document.getElementById('letter-spacing').value,
		textTransform: document.getElementById('text-transform').value,
		words: document.getElementById('words').value.split(',').map(word => word.trim()),
		colors: document
			.getElementById('colors')
			.value.split(',')
			.map(color => color.trim()),
	};

	// Preparing elements
	textWall.innerHTML = '';

	for (const item in wall.words) {
		const word = document.createElement('span');
		word.style.fontSize = `${wall.fontSize}px`;

		// adding gap
		textWall.classList.add(`gap-[${wall.lineGap}]`);
		textWall.style.gap = wall.lineGap;

		// adding letter spacing
		if (wall.letterSpacing > 0) {
			word.style.letterSpacing = `${wall.letterSpacing}px`;
			word.classList.add(`tracking-[${wall.letterSpacing}px]`);
		}

		// adding font weight
		word.style.fontWeight = wall.fontWeight;
		word.classList.add(`font-${wall.fontWeight}`);

		// adding text transform
		word.style.textTransform = wall.textTransform;
		word.classList.add(
			wall.textTransform === 'none' ? 'normal-case' : wall.textTransform
		);

		// adding color
		const color = wall.colors[item] || 'currentColor';
		word.style.color = color;
		word.classList.add(
			color === 'currentColor' ? 'text-current' : `text-[${color}]`
		);

		// adding text
		word.innerText = wall.words[item];
		textWall.append(word);
	}

	// Preparing words elements
	const items = document.querySelectorAll('#textwall span');
	const spanWidth = Array.from(items, span => span.offsetWidth);
	const longestSpan = Math.max(...spanWidth);
	const longestSpanIdx = spanWidth.indexOf(longestSpan);

	// Resizing words elements
	items.forEach((span, idx) => {
		if (span[idx] === longestSpanIdx) return;
		resizeSpan(span);
	});

	function resizeSpan(span) {
		let fontSize = +span.style.fontSize.replace('px', '');

		if (span.offsetWidth < longestSpan) {
			fontSize++;
			span.style.fontSize = `${fontSize}px`;
			resizeSpan(span);
		} else {
			span.classList.add(`text-[${fontSize}px]`);
		}
	}
	// remove transparenz
	wordwall.classList.remove('opacity-0');
}

// Toggle sidebar
function toggleSidebar() {
	sidebarOpen = !sidebarOpen;
	sidebar.firstElementChild.setAttribute('aria-expanded', sidebarOpen);
	sidebar.classList.toggle('-translate-x-full', !sidebarOpen);
	icon.classList.toggle('rotate-180', sidebarOpen);
}

function toggleModal() {
	showOutput = !showOutput;
	getTextWallOutput();

	modal.classList.toggle('hidden', !showOutput);
	modal.classList.toggle('flex', showOutput);
}

function getTextWallOutput() {
	const spans = textWall.getElementsByTagName('span');

	let formattedText = `<p id="textwall" class="flex flex-col items-center gap-[${
		document.getElementById('linegap').value
	}] [&>span]:leading-none">\n`;
	for (let span of spans) {
		formattedText += `\t${span.outerHTML.replace(/style="[^"]*"/g, '')}\n`;
	}
	formattedText += '</p>';

	document.getElementById('output').textContent = formattedText;
}

// Copy to clipboard
function copyToClipboard() {
	let showSuccess = false;
	const output = document.getElementById('output').textContent;
	navigator.clipboard.writeText(output);

	showSuccess = true;
	document.getElementById('succsess').classList.toggle('hidden', !showSuccess);
	document.getElementById('succsess').classList.toggle('flex', showSuccess);

	setTimeout(() => {
		showSuccess = false;
		document.getElementById('succsess').classList.toggle('hidden', !showSuccess);
		document.getElementById('succsess').classList.toggle('flex', showSuccess);
	}, 1000);
}

generateTextWall();

              
            
!
999px

Console