<div class="todo">
<ul role="list"></ul>
<button type="button" class="btn btn-add">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Add item
</button>
</div>
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
@layer reset, presentationstyles, demo;
/* These are the demo styles, the basic styling of ul and li can be found in presentationstyles layer to remove the clutter and keep to the essentials here of @starting-style and the animations */
@layer demo {
ul {
& li {
opacity: 1;
transform: translate(0, 0);
transition: transform 0.5s ease-out, border-radius 0.5s,
opacity 0.3s linear, background-color 0.3s ease-out;
@starting-style {
opacity: 0;
transform: translate(0, 50%);
}
&.removing {
opacity: 0;
transform: translate(-100%, 0);
~ li {
transition: translate 0.5s ease-out;
translate: 0 -100%;
}
}
}
&:has(.removing) + .btn-add {
transition: translate 0.5s ease-out;
translate: 0 -100%;
}
&:empty + button.btn-add {
border-radius: 10px;
}
}
}
@layer presentationstyles {
.todo {
width: 100%;
max-width: 600px;
}
input {
border-width: 0 0 1px 0;
border-style: dashed;
border-color: white;
background: none;
padding: 10px 0;
color: white;
font-size: 1.1rem;
&:focus {
outline: 0;
}
&::placeholder {
color: #ddd;
}
}
/* Basic ul and li styling to remove clutter from demo essentials */
ul {
display: flex;
flex-direction: column;
width: 100%;
list-style: none;
margin: 0;
padding: 0;
& li {
display: grid;
grid-template-columns: 1fr 20px;
gap: 5px;
background: darkcyan;
padding: 6px 16px;
&:first-child {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
&:focus-within {
background: #381d2a;
}
}
}
/* button styling */
.btn {
display: inline-block;
background: transparent;
border: none;
cursor: pointer;
font-family: "Roboto", sans-serif;
font-size: 1.2rem;
& svg {
width: 20px;
aspect-ratio: 1;
}
&.btn-add {
position: relative;
z-index: 1;
display: flex;
justify-content: center;
gap: 10px;
padding: 16px 20px;
align-items: center;
width: 100%;
color: white;
background: #004643;
border-radius: 0 0 10px 10px;
transition: background 0.3s;
&:is(:hover, :focus) {
background: #07716c;
}
}
&.btn-remove {
color: white;
& svg {
width: 20px;
}
}
}
}
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 1vmax;
display: flex;
justify-content: center;
min-height: 100vh;
font-family: "Roboto", sans-serif;
background: #faf4d3;
background-image: repeating-linear-gradient(
-45deg,
transparent,
transparent 1vw,
#f6be9a 1vw,
#f6be9a 50%
),
repeating-linear-gradient(
45deg,
#faf4d3,
#faf4d3 1vw,
#f6be9a 1vw,
#f6be9a 50%
);
background-size: 5vw 5vw, 3.5vw 2.5vw;
}
.sr-only:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
}
const button = document.querySelector("button");
const list = document.querySelector("ul");
// Create a function to add a new list item
function addListItem() {
const listItem = document.createElement("li");
// Create an input element for the list item
const input = document.createElement("input");
input.type = "text";
input.placeholder = "Enter a new to-do item";
input.ariaLabel = "To-do item";
// Add the input element to the list item
listItem.appendChild(input);
// Add a remove button to the list item
const removeButton = document.createElement("button");
removeButton.classList.add("btn", "btn-remove");
removeButton.ariaLabel = "Remove";
// Set the innerHTML of the remove button to the SVG code
removeButton.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
`;
listItem.appendChild(removeButton);
// Add the list item to the list
list.appendChild(listItem);
input.focus();
// Add an event listener to the remove button
removeButton.addEventListener("click", () => {
// Remove the list item from the list
listItem.classList.add("removing");
setTimeout(() => {
listItem.remove();
}, 500);
});
}
// Add an event listener to the button for the click event
button.addEventListener("click", addListItem);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.