Design comparison
Solution retrospective
This was a tough one!! 😄
Tricky parts were getting the borders working at different page widths, and getting the Vue CLI to properly access the correct images in the public directory for the portfolio/inner pages. As the project pages are the same page with data and images populated with a query, I was trying to autogenerate the img urls with a method. This worked locally but caused havoc when deployed into production 😫
In the end I put the image paths in the JSON file alongside the rest of the info on the page and it worked fine.
This project was good to get the hang of more complex routing. As ever, any way I could have improved on this v much appreciated 👍😎
says there's an accessibility issue on one of the buttons, but ive got it aria-labelled with a title how the documentation says it should be so should be fine 🤷♂️
Community feedback
- @pikapikamartPosted about 3 years ago
Hey, awesome work on this one. Just viewed the different links and everything looks great. Desktop layout looks great, there is just a horizontal scrollbar at the bottom, (suspecting a
width: 100vw
usage in here), the site is responsive as well and the mobile state looks really great.Don't know if I could check other links as well but here are some: HOME
- On your
footer
remove thewidth: 100vw
since this will create the horizontal scrollbar.100vw
doesn't respect the size of the vertical scrollbar on the right side. You can think of it by:
100vw === 100% of the screen vertical scrollbar on the right side === 16px ish?
So 100vw plus the scrollbar size exceeds the total width of the screen, creating extra space for horizontal scroll.
- I don't know if
aria-current
is needed on the website-logo link since there is thehome
link already. User will get 2 announcement if they are on the homepage when traversing both link. - Website-logo-link
a
tag should have eitheraria-label
attribute orsr-only
text inside, that describes where the link would take the user. Since this takes user to homepage, use homepage as the text-value. - For the website-logo
img
, I don't know a suitable text for this one though when it comes to portfolio with logo :> but still,logo
word as well is not suitable for describing image since this will just announce " logo graphic" and it will be ambiguous for the user. Maybe more valid text. - Usage of
id
in styling is not advisable, though I only found it on your hamburger toggle. - For the
header
navbar, usearia-label="primary"
on this and on thefooter
usearia-label="footer"
, use it on thenav
tag. - The 3 navlinks could have been wrapped inside a
ul
since they are "list" of links. - For the hero-section
about me
you should've not usedbutton
witha
tag since this will just create extra navigation when using keyboard. Use onlya
tag in here with the arrow-icon on the left side as a::before
or::after
of thea
tag. - Also, you don't use
aria-label
attribute onimg
tag, you use them for interactive elements likebutton
,a
tag and other that does need a text inside them to give meaning on the element. - Changing
section
tags into just usingdiv
on this sincesection
by itself is not informative when navigated as landmark unless they are labelled byaria-labelledby
pointing to like a heading tag inside thesection
. go to portfolio
should be using ana
tag since it is a link. When a component directs user to a new page, always usea
tag becausebutton
are for controls.contact me
should be using a link as well since it directs user.- When using client-side-navigation, always make sure that the next focus after the user navigates to the new page will be on the top of that current page. For example, you using keyboard and go the
portfolio
on thefooter
tag then select it as well using keyboard. It navigates the user properly, but, try using thetab
key again, the focus goes to the next link after theportfolio
which is thecontact me
.
So a good approach would be use something like, when the user navigates on the next page, make the
body
tag have liketabindex="-1"
for a moment then transfer thefocus
on thebody
tag so that the focus after toggling the footer-links won't stay at the bottom. Maybe creating a function that will run on first load for every link, the function will make sure that the focus is on thebody
tag of the current-link. Then maybe after like a second, remove thetabindex
, asetTimeout
would be great.FOOTER
- Use
<nav aria-label="footer">.../<nav>
so that it will be unique.
PORTFOLIO
- It would be better to use
h2
on theManage
project title and use a sr-onlyh1
inside themain
tag. You could use something like:
<main> <h1 class="sr-only"> Alex Spencer Projects </h1> ..... </main>
This way it will suit more.
View Project
should be link as well since they directs user in another page.- Adding a more visual on the
:focus-visible
state of eachview project
. Right now, if you navigate on them using keyboard, it is hard to see where you are at. - Also for me, I would something like screen-reader
span
between the "view" and "project" text because for example, using screen-reader and navigating different links, I would just getview project
multiple times since all links have the same name. I would use something like:
<a href="/projects?project=manage"> View <span class="sr-only"> Manage </span> Project </a>
This way, I would know what project am I going into without checking the heading tags at first if just skimming.
CONTACT ME
- On each
input
, it would be better to use thefor
attribute of thelabel
to point with their respectiveinput
so that thelabel
text could be clicked as well in order to type in the input-field instead of usingaria-labelledby
. - Also, you don't use
aria-live
for each of theinput
tags. Use only a singlearia-live
maybe ap
tag inside theform
which will handle all different event that will occur. For example, the name and email field are incorrect, you will just change the single-aria-live-text to like:
<p aria-live="polite"> Name field incorrect! Email field incorrect!
- When submitting a wrong form, you use the
aria-invalid
on thelabel
tag which should be on theinput
tag. Also, a proper way of linking the error-messages would look like:
if ( input is wrong ) input.setAttribute("aria-invalid", "true"); input.setAttribute("aria-describedBy", id of the error-message); else input.removeAttribute("aria-invalid"); input.removeAttribute("aria-describedBy");
The error-message element should have an
id
attribute which is referenced by thearia-describedBy
attribute on theinput
element. By doing that, your user will know that the input is wrong because ofaria-invalid
and they will know what kind of error they made because of thearia-describedBy
.- Submitting a correct form, it would be great to have something like a success message and you can change the
aria-live
element to announce something likeform successfully submitted
so that the user will be informed right away.
MOBILE
- Use
aria-expanded
attribute on thebutton
to inform a user that it has expanded/shown something. - Use
position: fixed
on thenav
when activating the toggle so that it won't create short horizontal scroll. Try toggling the hamburger at the moment and you can see that it creates a scroll at the bottom.
For now, those only. Again, really nice work on this one.
Marked as helpful2@fraserwatPosted about 3 years ago@martpika this (and your feedback on my other project) is - as ever! - soo good and thorough! Made a few changes, going to work through the rest this evening
1@fraserwatPosted almost 3 years ago@martpika Sorted!! Thanks again for the super detailed feedback.
HOME
- On the
aria-current
attribute, it seems like this is added automatically by the Vue router. You're right though, having it announced twice is not ideal - I've updated the top left corner icon to havearia-live="off"
to stop it getting announced. Thought this would be better than removing from the accessibility tree totally witharia-hidden
? What do you think? - Re
aria-label
on nav elements, this makes sense, but what is the rationale behind the best practice here? - Re the "focus on new pages" issue, this is a good spot. In the end I did the following in the App.vue file, idk if its done slightly differently in whatever framework you usually use:
watch: { $route() { window.scrollTo(0, 0); document .getElementById("app") .firstElementChild.firstElementChild.focus(); }, },
This way whenever the app routes to a new page you're resetting the focus to the first element (the logo link to the homepage).
0@pikapikamartPosted almost 3 years ago@fraserwat Hey, glad to be back in here and great that you are already refactoring some codes!
- For the website-link
aria-current
, don't usearia-hidden
on the link since that will remove the website-logo link itself. Is there any option in vue where you can "not" apply thearia-current
on the website-logo-link? That's a bit weird behavior to be honest. - The reason for using
aria-label
fornav
elements is to distinguish them for othernav
elements. For example on your site, since there are 2nav
being used, one on theheader
and one on thefooter
. Instead of just screen-reader announcing when traversing in anav
element,navigation landmark...
for bothnav
, if you used like:
`<nav aria-label="primary" /> <nav aria-label="footer" />
This will instead read as
primary navigation landmark
andfooter navigation landmark
distinguishing whatnav
is the user is in. You use this as well when you have like a breadcrumbs on the site, breadcrumbs are links that helps user know what section are they are in in a particular page.services - business-registration - sole-proprietorship
Something like that, and since those are links of the site, you will like:
<nav aria-label="breadcrumbs" />
- That is great, just tried it right now and navigating inside the
footer
links the user on the page and focus is set properly. Always have that where you are doing a multi page, because if you don't, screen-reader user can't really navigate on the new page where they are at.
0 - On your
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord