Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Dec 04 2021
Dec 04

What CMS is the agency using for their own website?

First have a look at the website of the agency. Is it built with Drupal? If this is the case then it is a pretty good indicator how passionate the agency is about Drupal. If not, Drupal might just be a side gig.

The best way to sniff out the CMS that’s powering the website is using Wappalyzer. This way you can easily see if a website is built with Drupal. Beware that sometimes wappalyzer won’t return any results in the CMS column. In that case the website most likely is headless and can still use Drupal as an underlying infrastructure. In that case it’s best to just straight up ask the agency if they use Drupal for their own website.

What other Drupal websites have they built?

The agency should be able to provide a list of at least five other Drupal websites they have developed. It doesn't need to be exactly in the same industry your business is in. Just make sure they made some Drupal websites. And if you’re looking to get a community built it’s a bonus when they already have something similar included in their portfolio.

What is their knowledge of existing Drupal modules?

If you want an agency to design and build a Drupal website for you it’s because you have a problem. This can be something like:

  • I want to attract more customers with my website
  • I need to share files privately with my customer
  • I want users to search through thousands of nodes

Before you contact an agency it’s important to have a detailed description of your problem. With this you can ask the agency how they think they can solve this problem for you. This doesn’t need to be a step to step guide, but more of a global overview of what techniques, modules or custom code they think will be required. 

Hopefully your problem is a common use case and can be solved with existing modules. Ask for a list of modules the agency will be using. If the agency has difficulty providing a list with modules this should be a red flag. They either are not experienced enough knowing what modules are available or they want to solve everything with custom code ignoring already existing technology which can be costly, spiking up the price of the proposal.

Nov 27 2021
Nov 27

What is no code?

Basically it comes down to building a complex website using a Graphical User Interface instead of typing code using a programming language such as PHP.

Personal experience

I’ve been designing and building Drupal websites for over 10+ years now and I didn’t have to write any code once. I might have tweaked some files here and there but the number of times I had to dive into some PHP code can be counted on one hand. 

What I have built with Drupal are not just simple websites with a few pages. I’ve built:

  • A video sharing sites for a University
  • An intranet where employees can share news and files. Including an overview of upcoming birthdays and an extensive search option where employees can easily find each other's information, such as an e-mail or telephone number
  • A community where users can sign up and privately share information. Even creating (private) groups within the community

Drupal is flexible

Out of the box Drupal is already very flexible. You can create content types, such as Articles, and add fields to them. These fields can be anything such as a simple text field or an image, video, file, mp3. You can also reference any entity within a field making it possible to set up relations between different content items (called nodes in Drupal). But you can even reference users or taxonomy terms.

Because Drupal is built with this flexibility in mind almost anything is an entity. Making it possible to connect different parts and ensuring all Drupal modules play nicely together.

Nov 15 2021
Nov 15

Custom Code unsustainable

Custom Code makes you dependent on the developer who created this piece of code. What happens if the code needs to be changed but the developer has moved on or isn’t available for a long period of time? You might end up with a broken website.

In theory it is always possible to let another developer take a swing at it, but most likely they will grunt at the code they get presented and will tell you it’s better to start from scratch. Which is fair, because it probably will be faster for them than to go through someone else’s code trying to figure out how they created the solution. 

Compare this to an already available Drupal module which you can download and use for free. Every Drupal module has a maintainer who is responsible for bugs and feature requests. If this maintainer becomes inactive it is possible for someone else to pick up where they left. Everyone can report a bug or request a feature and multiple developers can look into a sustainable solution.

When you can’t avoid Custom Code

If you need to connect Drupal to another system, such as an internal CRM tool, it is impossible to avoid some Custom Code. The arguments above still apply, though. Is it really necessary to connect these systems to Drupal to sync data? If it only concerns a few instances every month maybe it’s something that can be done by hand. If it is a well known system there might already be a module available, so make sure to check that first.

Update: After posting this blog I got a few reactions and I feel like I need to nuance a bit. If you are a developer and you can create a solution writing 10 lines of Custom Code instead of using a couple of modules, then by all means go for it. This blog is intended as a cautionary tale for organisations wasting money on a small part of a Drupal website (Custom Code) where it could better be spent on other facets of the website. Let me phrase it this way: if the Custom Code costs more than a third of the total price of your Drupal website, there might be something askew making you reconsider.

How do you feel about Custom Code?

Let me know by leaving a comment. I'm interested to hear use cases where Custom Code is unavoidable or why Custom Code might be better than an existing module.

Also, don’t forget to subscribe to my Drupal newsletter of Drupal RSS Feed

Nov 10 2021
Nov 10

Say, for example, that you want to share content (like PDF files) with your clients. You don’t want them to be publicly available, because they are for your clients eyes only. You also don’t want clients looking at each other's files. This is where the Group module comes in. Here you can create different group types (such as client) with which you can create a separate group for each client you want to share files with. 

In this tutorial I will show you how to set up the group module which can be used to share nodes privately to a set group of users.

Setting the Privates Files Directory

If you only want to share nodes within a group you can ignore this part. If you want to share files you need to create a private files directory. Else users without the correct permissions would still be able to access the files by guessing the correct URL of the file and typing it in the address bar of their browser. Learn how to set up a private files directory for Drupal

Setting up the Group module

  • Install the Group module
  • Enable the Group node module
  • Navigate to Group > Group types
  • Click + Add group type
  • Name the group type. I will follow the example I mentioned above and name it Client
  • You can enable or disable Create a new revision when a group is modified as you please
  • Enabling The group creator automatically becomes a member can be helpful when you want users to create their own groups
  • It’s best to enable Group creator must complete their membership in case you have required fields on a users’ profile page
  • Enabling both Automatically configure an administrative role and Automatically assign this administrative role to group creators is very useful, because now you can create admin permissions within the group
  • Click Save group type
  • Next we need to create the content type that will be used to share within the groups. Navigate to Structure > Content types
  • Click + Add content type
  • I will name this content type File
  • You can fill in the settings in the tabs as you please
  • Click Save and manage fields
  • You can now add any fields you like, but as in the example I’m following I will add a File field. Click + Add field
  • Below Add a new field select File
  • Label the field File
  • Click Save and continue
  • Under Upload destination select Private Files (see the remark I made about this above)
  • Click Save field settings
  • In the next screen you can change the settings as you please. Below Allowed file extensions I’ll put pdf as I only want to share PDF files
  • I like to name the File directory something more generic like files
  • I also check Enable Description field because then you can label the fields with something that makes more sense instead of just showing the filename
  • Click Save settings
  • What we need to do next is to make nodes of this content type available to the Client group we’ve created. Navigate to Group > Group types > Client and click on the Content tab
  • Click on Install next to Group node (File)
  • You can leave the setting on the next screen as is. Click on Install plugin
  • To test if this works we need to create a Group (Client). Navigate to Groups
  • Click on + Add group
  • Enter any title and click on Create client and complete your membership
  • Enter any URL alias. This will be shown in the address bar of the browser when viewing the group and click on Save group and membership
