#Attributes
Explore tagged Tumblr posts
Text
Spin the wheel for random attributes!
#demographics#culture#identity#human#humanity#tumblr polls#random polls#polls#apollo hour#my polls#fun polls#hyperspecific poll#attributes#not a hyperspecific poll in the traditional way but I feel it counts#spinner wheel#random
109 notes
·
View notes
Text
Working with gods means experiencing new found love and association for their attributes. Having before not really paying too much attention to cheetahs/tigers, ever since working with Dionysus I can't help but feel a fondness whenever I notice imagery or visit the zoo. I just think that's really lovely 🌿
#deities#deity#deity work#deity worship#greek gods#pagan witch#pagan#paganism#witch community#nature#dionysus#dionysian#greek deities#witchcore#witchcraft#witchblr#paganblr#hellenic worship#hellenic deities#attributes
171 notes
·
View notes
Text
tag the vtm oc whose highest Attribute is Intelligence!
22 notes
·
View notes
Text
Study reveals AI chatbots can detect race, but racial bias reduces response empathy
New Post has been published on https://thedigitalinsider.com/study-reveals-ai-chatbots-can-detect-race-but-racial-bias-reduces-response-empathy/
Study reveals AI chatbots can detect race, but racial bias reduces response empathy


With the cover of anonymity and the company of strangers, the appeal of the digital world is growing as a place to seek out mental health support. This phenomenon is buoyed by the fact that over 150 million people in the United States live in federally designated mental health professional shortage areas.
“I really need your help, as I am too scared to talk to a therapist and I can’t reach one anyways.”
“Am I overreacting, getting hurt about husband making fun of me to his friends?”
“Could some strangers please weigh in on my life and decide my future for me?”
The above quotes are real posts taken from users on Reddit, a social media news website and forum where users can share content or ask for advice in smaller, interest-based forums known as “subreddits.”
Using a dataset of 12,513 posts with 70,429 responses from 26 mental health-related subreddits, researchers from MIT, New York University (NYU), and University of California Los Angeles (UCLA) devised a framework to help evaluate the equity and overall quality of mental health support chatbots based on large language models (LLMs) like GPT-4. Their work was recently published at the 2024 Conference on Empirical Methods in Natural Language Processing (EMNLP).
To accomplish this, researchers asked two licensed clinical psychologists to evaluate 50 randomly sampled Reddit posts seeking mental health support, pairing each post with either a Redditor’s real response or a GPT-4 generated response. Without knowing which responses were real or which were AI-generated, the psychologists were asked to assess the level of empathy in each response.
Mental health support chatbots have long been explored as a way of improving access to mental health support, but powerful LLMs like OpenAI’s ChatGPT are transforming human-AI interaction, with AI-generated responses becoming harder to distinguish from the responses of real humans.
Despite this remarkable progress, the unintended consequences of AI-provided mental health support have drawn attention to its potentially deadly risks; in March of last year, a Belgian man died by suicide as a result of an exchange with ELIZA, a chatbot developed to emulate a psychotherapist powered with an LLM called GPT-J. One month later, the National Eating Disorders Association would suspend their chatbot Tessa, after the chatbot began dispensing dieting tips to patients with eating disorders.
Saadia Gabriel, a recent MIT postdoc who is now a UCLA assistant professor and first author of the paper, admitted that she was initially very skeptical of how effective mental health support chatbots could actually be. Gabriel conducted this research during her time as a postdoc at MIT in the Healthy Machine Learning Group, led Marzyeh Ghassemi, an MIT associate professor in the Department of Electrical Engineering and Computer Science and MIT Institute for Medical Engineering and Science who is affiliated with the MIT Abdul Latif Jameel Clinic for Machine Learning in Health and the Computer Science and Artificial Intelligence Laboratory.
What Gabriel and the team of researchers found was that GPT-4 responses were not only more empathetic overall, but they were 48 percent better at encouraging positive behavioral changes than human responses.
However, in a bias evaluation, the researchers found that GPT-4’s response empathy levels were reduced for Black (2 to 15 percent lower) and Asian posters (5 to 17 percent lower) compared to white posters or posters whose race was unknown.
To evaluate bias in GPT-4 responses and human responses, researchers included different kinds of posts with explicit demographic (e.g., gender, race) leaks and implicit demographic leaks.
An explicit demographic leak would look like: “I am a 32yo Black woman.”
Whereas an implicit demographic leak would look like: “Being a 32yo girl wearing my natural hair,” in which keywords are used to indicate certain demographics to GPT-4.
With the exception of Black female posters, GPT-4’s responses were found to be less affected by explicit and implicit demographic leaking compared to human responders, who tended to be more empathetic when responding to posts with implicit demographic suggestions.
“The structure of the input you give [the LLM] and some information about the context, like whether you want [the LLM] to act in the style of a clinician, the style of a social media post, or whether you want it to use demographic attributes of the patient, has a major impact on the response you get back,” Gabriel says.
The paper suggests that explicitly providing instruction for LLMs to use demographic attributes can effectively alleviate bias, as this was the only method where researchers did not observe a significant difference in empathy across the different demographic groups.
Gabriel hopes this work can help ensure more comprehensive and thoughtful evaluation of LLMs being deployed in clinical settings across demographic subgroups.
“LLMs are already being used to provide patient-facing support and have been deployed in medical settings, in many cases to automate inefficient human systems,” Ghassemi says. “Here, we demonstrated that while state-of-the-art LLMs are generally less affected by demographic leaking than humans in peer-to-peer mental health support, they do not provide equitable mental health responses across inferred patient subgroups … we have a lot of opportunity to improve models so they provide improved support when used.”
#2024#Advice#ai#AI chatbots#approach#Art#artificial#Artificial Intelligence#attention#attributes#author#Behavior#Bias#california#chatbot#chatbots#chatGPT#clinical#comprehensive#computer#Computer Science#Computer Science and Artificial Intelligence Laboratory (CSAIL)#Computer science and technology#conference#content#disorders#Electrical engineering and computer science (EECS)#empathy#engineering#equity
14 notes
·
View notes
Text
Hii
When I was on vacation, I was a little bored so here you have sketches of gods and their attributes ⚡️


Inspiration: EPIC: The Musical
(BTW I’m back lol)
#art#schetch#drawing#poses#greek gods#gods#aphrodite#zeus#hera#athena goddess of wisdom#attributes#epic the musical#epic the thunder saga#epic the wisdom saga
24 notes
·
View notes
Text

Ollivanders
{Makers of Fine Wands since 382 B }
A wand doodle turned into this :)
#illustration#illustrator#hogwarts#harrypotteruniverse#prop design#attribute design#attributes#harrypotterworld#harrypotterart#ollivanders#wand#wandmaking#characterart#characterdesign#characterdesignsheets#harrypotterdesign#maraudersera#wizardingworld#wizard#hogwarts school of witchcraft and wizardry#wizarding world#harry potter#hermione#ron weasley#Weasley#Potter#potterhead
114 notes
·
View notes
Note
Clanmew terms to describe weight and height? Like the heavy in Heavystep or the tall in Tallstar?
I'm going to give you a detailed breakdown of words for describing attributes, including pulling from the Lexicon, to try and have a good single-post guide for this.
Note: In an attempt to add some better grammatical rules for attributes going foward, for a larger quest to make Clanmew better for some "conversational" topics, some words are going to get edited in the Lexicon as well
Basic Attributes
MOST attributes in Clanmew are inherently "neutral" until modified. "Way" is simply Height, with "Wayeeb," "Wayrra," and "Waymor" meaning Short, Medium, and Tall.
Generic attributes CAN be used in names, and by default refer to the 'obvious' nature of a characteristic.
For example; Shortwhisker of SkyClan was Kas-hussk, Length-Whisker. Because his short whiskers were defining, Kas in this situation obviously means "short." If his whiskers suddenly grew in twice as long, Kas-hussk would suddenly mean "Longwhisker," as that would also be the obvious trait.
(For Talltail I'm kind of thinking of making his Clanmew name Swashmew, Tailkit, and then eventually earning a name on his return that means "Story-Traveled" in reference to how long he spent away from WindClan. "Talltale" in English, which could have been "Wanderstar" or even "Talestar")
Height; the vertical axis of an object = Way
Length; the horizontal axis of an object = Kas
Weight; the heaviness of an object = Bai
Age; amount of time a thing has existed = Kiq
Wealth; the amount of stuff that a thing has = Poh (Note: NOT money-related. Refers to how much prey you've caught in an outing, how rich a patch of territory is, how full your bowl is, etc. I cannot think of a better English translation.)
Threat Level; a Clan Culture value = Myyrn
Experience/Skill/Aptitude; how good you are at a thing = Pya
Favor; for mortals, liking things = Min (Do you want to say "I love you?" Go read this for examples.)
Gloss; the shininess of fur, has a double meaning as StarClan's favor in you = Shaw
Soft; 'Squishiness,' comfort, pliability = Afi (NOT a fur texture. Soft of texture is "wuff")
Hard = Bobur
Happy; contentedness, joy, satisfaction = Bia
Rank; political power, authority, social standing = Gorrl
Temperature; the normal, non-freezing and non-burning range of heat. For fevers, average weather, objects you touch casually = Waa
Suffixes; attached to the end of attributes to modify them
Little of a physical attribute = -eeb
Medium of a physical attribute = -rra
Large of a physical attribute = -mor
Has not collected much of the attribute; scarce, poor = -qef
Has collected a reasonable amount of the attribute; expected, normal, "hitting your numbers" = -qal
Has collected a whole lot of the attribute; rich, -ful = -qew
"-ness," the most basic suffix for turning any word into an noun to be used in questions and declarations = -wang.
There's a significant difference between eeb/rra/mor (ERM) and qef/qal/qew (QQQ), listen carefully.
The ERM set is about physical, innate attributes. Long legs, natural talent, harmless species. A cat who contains Waymor is a NATURALLY tall cat, it is their build. To say that a cat contains "pyaeeb" is like saying that they are always going to be bad at a thing, where you could comfort a clanmate with "pyaqef" to say that they don't have experience yet.
The QQQ set is about acquired traits. A cat who contains Baiqew may be one who might be carrying a lot of weight but could set the objects down. You might hear "Pohqal" for a cat who has caught as much prey as they need to on this particular outing. "Wayqew" is height that a cat has because they are standing on something.
(and wayqal implies that squilf has stepped up onto some sort of box or rock to be eye-level with the person she is talking to <3)
It's a small difference, but a meaningful one.
80 notes
·
View notes
Text
Dragon attributes are not absolute power.

35 notes
·
View notes
Note
What's your favorite thing about Moomintroll? And what is your favorite memory that you've made with your friends??
Ah, Moomintroll. My good best friend I get to see every time the grass turns green in Moominvalley. I usually wouldn't pick out favorites in somebody, but for Moomin, it would have to be his perseverance. Sometimes I don't understand how he pushes through things sometimes, even when things are tough. Something about that in him makes me drawn to him more, like an idol. Of course, I know he probably sees me as such, but he can be such a good role model... sometimes.
As for memories, I think that any time that we've gotten to sit around a camp fire, sing songs, laugh, and roast some homemade marshmallows is a favorite memory. Something big always happens, whether it's life-threatening or just a silly coincidence, but I look forward to every single one of those moments each day.
I'd like to know what some of your favorite memories are. Maybe with family? Friends? A favorite place? Whatever the memory, it's certainly special if it holds onto you. No matter what a person may say, that's your memory. Own it.
Can't wait to see more questions! :] - Snufkin
#moomin#moomin valley#moomins#moominvalley#snufkin#the moomins#memory#memories#perseverance#attributes#favorite#qna#you
16 notes
·
View notes
Text
Information sheet about Dionysus 🍇:
When being interested in deity worship it is important to do the regarding research about, well, everything. Not every source is tells you all the Information you need to gather. There's always gonna be a few questions you may have left unanswered so I'll try to mash it all up together in one post as a (hopefully) trustworthy source! The Information gathered below me, beside the basics is mostly based on all the questions I used to have that were left unanswered for a LONG while. (Long Post ahead)
Dionysus (Di-on-y-sus) also called Bacchus, is a member of the twelve greek Olympians. He is roughly classified as God of wine, fertility, vegetation, reincarnation, parties and festivites, comedy and tragedy plays, madness and wilderness. Bacchus is the Roman given name, depraved from the frenzy and madness he induced, called Baccheia. Additionally the Romans called him Liber Pater, meaning free father.
Family: His Father was Zeus, his Mother the mortal Semele (who was also classified as the Goddess of Bacchic frenzy), no full blooded siblings, his Wife was Ariadne
Myth: Simply told, Zeus and Semele were lovers. Hera, Wife of Zeus and Goddess of lawful marriages, women and family and marital harmony, felt jealousy and persuaded a pregnant Semele to ask Zeus if he would show her his true self. Now this part gets told each way, he agrees and his godly divinity burns her to death, or her consistant asking made him so angry that he let thunder rain onto her, resulting into her death. Either way, after her Death, Zeus feels compassion for the yet unborn child, cuts it out off Semeles body to sew it into his thigh until it can rightfully be born. The next part gets told differently. After his birth, Hera was so enranged that he was alive that she ordered the Titans to kill him. After they have ripped him apart, Rhea allegedly revived him again and Zeus ordered him to be brought up by the Nymphs. His attribute of the reincarnation steems from this myth. Differently it gets told like this: When he was born, out of protection, he was given to a foster parent. Now this again is different in each myth. Sometimes he was entrusted to Hermes, other times Seilenos, even after that he was given to Semeles sister and her husband. Eventually Hera found out about his location and drove the couple into madness, letting them murder each other. After this he wandered the world in search of his purpose. During his travels he learned of vine, wine-making, etc. He arrived in Greece then Thebes long time after trying to establish a reign. Marking his name as God of Epiphany (The god who comes). The, mostly winemaking skills, he has learned abroad impressed the people. But the ones in power, such as his cousin Perseus, denied his worship and disbelieved his divinity. Soon he has gotten his own cult under the influence of ecstasy and madness. Mostly the woman of Thebes have taken a liking to his influence, they were called Maenads. Everyone who was against his reign and the madness he spread were destroyed (by his Thyrsus in the Myths). His influence became wide spread, marking his title as the God of madness and frenzy.
Cultural context: Knowingly, he was worshipped in Naxos, Boiotia and Edonia. There he was seen as a God of Orphic Mysteries, A God of the Eleusinian Mysteries or God of the vegetable Gardens.
Attributes: Grape-vine, Ivy crown, Thyrsus, Parties and Festivites, Wilderness and Vegetation and Comedy and Tragedy Plays
Sacred things: Thyrsus, grape-vine, Ivy, Cinnamon, Silver Fir, Bindweed, Wheat, Barley, Leopard, Cheetah, Tiger, Goat, Donkey, Lion, Serpent, Wild bull, Apples, Figs, Berries, Acting, Wine, Drunkeness and Pleasure, Festivites, Ecstasy, Reincarnation, Predatory big cats, Homosexuality, the Colors Red, Purple, Gold and the Card of the Devil/Hanged Man
His Worship: Broadly his cult was called Bacchic, the followers Bacchantes. Some called it Dionysian Mysteries. He was called Dionysus Eleutherius, the liberator, as his wine, the madness and ecstasy free his followers from their monotone life and subvert their fear into something powerful. Those who believed in him were at first ridiculed until they realized what the consequences of being against his reign entailed. The first of his followers were the women, who were called Maenads. In their madness they tore wild animals apart, wearing their fur as devotion and even their family, believing them to be leopards/panthers of that sort. These Maenads additionally wore Ivy crowns as to honor Dionysus' attributes. Under his influence people were believed to be possessed by his godly powers, letting them gain unhuman strength. Followers of him included spirits of fertility, such as Satyrs.
Festivities: Dionysia (lesser Dionysia) was one of the oldest festivals in dedication to Dionysus. It was said to celebrate to cultivation of vine. Timewise it was celebrated around modern December/January. It was centered on a procession, followed by drama performances. City Dionysia (greater Dionysia) was a festival held three month after lesser Dionysia, modern March/April. This festival was more elaborate and carried more worthy offerings such as wooden statue of Dionysus. The followed drama performances were performed by more noteworthy playwrights. Anthesteria celebrated the beginning of spring. It span across three days, with each day regarding a tradition in honor of Dionysus.
Offering Ideas (traditional and modern): Alcohol (specifically Red wine), Bottles, Corks, Cider, Honeyed Milk, Water, weed or any type of hallucenigens, Drugs, Grape (Grape flavored things), ticket to the Theatre, Costumes/Masks, Pinecones, Fennel, any Wildflower, Figs, Ivy, Honey, Bones, imagery of his sacred animals, preserved Animals, fur cloth, Wheat, Barley, Olive Oil, Musk, Bread, Grape-Vine, Fruit, anything regarding Homosexuality or Effeminaty, Cinnamon, Silver Fir, Apples, storax, thistle, Black diamonds, frankincense, Golden jewerly, Amethyst/Tigereye, concert tickets, any imagery of his attributes, devotional acts of listening to music, singing, going drinking/partying, learning about his attributes, braiding hair, letting your hair grow out, making devotional art/hymns/prayers, wear his colors, sexual acts (only if you're comfortable with that), confidence in yourself, in ancient greece Maenads made blood offerings due to his connection with the dead (see: the myth of him going to the underworld to save his Mother Semele) but be REALLY careful if actually doing that
How to pray/offer to Dionysus: When praying to a Chthonic God you would have your head and hands down with your hair open. The Prayer can be anything. There is an actual structure of a hellenic prayer (invocation, argument, request) but during modern times it isn't necessary. Be respectful and thank him. Traditionally his offerings were burned but again, no necessity. Be sure to have some sort of protection during an offer/a prayer. "Euoi" was a passion cry from Bacchic worshippers that is still used today. You could use it in a prayer!
This is all the main information I've gathered so far. When coming to connect with gods its important to know what they represent and what they're known for.
Happy Witching!
Additional links to check out if you want to learn more about his myths or his connection to his attributes:
#nature#deities#deity#deity work#deity worship#greek gods#pagan#pagan witch#paganism#witch community#dionysian#dionysus#greek deities#ancient greece#greek mythology#witchcore#witchcraft#witchblr#paganblr#hellenic worship#hellenic deities#witches#attributes#wine#ivy#euoi
16 notes
·
View notes
Text
tag the vtm oc who has 1 Strength!
35 notes
·
View notes
Text
ORE'N Attribute Correlation Chart
🇯🇵 Japanese
🇬🇧 English (Fan-translated v.1)
Source: ORE'N Notion Site
#ORE'N#Attributes Correlation Chart#Element#Attributes#Admin's Note: I really spent almost 3 hours just for editing and using google translate/DeepL the two game's attributes chart#ORE'NGuide
4 notes
·
View notes
Text
Altara De Riva's Personality Sheet - Template by otherpigeon
[Bluesky][Pillowfort][Instagram][Tumblr][AO3][Nexus][Ko-Fi[Discord]
#dragon age veilgaurd#datv#templates#other's templates#personality sheet#Altara De Riva#De Riva#Antivan Crows#Sarcastic#Rogue#Assassin#Dragon Age: The Veilgaurd#DATV#Rook#Fem Rook#Personality#Attributes#Traits
3 notes
·
View notes
Text

Quote of The Day!
Know more on: https://dbf.adalaj.org/gOu9mRrY
2 notes
·
View notes
Text

"Strictly speaking, a real distinction exists only between two or more substances; and we can perceive that two substances are really distinct simply from the fact that we can clearly and distinctly understand one apart from the other." - Spinoza
28 notes
·
View notes
Text
How to Create Multi-Step Forms With Vanilla JavaScript and CSS
New Post has been published on https://thedigitalinsider.com/how-to-create-multi-step-forms-with-vanilla-javascript-and-css/
How to Create Multi-Step Forms With Vanilla JavaScript and CSS
Multi-step forms are a good choice when your form is large and has many controls. No one wants to scroll through a super-long form on a mobile device. By grouping controls on a screen-by-screen basis, we can improve the experience of filling out long, complex forms.
But when was the last time you developed a multi-step form? Does that even sound fun to you? There’s so much to think about and so many moving pieces that need to be managed that I wouldn’t blame you for resorting to a form library or even some type of form widget that handles it all for you.
But doing it by hand can be a good exercise and a great way to polish the basics. I’ll show you how I built my first multi-step form, and I hope you’ll not only see how approachable it can be but maybe even spot areas to make my work even better.
We’ll walk through the structure together. We’ll build a job application, which I think many of us can relate to these recent days. I’ll scaffold the baseline HTML, CSS, and JavaScript first, and then we’ll look at considerations for accessibility and validation.
I’ve created a GitHub repo for the final code if you want to refer to it along the way.
The structure of a multi-step form
Our job application form has four sections, the last of which is a summary view, where we show the user all their answers before they submit them. To achieve this, we divide the HTML into four sections, each identified with an ID, and add navigation at the bottom of the page. I’ll give you that baseline HTML in the next section.
Navigating the user to move through sections means we’ll also include a visual indicator for what step they are at and how many steps are left. This indicator can be a simple dynamic text that updates according to the active step or a fancier progress bar type of indicator. We’ll do the former to keep things simple and focused on the multi-step nature of the form.,
The structure and basic styles
We’ll focus more on the logic, but I will provide the code snippets and a link to the complete code at the end.
Let’s start by creating a folder to hold our pages. Then, create an index.html file and paste the following into it:
Open HTML
<form id="myForm"> <section class="group-one" id="one"> <div class="form-group"> <div class="form-control"> <label for="name">Name <span style="color: red;">*</span></label> <input type="text" id="name" name="name" placeholder="Enter your name"> </div> <div class="form-control"> <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" id="idNum" name="idNum" placeholder="Enter your ID number"> </div> </div> <div class="form-group"> <div class="form-control"> <label for="email">Email <span style="color: red;">*</span></label> <input type="email" id="email" name="email" placeholder="Enter your email"> </div> <div class="form-control"> <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" id="birthdate" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section class="group-two" id="two"> <div class="form-control"> <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" id="document"> </div> <div class="form-control"> <label for="department">Department <span style="color: red;">*</span></label> <select id="department" name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section class="group-three" id="three"> <div class="form-control"> <label for="skills">Skills (Optional)</label> <textarea id="skills" name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div class="form-control"> <input type="checkbox" name="terms" id="terms"> <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button id="btn" type="submit">Confirm and Submit</button> </section> <div class="arrows"> <button type="button" id="navLeft">Previous</button> <span id="stepInfo"></span> <button type="button" id="navRight">Next</button> </div> </form> <script src="script.js"></script>
Looking at the code, you can see three sections and the navigation group. The sections contain form inputs and no native form validation. This is to give us better control of displaying the error messages because native form validation is only triggered when you click the submit button.
Next, create a styles.css file and paste this into it:
Open base styles
:root --primary-color: #8c852a; --secondary-color: #858034; body font-family: sans-serif; line-height: 1.4; margin: 0 auto; padding: 20px; background-color: #f4f4f4; max-width: 600px; h1 text-align: center; form background: #fff; padding: 40px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; .form-group display: flex; gap: 7%; .form-group > div width: 100%; input:not([type="checkbox"]), select, textarea width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; .form-control margin-bottom: 15px; button display: block; width: 100%; padding: 10px; color: white; background-color: var(--primary-color); border: none; border-radius: 4px; cursor: pointer; font-size: 16px; button:hover background-color: var(--secondary-color); .group-two, .group-three display: none; .arrows display: flex; justify-content: space-between align-items: center; margin-top: 10px; #navLeft, #navRight width: fit-content; @media screen and (max-width: 600px) .form-group flex-direction: column;
Open up the HTML file in the browser, and you should get something like the two-column layout in the following screenshot, complete with the current page indicator and navigation.
Adding functionality with vanilla JavaScript
Now, create a script.js file in the same directory as the HTML and CSS files and paste the following JavaScript into it:
Open base scripts
const stepInfo = document.getElementById("stepInfo"); const navLeft = document.getElementById("navLeft"); const navRight = document.getElementById("navRight"); const form = document.getElementById("myForm"); const formSteps = ["one", "two", "three"]; let currentStep = 0; function updateStepVisibility() formSteps.forEach((step) => document.getElementById(step).style.display = "none"; ); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`; navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block"; document.addEventListener("DOMContentLoaded", () => navLeft.style.display = "none"; updateStepVisibility(); navRight.addEventListener("click", () => if (currentStep < formSteps.length - 1) currentStep++; updateStepVisibility(); ); navLeft.addEventListener("click", () => if (currentStep > 0) currentStep--; updateStepVisibility(); ); );
This script defines a method that shows and hides the section depending on the formStep values that correspond to the IDs of the form sections. It updates stepInfo with the current active section of the form. This dynamic text acts as a progress indicator to the user.
It then adds logic that waits for the page to load and click events to the navigation buttons to enable cycling through the different form sections. If you refresh your page, you will see that the multi-step form works as expected.
Multi-step form navigation
Let’s dive deeper into what the Javascript code above is doing. In the updateStepVisibility() function, we first hide all the sections to have a clean slate:
formSteps.forEach((step) => document.getElementById(step).style.display = "none"; );
Then, we show the currently active section:
document.getElementById(formSteps[currentStep]).style.display = "block";`
Next, we update the text that indicators progress through the form:
stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`;
Finally, we hide the Previous button if we are at the first step and hide the Next button if we are at the last section:
navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Let’s look at what happens when the page loads. We first hide the Previous button as the form loads on the first section:
document.addEventListener("DOMContentLoaded", () => navLeft.style.display = "none"; updateStepVisibility();
Then we grab the Next button and add a click event that conditionally increments the current step count and then calls the updateStepVisibility() function, which then updates the new section to be displayed:
navRight.addEventListener("click", () => if (currentStep < formSteps.length - 1) currentStep++; updateStepVisibility(); );
Finally, we grab the Previous button and do the same thing but in reverse. Here, we are conditionally decrementing the step count and calling the updateStepVisibility():
navLeft.addEventListener("click", () => if (currentStep > 0) currentStep--; updateStepVisibility(); );
Handling errors
Have you ever spent a good 10+ minutes filling out a form only to submit it and get vague errors telling you to correct this and that? I prefer it when a form tells me right away that something’s amiss so that I can correct it before I ever get to the Submit button. That’s what we’ll do in our form.
Our principle is to clearly indicate which controls have errors and give meaningful error messages. Clear errors as the user takes necessary actions. Let’s add some validation to our form. First, let’s grab the necessary input elements and add this to the existing ones:
const nameInput = document.getElementById("name"); const idNumInput = document.getElementById("idNum"); const emailInput = document.getElementById("email"); const birthdateInput = document.getElementById("birthdate") const documentInput = document.getElementById("document"); const departmentInput = document.getElementById("department"); const termsCheckbox = document.getElementById("terms"); const skillsInput = document.getElementById("skills");
Then, add a function to validate the steps:
Open validation script
function validateStep(step)
Here, we check if each required input has some value and if the email input has a valid input. Then, we set the isValid boolean accordingly. We also call a showError() function, which we haven’t defined yet.
Paste this code above the validateStep() function:
function showError(input, message) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.add("error"); errorSpan.textContent = message;
Now, add the following styles to the stylesheet:
Open validation styles
input:focus, select:focus, textarea:focus outline: .5px solid var(--primary-color); input.error, select.error, textarea.error outline: .5px solid red; .error-message font-size: x-small; color: red; display: block; margin-top: 2px; .arrows color: var(--primary-color); font-size: 18px; font-weight: 900; #navLeft, #navRight display: flex; align-items: center; gap: 10px; #stepInfo color: var(--primary-color);
If you refresh the form, you will see that the buttons do not take you to the next section till the inputs are considered valid:
Finally, we want to add real-time error handling so that the errors go away when the user starts inputting the correct information. Add this function below the validateStep() function:
Open real-time validation script
function setupRealtimeValidation() nameInput.addEventListener("input", () => if (nameInput.value.trim() !== "") clearError(nameInput); ); idNumInput.addEventListener("input", () => if (idNumInput.value.trim() !== "") clearError(idNumInput); ); emailInput.addEventListener("input", () => if (emailInput.validity.valid) clearError(emailInput); ); birthdateInput.addEventListener("change", () => if (birthdateInput.value !== "") clearError(birthdateInput); ); documentInput.addEventListener("change", () => if (documentInput.files[0]) clearError(documentInput); ); departmentInput.addEventListener("change", () => if (departmentInput.value !== "") clearError(departmentInput); ); termsCheckbox.addEventListener("change", () => if (termsCheckbox.checked) clearError(termsCheckbox); );
This function clears the errors if the input is no longer invalid by listening to input and change events then calling a function to clear the errors. Paste the clearError() function below the showError() one:
function clearError(input) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.remove("error"); errorSpan.textContent = "";
And now the errors clear when the user types in the correct value:
The multi-step form now handles errors gracefully. If you do decide to keep the errors till the end of the form, then at the very least, jump the user back to the erroring form control and show some indication of how many errors they need to fix.
Handling form submission
In a multi-step form, it is valuable to show the user a summary of all their answers at the end before they submit and to offer them an option to edit their answers if necessary. The person can’t see the previous steps without navigating backward, so showing a summary at the last step gives assurance and a chance to correct any mistakes.
Let’s add a fourth section to the markup to hold this summary view and move the submit button within it. Paste this just below the third section in index.html:
Open HTML
<section class="group-four" id="four"> <div class="summary-section"> <p>Name: </p> <p id="name-val"></p> <button type="button" class="edit-btn" id="name-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>ID Number: </p> <p id="id-val"></p> <button type="button" class="edit-btn" id="id-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Email: </p> <p id="email-val"></p> <button type="button" class="edit-btn" id="email-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Date of Birth: </p> <p id="bd-val"></p> <button type="button" class="edit-btn" id="bd-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>CV/Resume: </p> <p id="cv-val"></p> <button type="button" class="edit-btn" id="cv-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Department: </p> <p id="dept-val"></p> <button type="button" class="edit-btn" id="dept-edit"> <span>✎</span> <span>Edit</span> </button> </div> <div class="summary-section"> <p>Skills: </p> <p id="skills-val"></p> <button type="button" class="edit-btn" id="skills-edit"> <span>✎</span> <span>Edit</span> </button> </div> <button id="btn" type="submit">Confirm and Submit</button> </section>
Then update the formStep in your Javascript to read:
const formSteps = ["one", "two", "three", "four"];
Finally, add the following classes to styles.css:
.summary-section display: flex; align-items: center; gap: 10px; .summary-section p:first-child width: 30%; flex-shrink: 0; border-right: 1px solid var(--secondary-color); .summary-section p:nth-child(2) width: 45%; flex-shrink: 0; padding-left: 10px; .edit-btn width: 25%; margin-left: auto; background-color: transparent; color: var(--primary-color); border: .7px solid var(--primary-color); border-radius: 5px; padding: 5px; .edit-btn:hover border: 2px solid var(--primary-color); font-weight: bolder; background-color: transparent;
Now, add the following to the top of the script.js file where the other consts are:
const nameVal = document.getElementById("name-val"); const idVal = document.getElementById("id-val"); const emailVal = document.getElementById("email-val"); const bdVal = document.getElementById("bd-val") const cvVal = document.getElementById("cv-val"); const deptVal = document.getElementById("dept-val"); const skillsVal = document.getElementById("skills-val"); const editButtons = "name-edit": 0, "id-edit": 0, "email-edit": 0, "bd-edit": 0, "cv-edit": 1, "dept-edit": 1, "skills-edit": 2 ;
Then add this function in scripts.js:
function updateSummaryValues() nameVal.textContent = nameInput.value; idVal.textContent = idNumInput.value; emailVal.textContent = emailInput.value; bdVal.textContent = birthdateInput.value; const fileName = documentInput.files[0]?.name; if (fileName) const extension = fileName.split(".").pop(); const baseName = fileName.split(".")[0]; const truncatedName = baseName.length > 10 ? baseName.substring(0, 10) + "..." : baseName; cvVal.textContent = `$truncatedName.$extension`; else cvVal.textContent = "No file selected"; deptVal.textContent = departmentInput.value; skillsVal.textContent = skillsInput.value || "No skills submitted"; }
This dynamically inserts the input values into the summary section of the form, truncates the file names, and offers a fallback text for the input that was not required.
Then update the updateStepVisibility() function to call the new function:
function updateStepVisibility() formSteps.forEach((step) => document.getElementById(step).style.display = "none"; ); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step $currentStep + 1 of $formSteps.length`; if (currentStep === 3) updateSummaryValues(); navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Finally, add this to the DOMContentLoaded event listener:
Object.keys(editButtons).forEach((buttonId) => const button = document.getElementById(buttonId); button.addEventListener("click", (e) => currentStep = editButtons[buttonId]; updateStepVisibility(); ); );
Running the form, you should see that the summary section shows all the inputted values and allows the user to edit any before submitting the information:
And now, we can submit our form:
form.addEventListener("submit", (e) => e.preventDefault(); if (validateStep(2)) alert("Form submitted successfully!"); form.reset(); currentFormStep = 0; updateStepVisibility(); );
Our multi-step form now allows the user to edit and see all the information they provide before submitting it.
Accessibility tips
Making multi-step forms accessible starts with the basics: using semantic HTML. This is half the battle. It is closely followed by using appropriate form labels.
Other ways to make forms more accessible include giving enough room to elements that must be clicked on small screens and giving meaningful descriptions to the form navigation and progress indicators.
Offering feedback to the user is an important part of it; it’s not great to auto-dismiss user feedback after a certain amount of time but to allow the user to dismiss it themselves. Paying attention to contrast and font choice is important, too, as they both affect how readable your form is.
Let’s make the following adjustments to the markup for more technical accessibility:
Add aria-required="true" to all inputs except the skills one. This lets screen readers know the fields are required without relying on native validation.
Add role="alert" to the error spans. This helps screen readers know to give it importance when the input is in an error state.
Add role="status" aria-live="polite" to the .stepInfo. This will help screen readers understand that the step info keeps tabs on a state, and the aria-live being set to polite indicates that should the value change, it does not need to immediately announce it.
In the script file, replace the showError() and clearError() functions with the following:
function showError(input, message) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.add("error"); input.setAttribute("aria-invalid", "true"); input.setAttribute("aria-describedby", errorSpan.id); errorSpan.textContent = message; function clearError(input) const formControl = input.parentElement; const errorSpan = formControl.querySelector(".error-message"); input.classList.remove("error"); input.removeAttribute("aria-invalid"); input.removeAttribute("aria-describedby"); errorSpan.textContent = "";
Here, we programmatically add and remove attributes that explicitly tie the input with its error span and show that it is in an invalid state.
Finally, let’s add focus on the first input of every section; add the following code to the end of the updateStepVisibility() function:
const currentStepElement = document.getElementById(formSteps[currentStep]); const firstInput = currentStepElement.querySelector( "input, select, textarea" ); if (firstInput) firstInput.focus();
And with that, the multi-step form is much more accessible.
Conclusion
There we go, a four-part multi-step form for a job application! As I said at the top of this article, there’s a lot to juggle — so much so that I wouldn’t fault you for looking for an out-of-the-box solution.
But if you have to hand-roll a multi-step form, hopefully now you see it’s not a death sentence. There’s a happy path that gets you there, complete with navigation and validation, without turning away from good, accessible practices.
And this is just how I approached it! Again, I took this on as a personal challenge to see how far I could get, and I’m pretty happy with it. But I’d love to know if you see additional opportunities to make this even more mindful of the user experience and considerate of accessibility.
References
Here are some relevant links I referred to when writing this article:
How to Structure a Web Form (MDN)
Multi-page Forms (W3C.org)
Create accessible forms (A11y Project)
#:not#Accessibility#ADD#aria#Article#Articles#attention#attributes#background#border-radius#box#box-shadow#browser#buttons#challenge#change#classes#code#Color#content#CSS#CV#dept#direction#display#email#error handling#event#Events#Exercise
2 notes
·
View notes