Skip to content
  • Unlock Pro
  • Log in with GitHub
Solution
Submitted over 1 year ago

Vanilla HTML, CSS, JS - Flexbox and Grid - Accessible News homepage

accessibility, bem
Anar•700
@anar-sol
A solution to the News homepage challenge
View live sitePreview (opens in new tab)View codeCode (opens in new tab)

Solution retrospective


  • Solution URL: Github repo
  • Live Site URL: News homepage

Built with

  • Vanilla HTML, CSS, and JS
  • Semantic HTML5 markup
  • BEM naming convention
  • CSS custom properties
  • Flexbox
  • CSS Grid
  • Accessibility
  • Mobile-first workflow (except for the menu)
  • Progressive enhancement

What I learned

I used semantic HTML elements to implement the different components:

  • I used <article> elements for the article cards, as I considered them as independent content that could be displayed or reused elsewhere.
  • To contain the different categories of articles, I used <section> elements.

I structured the page with appropriate heading levels, some of them are accessible to screen reader only. Every <section> has a heading.

I tried to make the components as independent as possible. For that, I used the BEM naming convention and divided the CSS and JS into multiple files, one for each component (with some exceptions).

To change the paddings, sizing, and other properties depending on viewport I didn't apply a different value for the property but changed a css custom property.

:root {
    --logo-width: 3rem;
}

@media (min-width: 48rem) {
    :root {
        --logo-width: 4rem;
    }
}

.logo {
    width: var(--logo-width);
}

For accessibility:

  • I implemented a skip-to-main link
  • used aria-label for image only links and buttons
  • used aria-label for the "read more" link
  • implemented an accessible hamburger menu
  • styled hover, active, and focus states to make visible
  • kept a logical and natural tab order

I used JS to make the whole cards clickable while keeping the content selectable.

const cards = document.querySelectorAll(".card");
cards.forEach(card => {
    card.addEventListener("click", () => {
        const mainLink = card.querySelector(".card__main-link");
        const isTextSelected = window.getSelection().toString();
        if (!isTextSelected && mainLink) {
            mainLink.click();
        }
    });
});

The main navigation panel can be closed with the button, by pressing the ESC key, and when clicking the overlay. The focus returns to the hamburger menu.

Continued development

If I had more time to dedicate to this project

  • I would refactor the CSS and make a better (and cleaner) use of the variables
  • Try to find a solution to make the whole clickable cards more accessible to keyboard users and add an active state
  • Change the colors to fix contrast issues.

Useful resources

  • To learn how to implement an accessible clickable card.
  • To make an accessible "Read more" link.
  • To make image only links and buttons accessible. For accessible icon buttons.
  • For accessible SVGs.
  • Various resources to implement an accessible skip-to-main link, make the skip-to-main invisible by default, skip-to-main on web.dev, and skip-to-main on css-tricks.
  • How to make a component accessible to screen readers only.
  • Inspiration for making a button controlled navigation menu.
  • Resources used for the css reset.

Feel free to share any feedback

Code
Select a file

Please log in to post a comment

Log in with GitHub

Community feedback

No feedback yet. Be the first to give feedback on Anar's solution.

Join 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
Frontend Mentor logo

Stay up to datewith new challenges, featured solutions, selected articles, and our latest news

Frontend Mentor

  • Unlock Pro
  • Contact us
  • FAQs
  • Become a partner

Explore

  • Learning paths
  • Challenges
  • Solutions
  • Articles

Community

  • Discord
  • Guidelines

For companies

  • Hire developers
  • Train developers
© Frontend Mentor 2019 - 2025
  • Terms
  • Cookie Policy
  • Privacy Policy
  • License

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

How does the accessibility report work?

When a solution is submitted, we use axe-core to run an automated audit of your code.

This picks out common accessibility issues like not using semantic HTML and not having proper heading hierarchies, among others.

This automated audit is fairly surface level, so we encourage to you review the project and code in more detail with accessibility best practices in mind.

How does the CSS report work?

When a solution is submitted, we use stylelint to run an automated check on the CSS code.

We've added some of our own linting rules based on recommended best practices. These rules are prefixed with frontend-mentor/ which you'll see at the top of each issue in the report.

The report will audit all CSS, SCSS and Less files in your repository.

How does the HTML validation report work?

When a solution is submitted, we use html-validate to run an automated check on the HTML code.

The report picks out common HTML issues such as not using headings within section elements and incorrect nesting of elements, among others.

Note that the report can pick up “invalid” attributes, which some frameworks automatically add to the HTML. These attributes are crucial for how the frameworks function, although they’re technically not valid HTML. As such, some projects can show up with many HTML validation errors, which are benign and are a necessary part of the framework.

How does the JavaScript validation report work?

When a solution is submitted, we use eslint to run an automated check on the JavaScript code.

The report picks out common JavaScript issues such as not using semicolons and using var instead of let or const, among others.

The report will audit all JS and JSX files in your repository. We currently do not support Typescript or other frontend frameworks.