Oct 28 2021
Oct 28

Making it possible for visitors to create an account

Drupal core comes with great user management capabilities. Enabling users to create an account is as simple as turning a switch. Under Configuration > People > Account settings below Who can register accounts? I’ll select Visitors.

Let users can create content

I want users to be able to create content, so I’ll add an extra ‘member’ role with which I can grant users with this role specific permissions. You might think this step is unnecessary because you can also use the default ‘Authenticated user’ role. In the past, however, I’ve learned it’s best to always create an extra role for site members. This way you can take away permissions from a user without having to block or delete them. Using the Registration role module I can automatically assign the member role to any newly created user.

I’ll create a new content type called ‘Post’. This content type will the following fields:

  • Title
  • Text (plain, long)
  • Image (Drupal core image field)
  • Link (Drupal core link field)

I’ll also enable comments for this content type as I want users to have the ability to discuss the post, which is a important part of Reddit as well. I’ll set them up as detailed in this blog post on how to optimize comments for Drupal.

Next I will give users with the member role the permission to create nodes of the ‘Post’ content type. Also a menu item needs to be created to the node add form of this content type in the main menu. This way users with the member role can start posting content immediately.

Enabling users to up or down vote content

At the core of Reddit is the up or downvoting of posts. Creating a leader board displaying the most upvoted posts on top. To accomplish this with Drupal I will install the Voting API and the Rate module. Within the Rate configuration I create a thumbs up/down widget and set it to be displayed on all nodes of the Post content type. I will also set the permissions so that users with the member role can vote.

When a user of with the member role navigates to a node of the post type a thumbs up/down widget is shown. Users can now upvote or downvote the post.

Next I’ll create a view with all the nodes of the Post content type. These nodes are sorted based on upvotes, displaying the most upvoted content at the top of the list. I’ll also enable voting on this view so users can quickly browse all the posts and vote on posts. 

I’ll also add an infinite scroll to this view so users can keep on scrolling and rating content without navigating to another page.

Oct 20 2021
Oct 20

Optimizing your Drupal website for Search engines

Out of the box Drupal can use some help when it comes to SEO. One of the most impactful things you can do is installing the Pathauto module. With this module you can automatically generate URLs for all your nodes that make sense. So instead of node/34 your node can also be viewed with a prettier URL such as services/hosting. You can create patterns to generate these paths based on tokens. 

The patterns I always use to generate the paths are as follow: 

  • I start with the plural of the content type. If the content type is named article, the first part of the path will be articles. The second part will be the title for which you can use the following token [node:title].
  • There are some exceptions such as nodes of the Page content type which only need the [node:title] as URL. Pages such as contact or the privacy statement for example.
  • In some cases you can extend the URLs by adding a token for a field that is referencing another node or taxonomy term. A good example is an Article content type that refers to a taxonomy term that is used as a category. The pattern would then be: articles/[node:field_category]/[node:title]. Adding this extra category in the URL can also boost your SEO.

Next you want to install the Metatag module. With this module you have more control over the meta tags that will be used in the HTML of your nodes. These meta tags can be used by search engines (such as Google) or social media networks (such as Facebook and Twitter) to display your content. Do note that meta tags keywords aren’t relevant anymore, because they were frequently abused as SPAM. So it’s not worth the hassle to add them to your nodes. Also, even though you enter a meta tag description, Google may still use other parts of your content to display in the search results.

Another thing that can boost your SEO is by using the XML Sitemap module. This module creates an up to date XML sitemap with paths to all the nodes in your websites. Every time you publish a new node this will be automatically included in the sitemap. This sitemap can then be used by SEO services such as Google Search Console to crawl your website. Using the XML sitemap instead of relying on the old fashioned way of crawling (waiting for a bot to visit your website) means your content will be visible faster within the search engine results. 

Sometimes you have pages that don’t need to be included in the search results. Such as profile pages of users or content that’s only referenced by other content. In that case you can use the Rabbit Hole module to determine what needs to happen when a visitor (or search engine bot) visits such a page. You can either show a 404 or a 403 error. Or you can redirect the user to another page. This can be done based on content types, users, taxonomy terms, files, media, etc. You can also determine this on a node by node basis.

How to work with images and video

Packed with Drupal core comes the great Media module. The only thing you need to do is to enable it after installing Drupal. With the Media module all your images and videos become their own entity. Meaning you can reference the same image or video when you want to display a media element. So if you want to reuse an image for multiple nodes, you can now easily select it instead of needing it to upload twice. This saves hassle and space on your server. Learn how to set up the Media module correctly.

Improve the theming capabilities of your Drupal website 

It’s best to start off with a very basic starter theme. This way you can start theming immediately. Here you can learn more about the theme I always use at the start of every new Drupal project.

If you want more control over how to style different blocks you can install the Block Class module. This module gives every block an extra input field which you can use to add one or multiple CSS classes. In your stylesheet you can create reusable classes which saves you work (and time) because you don’t need to target every block individually by ID.

Another thing you can do, to make your theming life easier, is by installing the Link Attributes widget module. After installing and enabling this module you will get the option to give menu items extra attributes such as a CSS class. Now you have more control over how an individual menu item should be styled, such as a login link.

I already talked about the Paragraphs module above and it can even be more powerful for themers if you add the Classy Paragraphs module. With this module you can assign one or multiple classes to a paragraph, giving you more freedom when it comes to styling your paragraphs. I use it to give editors more control on the maximum width of a paragraph (small, medium, large or full screen). 
Tip: If you patch this module you have more control over what options (paragraph classes) users can choose when creating paragraphs.

What do you always add when you create a new Drupal website?

Let me know by leaving a comment. Or if you have any question about the above you can use the comment section as well.

Don’t forget to subscribe to my Drupal newsletter or Drupal RSS feed.

Oct 13 2021
Oct 13
  1. Image effects
    This module greatly improves the things you can do to your images within your Drupal image styles. Such as changing the brightness, contrast or opacity. You can overlay images with other images (such as a watermark) or you can blur or sharpen images. Check this readme file for all the effects that are available.
  2. Flag
    With the flag module you can create custom flags (buttons) for your nodes. For example users can flag nodes as being helpful or report spam. You can also sort nodes with views on most or least flagged. Or you can create a views block of all the nodes a particular user has flagged.
  3. Voting API
    This module is required if you want users to vote on content. The module itself does not supply a way for users to interact with your nodes, but it offers an API for other modules to build upon, such as Fivestar.
  4. Fivestar
    As mentioned above, this module let’s users rate nodes. It integrates with Views so you can create view blocks only showing nodes above or below a rating threshold. Or you can sort nodes based on rating. It also makes it possible for anonymous users to vote.
  5. Inline Entity Form
    Create, edit or remove referenced content directly from the current edit screen with this module. If you are adding a node and referencing other nodes you sometimes want to make an adjustment to the referenced node, such as correcting a title or deleting outdated content. Inline Entity Form gives you these capabilities directly in the editing form.
  6. IP Login
    This module will log you into your Drupal website automatically based on your IP address. You can even set an IP range or make use of wildcards.
  7. DraggableViews
    Sorting nodes on publication date or title is easy with views. Things become a bit more complex if you want to custom sort your nodes. The DraggableViews module helps by giving you the option to create views where you can drag and drop your sorting, just as you can do with taxonomy terms. Now you can adjust a view and sort it based on the weight assigned by the DraggableViews module.
  8. Domain Access
    With Domain Access you can create multiple domains within the same Drupal installation which can function as separate sites. More about multi sites with Drupal and Domain Access.
  9. Views Data Export
    With this module you can export any data returned by a view as a CSV, XLS, DOC, TXT or XML file. This means you can create a view, as you normally would, with your preferred filters and sorting and exporting it to a file.
  10. Automated Logout
    If you want an extra layer of security you can use this module to automatically log out users after a certain amount of time has passed since the last interaction. You can set different timeout rules for different roles. Optionally you can integrate a JavaScript timer counting down the time the user will be logged out.
  11. Entity Clone
    Entity clone lets you easily clone different entities such as nodes, content types, users or roles. Just beware that cloning paragraphs is not yet supported and can seriously mess up your site.
  12. Field Formatter Class
    After installing this module you will be able to give a field one or multiple extra custom CSS classes from the display view of the content type containing the field. Especially handy for themers to create global classes which can be reused instead of targeting every field individually with CSS.
  13. Taxonomy Access Control Lite
    This is a very powerful module if you want to control the access of your nodes based on user roles. You can create a taxonomy vocabulary and create a reference from nodes to terms within this vocabulary. Based on the term referenced to the node you can grant or deny users with a particular role to view, edit or delete these nodes.

I want to thank arek and Casiva Agustin for some of these suggestions.

If you have any suggestions of your own, please let me know by leaving a comment. Also don’t forget to subscribe to my Drupal newsletter or Drupal RSS Feed.

Oct 05 2021
Oct 05

Why you should enable comments on your Drupal website

Comments are a great way for users to interact with your website. It gives them the ability to ask you about the stuff you write. This can give you new insights on what to write about. It also opens up the possibility to improve your content when something is not clear or when you got something wrong. 

Comments also improve the SEO of your Drupal website. Because commenters tend to reuse important keywords, when asking questions or discussing the content you’ve written. Also, every time a new comment is posted, search engines such as Google will view this an update to the original post. Signalling that the content is being updated, which in most cases it is because you clarify things or answer questions.

Don’t be afraid to open up comments. Of course someone can disagree with you, which doesn’t have to be bad. It gives you an opportunity to restate your point or maybe change the way you think about things.

Then there are spammers, which can easily be blocked with Cleantalk (which I will discuss later in this post) and people who mean harm by posting weird or offensive stuff. The chance you get these types of people to comment on your content are very slim. And even then you can just quickly delete them when you got your notification setup correctly (which I will get to below).

Why host your own comments and not use comment services such as disqus

Instead of using the Drupal comment functionality you can also outsource this by using external comments services such as Disqus. I would advise against this, because:

  • The comments are not your own. What happens if the service goes out of business? All the valuable comments (and content) would be gone.
  • Most services wrap the comments in a JavaScript container avoiding search engines such as Google to index them correctly. The SEO benefits of having comments on your site would be non-existent.
  • The big advantage of outsourced comment services, such as Disqus, is blocking the SPAM, but if you use Cleantalk (more about this service below) you can easily do this yourself.

Setting up comments

If you want people to post comments on your Drupal website you first need to enable the comments module which comes with the Drupal core. After that, you can add a new field to the content type you want people to comment on. As a field type select Comments.

I like to enable Threading so you can create a visual distinction when someone replies on a comment. I set the comments per page to 999. I want all the comments to show on the same page without pagination. Next is set Anonymous commenting to Anonymous posters may leave their contact information. This will enable users to comment anonymously, but also have the ability to enter their name and/or email. Making sure users can enter their email is important when using the Comment notify module, but I will get to that later in this post. 

Create a better way to add and reply to comments

The default comment functionality is fine, but to make the user experience even better you can install the Ajax Comments module. This module replaces the comment form with a version powered with Ajax. When a user posts a comment, only the comment section will be reloaded, instead of the whole page. Also, when replying on a comment the comment form will be loaded directly under the comment instead of redirecting to a new page. 

After installing the module you can enable the Ajax comments functionality on the display tab of the content type that has a comment field.

Sep 29 2021
Sep 29

How to override the HTML that is generated by Drupal

If you want to override HTML that is generated by Drupal, you will need to create a templates folder inside your Drupal theme folder. Here you can create so-called twig files with which you can tell Drupal how the HTML should be generated. 

Creating these twig files from scratch is a lot of work and also unnecessary. The best way is to go to the theme folder of the base theme you’re using, which you have specified in your themename.info.yml. In my case that would be Classy which is located at core/themes/classy. Here you will find a templates folder as well. Within this folder you will find subfolders which categorize specific Drupal elements. One folder, which is particularly important, is the layout folder. In this folder you will find (among others) two files which you want to override, namely:

  • html.html.twig
  • page.html.twig

Copy these files over to your own templates folder in your theme folder. You can also create a layout subfolder, which isn’t required, but does help keep things clear.

If you open the html.html.twig file you can see that this is the file which generates the , and the tag. You can overwrite this file by adding scripts such as Google Fonts (although you might want to load these locally). I always overwrite this file so I can point Drupal to my custom favicon icons which I generate with this favicon generator.

The page.html.twig file renders everything in the tag. This is important because here you can determine which regions should be rendered where. These are the regions you have specified in your themename.info.yml file. Rendering a region is done as follow:

  {% if page.hero %}

    {{ page.hero }}

  {% endif %}

Basically saying that if there is a block in the hero region then render the region. If you don’t enclose {{ page.hero }} within the if statement Drupal will always generate the (empty) region.  

Sep 23 2021
Sep 23

Before we start

In this example I will show nodes in a RSS feed of the ‘Article’ content type, which I’ve already created. This article content type contains an Image field (learn how to efficiently reuse your image fields) and a Summary field of the type Text (formatted, long). I prefer using a separate Summary field instead of the default Body with the built in summary option, because this gives me more flexibility.  

It’s also highly advisable to install the Publication Date module. This will add an extra field to your content type containing the date the node was actually published. You will need this date to correctly display nodes in a feed.

You can also use the creation date, but this might not always be the date stamp you want your nodes to have. If, for example, you’ve started a draft and finally publish the node a few days or weeks later, the creation date will lag behind the actual publish date. This can mess up the way your articles are displayed in an aggregator such as Planet Drupal.

Sep 18 2021
Sep 18
  • Download the latest version of Drupal 9 and extract the files on your local machine.
  • In the extracted Drupal 9 folder remove the following folders:
  • In the root of your local Drupal 8 site remove all the files and these folders:
  • Copy over all the files and folders from the Drupal 9 directory over to the directory of your local Drupal 8 site
  • Navigate to /update.php on your local Drupal 8 website
  • Fix any errors that might pop up and apply the database updates
  • If all went well your website should now be upgraded to Drupal 9
  • Go to your live Drupal 8 website and put it in maintenance mode by navigating to Configuration > Development > Maintenance mode
  • Open an FTP client and go to the Drupal 8 directory of your live site
  • Remove all files and folders
  • Upload all files and folders from your just upgraded local Drupal 9 site
  • Open Acquia Dev Desktop 2 and open the database manager by clicking on More
  • Select the correct database on the left and click on Export
  • Click on Start. This will initiate a download of your database in a .sql file
  • Go to your hosting panel of your live site and access the database manager (usually phpmyadmin)
  • Click on the database used for your live Drupal 8 website
  • Drop all tables
  • Import the .sql file you’ve exported
  • If all went well you can now visit your upgraded Drupal 9 website on your live location

As I said before, this might not be the correct way of upgrading a Drupal 8 to a Drupal 9 website, but for me it's the only thing that worked. Hopefully this will help you as well and if there is a flaw in my thinking please let me know by leaving a comment.

Also, don't forget to subscribe to my Drupal newsletter.

Sep 15 2021
Sep 15

Layout and (white)space

It’s important to use a lot of whitespace. Whitespace makes a design look professional. It’s better to have too much than too little whitespace. 

Use consistent pixel distances when it comes to spacing your elements. I use steps of 4 pixels. So all my elements are spaced with 4px, 8px, 16px, 24px, 32px, 64px etcetera. As a default I use 24px to space items on screens that are smaller than 800 pixels wide. If the viewport is wider I use media queries to increase the spacing to 32 pixels.

Also, it’s not always necessary to use the full width of a screen. If you have a block of text and display it full width on a large screen, it becomes unreadable. It’s better to limit the width of the block and centre it.

Sep 13 2021
Sep 13

Enabling crop styles on the Image media type

When we upload an image we want to be able to crop them for the different image styles.

  • Navigate to Structure > Media types > Image > Manage form display
  • Under Widget next to Image select ImageWidget crop
  • Click on the gear on the right side to open the settings
  • Under Crop type select all thee crop types (Hero, Thumbnail, Social)
  • Click Update
  • Click Save

When you want to upload an image to a blogpost and correctly crop them you have two ways of accomplishing this:

  1. Upload the image under Content > Media > + Add media. Select image and upload a file in the image field. As the upload is completed an extra set of Crop tabs will appear. You can now crop the image for the three different image styles and save the image. Next you can create or edit a blog post and click Add media in the image field we’ve created above. Select the image you’ve uploaded and cropped in the previous step. 
  2. You can also follow through this process the other way around. Meaning you will first create or edit a blog post and add media to the image field and upload an image directly while editing the blog. After saving the blog post you can still adjust the crop styles by navigating to Content > Media and edit (crop) the uploaded image.
Sep 08 2021
Sep 08

2 Page and site navigation 

Success Criterion 1.3.3 Sensory Characteristics
When instructions are given on your Drupal website they can’t be dependent on sensory characteristics of components such as shape, colour, size, visual location, orientation, or sound.

So for example you can’t just use an icon, such as a checkmark, to indicate something was done successful. It needs to be accompanied by a text description like ‘Your submission was sent’.

On my Drupal website I don’t give any instructions of this nature.

Success Criterion 1.3.4 Orientation
This criteria states that you can’t lock your site to a specific orientation such as landscape or portrait.

My Drupal site is fully responsive and viewable in any orientation.

