Most common mistakes Junior Front-end developers make, insights from our recruitment projects

codequest’s approach to recruitment is to make it as individual as possible. We believe that the overall process allows us and the candidate to get to know each other both on the personal and professional level. At the very beginning, we try to find out what kind of programmer candidates are, what their code looks like or how much heart was put in their projects. One of the ways to achieve this was to ask them to do a small recruitment exercise that would be a starting point for future steps. There’s no strict time pressure. We expect that the code they send us will reflect their best skills at that point in time. Recently, when looking for junior front-end developers, we asked candidates to create a simple responsive page inspired by the login screen that would meet specific requirements outlined in the exercise:

Landing page design used in the recruitment task

No matter what the result was, every candidate got detailed feedback after the code review. It included all the awesome parts as well as those not so. After the analysis, we realized that many of the same mistakes have been repeatedly made across the sent projects. Let’s take a look at the most common ones.


Semantic HTML is a key aspect of building pages and their components. It makes the document’s structure more logical, helps index content by the web crawlers or makes using website with screen readers easier. However, while going over the candidates’ code we often noticed:

  • Replacing native elements — HTML5 brings a set of new tags created for dedicated roles (e.g. header, main, footer, section etc.). Replacing them with divs is just unnecessary.
  • Wrong headlines structure — no matter if you care about SEO or not, proper headlines helps to structure your content and highlight the relevance of each part. Using only h3-s or wrong jumbled hierarchy asks to be fixed immediately.
  • Wrong attributes values — skipping alt attributes in image tags was a very common bad practice. In most cases, it shouldn’t be left empty but declared properly. On the other hand, if we use images just for a decorative purpose (e.g. icons) an alt attribute can be omitted. Just do it in pair with your aria-hidden or presentation role. Another very common mix-up was an incorrect language code in HTML’s lang attribute.
  • Syntax inconsistency — HTML5 provides slightly different syntax from the 4th or XHTML versions. One of the changes is replacing self-close tags with void elements (e.g input, br, img etc.). Even though the self-close versions still can be used and the browsers’ HTML parsing engines won’t have any problems with them, according to W3C specification examples they’re promoted to be declared just by using a start tag.

Most of these mistakes could be easily avoided by using validators — either external ones (for example W3C validator) or those built in an IDE or by code editors plugins.


As a visual layer CSS has an enormous influence on the rendering steps and overall site performance. Building a CSS Object Model (CSSOM) or painting processes should be optimized right from the start by declaring and implementing styles in the right way. With many techniques and good practices to follow, there are unfortunately some bad and lazy approaches as well. Be aware of those, especially:

  • Deep nesting — declaring properties for specific and deeply nested elements (.hello > .bar li a:hover span { … }) are very expensive and easy to commit, especially when using /S(C|A)SS/ or LESS transpilers. Using classes is an easy way to solve this issue.
  • Inline declarations — even though this is the most efficient way of appending styles to the element, they are hard to maintain, especially among class attributes declarations. Let’s save them for e-mail templates or dynamic insertions.
  • No default declarations — according to the DRY rule, shared properties (for example those from the font-* group) should be declared in the top containers (for example body) and inherited by their children. Declaring the same ones in every element doesn’t seem like a good idea.
  • No files structure — thanks to native CSS imports or those provided by the transpilers we can split our code into logical chunks. As much as it might not be critical for a small project, it becomes a real necessity as it gets bigger!
  • Wrong properties values and units — thanks to today’s tools we can solve those bugs by using linters (e.g. stylelint), validators or IDEs built-in tools.
  • No naming convention — it may not seem so crucial at first glance but clean code brings a lot of profits, especially during debugging. Keep your code consistent and don’t be afraid to follow standards and good patterns, for example, BEM. As for the naming convention, kebab-case in CSS seems to be the best choice.


In the recruitment project mentioned above, JavaScript hasn’t played a key part in the final score, but we wanted to include it in candidates code reviews to give a full overview of their skillset and to comment on some good practices worth following.

  • No code encapsulation — avoid global declarations, even if it’s just a simple validation script and nothing more. Using ES6 block scopes or IIFE pattern can keep specific logic without risk of any collision with other parts in the code. If you have to use globals for some reason, consider using namespaces.
  • Wrong variables types — let, var, const — it’s great to know the difference and use them according to specification.
  • Using JavaScript for native CSS styling effects — an old, good rule says: “If you can do something with CSS, do it with CSS”. For example, there’s no need to register a mouseover event on an element just to append a class to change its color. Simply use :hover pseudo-class instead.
  • Pointless usage of vendors — including whole libraries can be sometimes a bit over the top, especially if it’s done just to use a single method or some feature that has already been implemented natively in the language. For example, in the ES6 and HTML5 era many of the jQuery features can be easily replaced natively. Same with lodash.
  • No error handling — sooner or later your code will throw exceptions — a reference to a non-existing DOM element, an unexpected REST API response or invalid callback return value — make sure your code is fault tolerant.

As in the cases of HTML or CSS it’s recommended to use linters (e.g. ESlint) and any other tools that help make our code better (for example static typing with TypeScript or Flow). Along with pointing out syntax issues they often provide performance and security tips.

Aside from the coding aspects, we noticed a few doubtful trends in candidates’ projects:

  • Untested project — in the task description we suggested testing the final landing page in the most popular browsers. Not all candidates did it though. It’s worth to keep in mind that many browsers still have problems with some JS or CSS support, and it’s not just about IE (see for example flex bugs issues list). There are some tools out there that can help you with finding them out, for example, Browserstack for manual testing or autoprefixers to ensure compatibility, like Browserslist. Always try to provide as good experience as possible for all users using any browsers or devices.
  • No Readme file — pointing this out this may be a little bit surprising, but we shouldn’t underestimate the role of file in our repository. A well-written document not only makes a great first impression but also shows your care about the project and its possible contributors. It’s good to have it in the back of your mind, not only for the recruitment purposes.
  • Unclear projects history — Unfortunately, commits logs found in the project’s repository reveals that a lot of people were not sure how and when to commit their changes. Many of them had very vague messages (e.g. “fix”), the other included changes in the whole application, much more than a scope declared in the message. Some projects had almost no commits (one or two for the entire project!). There’s a lot of articles about good practices, but this approach sums them all fairly well: Commit Often, Perfect Later, Publish Once.


There’s nothing wrong about making mistakes, especially when you’re a beginner. The point is to learn from them. Nowadays, thanks to numerous tools, web development seems much easier than before. It’s great to use linters and code prettiers, validate your code as often as possible and run tests before pushing to the repository. In codequest, we believe in writing code first and foremost for people, not for machines. Working and clean code is a value for everyone, especially for your future self. It makes programming journey much more enjoyable! 🕺