Success Criterion 2.4.2 Page Titled
Every page needs a title (the

HTML element) that describes the purpose of the page.</p> <p>On my Drupal website I use the <a href="https://www.drupal.org/project/metatag">Metatag module</a> to generate the <title> tag. This tag is generated by using the title of the node and combining the name of my site such as:</p> <p><em>50 Drupal modules every Drupal professional should know about | Robert Roose: Drupal designer</em></p> <p>Every node on my Drupal website has a very descriptive title of what the page is about which is used in the <title> tag. </p> <p><a href="https://www.w3.org/TR/WCAG21/#headings-and-labels">Success Criterion 2.4.6 Headings and Labels</a><br /> Just like the title of the page all the headings and labels used on your website should be clear and describe the element it concerns.</p> <p>As I try to write very concise and clear content I think I got this covered. All my headings and labels have the intent to be descriptive of the content it concerns.</p> <p><a href="https://www.w3.org/TR/WCAG21/#consistent-navigation">Success Criterion 3.2.3 Consistent Navigation</a><br /> Navigation elements (such as the main menu or search) should be in the same relative order and consistent through all pages.</p> <p>On my Drupal website I have two navigation elements, the footer menu which is always positioned on the bottom of the website and a main menu. This main menu will become sticky when a user scrolls down, so it’s always visible in the same position. The main menu becomes a hamburger menu tucked on the left side when the viewport becomes too small to display the full menu. This might be an issue because the functionality and position of the menu changes. But as this is a common design pattern I believe this won’t be rejected.</p> <p><a href="https://www.w3.org/TR/WCAG21/#consistent-identification">Success Criterion 3.2.4 Consistent Identification</a><br /> Throughout your Drupal website components need to be consistently identified. So for example if you have a block with the latest articles on your homepage you have to use the same title for your block as for an overview page with all your articles. </p> <p>As Drupal is modular reusing block and functionality it’s pretty safe to say all components are consistently identified.</p> </div> </div> </div> <div class="paragraph__width paragraph__width--small paragraph paragraph--type--newsletter paragraph--view-mode--default paragraph--id--63"> <div class="paragraph__content"> <div class="clearfix text-formatted field field--name-field-pg-text field--type-text-long field--label-hidden field__item"><h2>Subscribe to my Drupal Newsletter</h2> <p>And receive updates about new Drupal posts (and more) directly in your inbox!</p> </div> <div class="field field--name-field-pg-form field--type-webform field--label-hidden field__item"><span id="webform-submission-drupal-newsletter-paragraph-63-form-ajax-content"></span><div id="webform-submission-drupal-newsletter-paragraph-63-form-ajax" class="webform-ajax-form-wrapper" data-effect="fade" data-progress-type="throbber"><form class="webform-submission-form webform-submission-add-form webform-submission-drupal-newsletter-form webform-submission-drupal-newsletter-add-form webform-submission-drupal-newsletter-paragraph-63-form webform-submission-drupal-newsletter-paragraph-63-add-form js-webform-details-toggle webform-details-toggle" data-drupal-selector="webform-submission-drupal-newsletter-paragraph-63-add-form" action="/blog/drupal/creating-more-accessible-drupal-website" method="post" id="webform-submission-drupal-newsletter-paragraph-63-add-form" accept-charset="UTF-8"> <fieldset class="form js-webform-type-fieldset webform-type-fieldset js-form-item form-item js-form-wrapper form-wrapper" data-drupal-selector="edit-form" id="edit-form"> <legend> <span class="visually-hidden fieldset-legend">Form</span> </legend> <div class="fieldset-wrapper"> <div class="js-form-item form-item js-form-type-email form-type-email js-form-item-e-mail form-item-e-mail"> <label for="edit-e-mail" class="js-form-required form-required">E-mail</label> <input data-webform-required-error="You forgot to fill in your e-mail." data-drupal-selector="edit-e-mail" type="email" id="edit-e-mail" name="e_mail" value="" size="60" maxlength="254" class="form-email required" required="required" aria-required="true" /> </div> <div data-drupal-selector="edit-actions" class="form-actions webform-actions js-form-wrapper form-wrapper" id="edit-actions"><input class="webform-button--submit newsletter-subscribe button button--primary js-form-submit form-submit" data-drupal-selector="edit-actions-submit" data-disable-refocus="true" type="submit" id="edit-actions-submit" name="op" value="Subscribe" /> </div> </div> </fieldset> <input autocomplete="off" data-drupal-selector="form-oxmyffubgxivgjl5vcjsf7yehysja1abyidwlabxdxe" type="hidden" name="form_build_id" value="form-oXmYFfUbgXIvgJl5VcJsf7YehysJa1AByIdWlAbXdxE" /> <input data-drupal-selector="edit-webform-submission-drupal-newsletter-paragraph-63-add-form" type="hidden" name="form_id" value="webform_submission_drupal_newsletter_paragraph_63_add_form" /> </form> </div></div> </div> </div> <div class="paragraph paragraph--type--text paragraph--view-mode--default paragraph--id--64"> <div class="paragraph__content"> <div class="clearfix text-formatted field field--name-field-pg-text field--type-text-long field--label-hidden field__item"><h2>3 Colour and text</h2> <p><a href="https://www.w3.org/TR/WCAG21/#use-of-color">Success Criterion 1.4.1 Use of Colour</a><br /> Colour cannot be the only visual indicator to inform a user, indicate an action or ask for a reaction. Such as only using a color to indicate an input field which is not filled in correctly.</p> <p>Here is where my website is currently failing. I only used a colour to indicate a link or active menu state. As the contrast isn’t sufficient I added a border (underline) to all the links in the main content. Also I’ve added a line to indicate the active menu item.</p> <p><a href="https://www.w3.org/TR/WCAG21/#contrast-minimum">Success Criterion 1.4.3 Contrast (Minimum)</a><br /> Text (and images of text) has to have a contrast ratio of 4,5:1 and large text a contrast ratio of 3:1.</p> <p>For the main text on my website is used #888888 (gray) on a #222222 (near black) background. When I check these values with the <a href="https://webaim.org/resources/contrastchecker/">WebAIM contrast checker</a> it results in a contrast ratio of 4,48:1 just failing the criteria. So I’ve changed the #888888 to #999999 which does pass the test. </p> <p><a href="https://www.w3.org/TR/WCAG21/#resize-text">Success Criterion 1.4.4 Resize text</a><br /> Users should be able to resize the text on your Drupal website without loss of content or functionality.</p> <p>Because my Drupal website is fully responsive this isn’t any problem. Blowing up the size of the text to 200% doesn’t break the content or functionality.</p> <p><a href="https://www.w3.org/TR/WCAG21/#images-of-text">Success Criterion 1.4.5 Images of Text</a><br /> Basically this says you shouldn’t use text as an image. Because of modern CSS techniques there is no excuse anymore to display text as an image, which is why this criteria doesn’t concern most up to date websites, like mine.</p> <p><a href="https://www.w3.org/TR/WCAG21/#reflow">Success Criterion 1.4.10 Reflow</a><br /> Content and functionality should not break if the website is viewed in a viewport of 320 pixels wide and 256 pixels high. As mentioned above my Drupal website is fully responsive so this won’t be an issue.</p> <p><a href="https://www.w3.org/TR/WCAG21/#non-text-contrast">Success Criterion 1.4.11 Non-text Contrast</a><br /> User interface components (to control the website such as links) and graphical objects (to understand the website such as graphs or diagrams) need a 3:1 contrast.</p> <p>I’ve checked all elements on contrast ratio and they pass the 3:1 requirement.</p> <p><a href="https://www.w3.org/TR/WCAG21/#text-spacing">Success Criterion 1.4.12 Text Spacing</a><br /> It needs to be possible to change the text with an external tool to the following settings:</p> <ul> <li>Line height (line spacing) to at least 1.5 times the font size;</li> <li>Spacing following paragraphs to at least 2 times the font size;</li> <li>Letter spacing (tracking) to at least 0.12 times the font size;</li> <li>Word spacing to at least 0.16 times the font size.</li> </ul> <p>All content should still be visible using these style settings.</p> <p>To test this you can use the <a href="https://add0n.com/stylus.html">Stylus browser plugin</a>. This plugin enables you to inject CSS code on any website. Create a new style and use the following CSS code:</p> <p><code>* {<br /> line-height: 1.5 !important;<br /> letter-spacing: 0.12em !important;<br /> word-spacing: 0.16em !important;<br /> }</p><p>p {<br /> margin-bottom: 2em !important;</code></p> <p>If I visit my website, with the CSS styles as an override, nothing breaks so this should be fine.</p> </div> </div> </div> <div class="paragraph paragraph--type--text paragraph--view-mode--default paragraph--id--65"> <div class="paragraph__content"> <div class="clearfix text-formatted field field--name-field-pg-text field--type-text-long field--label-hidden field__item"><h2>4 Basic code analysis</h2> <p><a href="https://www.w3.org/TR/WCAG21/#bypass-blocks">Success Criterion 2.4.1 Bypass Blocks</a><br /> You need to have a way to bypass blocks and directly navigate to the main content.</p> <p>Out of the box Drupal provides a skip link. If you press tab viewing your Drupal website a skip link should appear. My Drupal website also has this skip link, but it wasn’t styled yet, showing as a blue link on a dark background. I’ve changed the styling of my skip link so it’s better visible.</p> <p><a href="https://www.w3.org/TR/WCAG21/#language-of-page">Success Criterion 3.1.1 Language of Page</a><br /> The language of the page has to be set correctly. This can be done by giving your HTML tag a lang attribute containing the language code of the language that is used on the page. </p> <p>Drupal sets this automatically so this should not be a problem. Even if your <a href="https://robertroose.com/blog/drupal/tips-setting-your-multilingual-drupa...">website is multilingual</a> and you correctly use Drupal's built in functionality this should be no issue.</p> <p>Checking the HTML tag of this website I see it correctly displays the <em>lang = “en”</em> attribute. Also, when I check the Dutch version of my website it displays the <em>lang = “nl”</em> attribute.</p> <p><a href="https://www.w3.org/TR/WCAG21/#language-of-parts">Success Criterion 3.1.2 Language of Parts</a><br /> In some cases it’s possible to have a quote in a different language on your website. If so you need to identify this HTML part correctly by adding the lang attribute.</p> <p>As my website is completely in English there is no action needed on my part to correct this.</p> <p><a href="https://www.w3.org/TR/WCAG21/#parsing">Success Criterion 4.1.1 Parsing</a><br /> Incorrect HTML (such as tags that are opened but not closed) can cause issues when viewing a website with a screen reader.</p> <p>I’ve checked my website with the <a href="https://validator.w3.org/">W3C validator</a>. I’m getting some warnings but no errors, which basically means I’ve got no faulty or incorrect code.</p> </div> </div> </div> <div class="paragraph paragraph--type--text paragraph--view-mode--default paragraph--id--66"> <div class="paragraph__content"> <div class="clearfix text-formatted field field--name-field-pg-text field--type-text-long field--label-hidden field__item"><h2>Conclusion</h2> <p>As you can see Drupal is pretty accessible out of the box. Most issues were caused by my custom theme. but we’re easily fixed. Hopefully this blog inspired you to look into the accessibility of your website as well.</p> <p>If you have any additional tips or questions, please let me know by leaving a <a href="#comments">comment</a>. Also don’t forget to subscribe to my <a href="https://robertroose.com/drupal-newsletter">Drupal newsletter</a>!</p> </div> </div> </div> <div class="paragraph__style paragraph__style--small-header paragraph paragraph--type--block paragraph--view-mode--default paragraph--id--67"> <div class="paragraph__content"> <div class="field field--name-field-pg-block field--type-block-field field--label-hidden field__item"><div class="views-element-container block block-views block-views-blockblog-block-2" id="block-views-block-blog-block-2"> <h2>More blog posts about Drupal</h2> <div><div class="articles related view view-blog view-id-blog view-display-id-block_2 js-view-dom-id-1d30b500fb43247f41a707fda78ce4bbd0cf4b5a3a56a4130476dfec35d81c9b"> <div class="view-content"> <div class="views-row-link views-row"><div class="views-field views-field-title"><h2 class="field-content"><a href="https://robertroose.com/blog/drupal/drupal-theming-tips-web-designers-st..." hreflang="en">Drupal theming tips for web designers starting with Drupal</a></h2></div><div class="views-field views-field-field-node-summary"><div class="field-content">With this blogpost I, Drupal web designer for 10+ years, will show you how I theme my Drupal websites. How does it work, what is my set up and what do you need to be aware of. </div></div><span class="views-field views-field-published-at"><span class="views-label views-label-published-at">Published</span><span class="date">29 September 2021</span><span class="arrow"></span></span><div class="views-field views-field-field-node-image"><div class="field-content"> <img src="https://robertroose.com/sites/default/files/styles/thumbnail/public/imag..." width="450" height="300" alt="Woman working on a computer" loading="lazy" typeof="foaf:Image" class="image-style-thumbnail" /> </div></div></div> <div class="views-row-link views-row"><div class="views-field views-field-title"><h2 class="field-content"><a href="https://robertroose.com/blog/drupal/tips-setting-your-multilingual-drupa..." hreflang="en">Tips for setting up your multilingual Drupal website</a></h2></div><div class="views-field views-field-field-node-summary"><div class="field-content">As of Drupal version 8 multilingual support is baked in. Still, it can be frustrating to let Drupal play nice with more than one language. In this blog I’ll help you with some annoying quirks. </div></div><span class="views-field views-field-published-at"><span class="views-label views-label-published-at">Published</span><span class="date">5 August 2021</span><span class="arrow"></span></span><div class="views-field views-field-field-node-image"><div class="field-content"> <img src="https://robertroose.com/sites/default/files/styles/thumbnail/public/imag..." width="450" height="300" alt="Flags of the UN in front of the Eifel tower" loading="lazy" typeof="foaf:Image" class="image-style-thumbnail" /> </div></div></div> <div class="views-row-link views-row"><div class="views-field views-field-title"><h2 class="field-content"><a href="https://robertroose.com/blog/drupal/how-design-and-build-sustainable-cli..." hreflang="en">How to design and build a sustainable climate friendly Drupal website</a></h2></div><div class="views-field views-field-field-node-summary"><div class="field-content">In this blogpost I will share how you can design and build an eco friendly Drupal website. </div></div><span class="views-field views-field-published-at"><span class="views-label views-label-published-at">Published</span><span class="date">16 July 2021</span><span class="arrow"></span></span><div class="views-field views-field-field-node-image"><div class="field-content"> <img src="https://robertroose.com/sites/default/files/styles/thumbnail/public/imag..." width="450" height="300" alt="A row of trees" loading="lazy" typeof="foaf:Image" class="image-style-thumbnail" /> </div></div></div> </div> </div> </div> </div> </div> </div> </div> </div> <section id="node-article-field-node-comments" class="field field--name-field-node-comments field--type-comment field--label-above comment-wrapper"> <a name="comments" class="jump-to-comments"></a> <form class="comment-default-comments-form comment-form ajax-comments-reply-form-node-19-field_node_comments-0-0 ajax-comments-form-add" data-user-info-from-browser id="ajax-comments-reply-form-node-19-field-node-comments-0-0" data-drupal-selector="comment-form" action="https://robertroose.com/comment/reply/node/19/field_node_comments" method="post" accept-charset="UTF-8"> <div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-name form-item-name"> <label for="edit-name">Your name</label> <input data-drupal-default-value="Anonymous" data-drupal-selector="edit-name" type="text" id="edit-name" name="name" value="" size="30" maxlength="60" class="form-text" /> </div> <div class="js-form-item form-item js-form-type-email form-type-email js-form-item-mail form-item-mail"> <label for="edit-mail">Email</label> <input data-drupal-selector="edit-mail" aria-describedby="edit-mail--description" type="email" id="edit-mail" name="mail" value="" size="30" maxlength="64" class="form-email" /> <div id="edit-mail--description" class="description"> The content of this field is kept private and will not be shown publicly. </div> </div> <div class="js-form-item form-item js-form-type-url form-type-url js-form-item-homepage form-item-homepage"> <label for="edit-homepage">Homepage</label> <input data-drupal-selector="edit-homepage" type="url" id="edit-homepage" name="homepage" value="" size="30" maxlength="255" class="form-url" /> </div> <input data-drupal-selector="edit-form-html-id" type="hidden" name="form_html_id" value="ajax-comments-reply-form-node-19-field-node-comments-0-0" /> <input data-drupal-selector="edit-wrapper-html-id" type="hidden" name="wrapper_html_id" value="node-article-field-node-comments" /> <input autocomplete="off" data-drupal-selector="form-omaz4o9lpd4o3ghqu1tkf4mijbg2pedigvfarsub-w4" type="hidden" name="form_build_id" value="form-omaz4o9Lpd4O3ghqU1tkF4MIJBG2pEdIGVFARsub-w4" /> <input data-drupal-selector="edit-comment-default-comments-form" type="hidden" name="form_id" value="comment_default_comments_form" /> <div class="field--type-text-long field--name-comment-body field--widget-text-textarea js-form-wrapper form-wrapper" data-drupal-selector="edit-comment-body-wrapper" id="edit-comment-body-wrapper"> <div class="js-text-format-wrapper text-format-wrapper js-form-item form-item"> <div class="js-form-item form-item js-form-type-textarea form-type-textarea js-form-item-comment-body-0-value form-item-comment-body-0-value"> <label for="edit-comment-body-0-value" class="js-form-required form-required">Comment</label> <div class="form-textarea-wrapper"> <textarea class="js-text-full text-full form-textarea required resize-vertical" data-media-embed-host-entity-langcode="en" data-drupal-selector="edit-comment-body-0-value" id="edit-comment-body-0-value" name="comment_body[0][value]" rows="5" cols="60" placeholder="" required="required" aria-required="true"></textarea> </div> </div> <div class="js-filter-wrapper filter-wrapper js-form-wrapper form-wrapper" data-drupal-selector="edit-comment-body-0-format" id="edit-comment-body-0-format"><div class="filter-help js-form-wrapper form-wrapper" data-drupal-selector="edit-comment-body-0-format-help" id="edit-comment-body-0-format-help"><a href="https://robertroose.com/filter/tips" target="_blank" data-drupal-selector="edit-comment-body-0-format-help-about" id="edit-comment-body-0-format-help-about">About text formats</a></div> <div class="js-filter-guidelines filter-guidelines js-form-wrapper form-wrapper" data-drupal-selector="edit-comment-body-0-format-guidelines" id="edit-comment-body-0-format-guidelines"><div data-drupal-format-id="restricted_html" class="filter-guidelines-item filter-guidelines-restricted_html"> <h4 class="label">Restricted HTML</h4> <ul class="tips"> <li>Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id></li> <li>Lines and paragraphs break automatically.</li> <li>Web page addresses and email addresses turn into links automatically.</li> </ul> </div> </div> </div> </div> </div> <div class="js-form-item form-item js-form-type-checkbox form-type-checkbox js-form-item-notify form-item-notify"> <input data-drupal-selector="edit-notify" type="checkbox" id="edit-notify" name="notify" value="1" checked="checked" class="form-checkbox" /> <label for="edit-notify" class="option">Send me an email when I get a reply</label> </div> <input data-drupal-selector="edit-notify-type" type="hidden" name="notify_type" value="2" /> <div data-drupal-selector="edit-actions" class="form-actions js-form-wrapper form-wrapper" id="edit-actions--3"><input data-drupal-selector="edit-ajax-comments-reply-form-node-19-field-node-comments-0-0" type="submit" id="edit-ajax-comments-reply-form-node-19-field-node-comments-0-0" name="op" value="Save" class="button button--primary js-form-submit form-submit" /> </div> </form> </section> </div> </article> </div> </div> </div> </main> <footer role="contentinfo" class="footer"> <div class="region region-footer"> <nav role="navigation" aria-labelledby="block-molyneux-bottommenu-menu" id="block-molyneux-bottommenu" class="settings-tray-editable block block-menu navigation menu--bottom-menu" data-drupal-settingstray="editable"> <h2 class="visually-hidden" id="block-molyneux-bottommenu-menu">Bottom menu</h2> <ul class="menu"> <li class="menu-item"> <a href="https://robertroose.com/privacy-statement" data-drupal-link-system-path="node/33">Privacy statement</a> </li> </ul> </nav> </div> </footer> </div> </div> <div class="off-canvas-wrapper"><div id="off-canvas"> <ul> <li class="menu-item--_e2f866f-d786-4a7d-801f-00453e05c22a"> <a href="https://robertroose.com/" data-drupal-link-system-path="<front>">Blog</a> </li> <li class="menu-item--_899de69-78bb-4217-b68e-6b34bc834ba8"> <a href="https://robertroose.com/about-me" data-drupal-link-system-path="node/11">About me</a> </li> <li class="menu-item--_84fc7c1-7f1e-4555-ae58-0f7c8738ebde"> <a href="https://robertroose.com/drupal-newsletter" data-drupal-link-system-path="node/12">Newsletter</a> </li> <li class="menu-item--_916d83a-dd40-4e8d-8052-c74bde5729e7"> <a href="https://robertroose.com/contact" data-drupal-link-system-path="node/6">Contact</a> </li> </ul> </div></div> <script type="application/json" data-drupal-selector="drupal-settings-json">{"path":{"baseUrl":"\/","scriptPath":null,"pathPrefix":"","currentPath":"node\/19","currentPathIsAdmin":false,"isFront":false,"currentLanguage":"en"},"pluralDelimiter":"\u0003","suppressDeprecationErrors":true,"ajaxPageState":{"libraries":"ajax_comments\/commands,asset_injector\/js\/matomo_tags_container,asset_injector\/js\/robertroose_com_matomo_tracking_code,classy\/base,classy\/messages,classy\/node,cleantalk\/apbct-public,comment_notify\/comment_notify,core\/jquery.form,core\/normalize,extlink\/drupal.extlink,filter\/drupal.filter,lazy\/lazy,molyneux\/global-scripts,molyneux\/global-styling,paragraphs\/drupal.paragraphs.unpublished,responsive_menu\/responsive_menu.breakpoint,responsive_menu\/responsive_menu.config,responsive_menu\/responsive_menu.styling,system\/base,views\/views.module,webform\/webform.ajax,webform\/webform.element.details.save,webform\/webform.element.details.toggle,webform\/webform.element.message,webform\/webform.form,webform\/webform.theme.classy","theme":"molyneux","theme_token":null},"ajaxTrustedUrl":{"form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM":true,"https:\/\/robertroose.com\/blog\/drupal\/creating-more-accessible-drupal-website?ajax_form=1":true,"https:\/\/robertroose.com\/comment\/reply\/node\/19\/field_node_comments":true,"https:\/\/robertroose.com\/ajax_comments\/add\/node\/19\/field_node_comments":true},"responsive_menu":{"position":"left","theme":"theme-dark","pagedim":"pagedim","modifyViewport":true,"use_bootstrap":false,"breakpoint":"all and (min-width: 940px)","drag":false,"mediaQuery":"all and (min-width: 940px)"},"lazy":{"lazysizes":{"lazyClass":"lazyload","loadedClass":"lazyloaded","loadingClass":"lazyloading","preloadClass":"lazypreload","errorClass":"lazyerror","autosizesClass":"lazyautosizes","srcAttr":"data-src","srcsetAttr":"data-srcset","sizesAttr":"data-sizes","minSize":40,"customMedia":[],"init":true,"expFactor":1.5,"hFac":0.8,"loadMode":2,"loadHidden":true,"ricTimeout":0,"throttleDelay":125,"plugins":[]},"placeholderSrc":"","preferNative":false,"minified":true,"libraryPath":"\/libraries\/lazysizes"},"data":{"extlink":{"extTarget":true,"extTargetNoOverride":false,"extNofollow":false,"extNoreferrer":true,"extFollowNoOverride":false,"extClass":"0","extLabel":"(link is external)","extImgClass":false,"extSubdomains":true,"extExclude":"","extInclude":"","extCssExclude":"","extCssExplicit":"","extAlert":false,"extAlertText":"This link will take you to an external web site. We are not responsible for their content.","mailtoClass":"0","mailtoLabel":"(link sends email)","extUseFontAwesome":false,"extIconPlacement":"append","extFaLinkClasses":"fa fa-external-link","extFaMailtoClasses":"fa fa-envelope-o","whitelistedDomains":[]}},"ajax":{"edit-actions-submit":{"callback":"::submitAjaxForm","event":"click","effect":"fade","speed":500,"progress":{"type":"throbber","message":""},"disable-refocus":true,"url":"https:\/\/robertroose.com\/blog\/drupal\/creating-more-accessible-drupal-website?ajax_form=1","dialogType":"ajax","submit":{"_triggering_element_name":"op","_triggering_element_value":"Subscribe"}},"edit-ajax-comments-reply-form-node-19-field-node-comments-0-0":{"url":"https:\/\/robertroose.com\/ajax_comments\/add\/node\/19\/field_node_comments","wrapper":"node-article-field-node-comments","method":"replaceWith","effect":"fade","event":"mousedown","keypress":true,"prevent":"click","dialogType":"ajax","submit":{"_triggering_element_name":"op","_triggering_element_value":"Save"}}},"user":{"uid":0,"permissionsHash":"3a4bd2b3a4f0d7179d99ef0072b1e0bba0daefd71f2813d42bee801899097aa8"}}</script> <script src="https://robertroose.com/sites/default/files/js/js_LL6l3ucLTehAUtOypb1zey..."></script> </body> </html>

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web