Security, Insights, and Results for your Drupal or WordPress Website - The Open Source for Business Solutions https://www.freelock.com/ en Fred Hutchinson Cancer Research Center eagle-i Integration https://www.freelock.com/partners/portfolio/fred-hutchinson-cancer-research-center-eagle-i-integration <span>Fred Hutchinson Cancer Research Center eagle-i Integration</span> <div class="field field--name-field-portfolio-extrashots field--type-image field--label-above"> <div class="field--label">Additional Screenshots</div> <div class="field--items"> <div class="field--item"> <img loading="lazy" src="/sites/default/files/Selection_092.png" width="1015" height="619" alt="Fred Hutchinson" typeof="foaf:Image" class="img-responsive" /> </div> </div> </div> <span><a title="View user profile." href="/users/john-locke" lang="" about="/users/john-locke" typeof="schema:Person" property="schema:name" datatype="">John Locke</a></span> <span>Mon, 01/01/2018 - 00:00</span> Mon, 01 Jan 2018 08:00:00 +0000 John Locke 1025 at https://www.freelock.com https://www.freelock.com/partners/portfolio/fred-hutchinson-cancer-research-center-eagle-i-integration#comments University of Washington Center for Reinventing Public Education (CRPE) https://www.freelock.com/partners/portfolio/university-washington-center-reinventing-public-education-crpe <span>University of Washington Center for Reinventing Public Education (CRPE)</span> <div class="field field--name-field-portfolio-extrashots field--type-image field--label-above"> <div class="field--label">Additional Screenshots</div> <div class="field--items"> <div class="field--item"> <img loading="lazy" src="/sites/default/files/crpe_full_homepage.png" width="1070" height="2937" alt="crpe_full_homepage" title="crpe_full_homepage" typeof="foaf:Image" class="img-responsive" /> </div> <div class="field--item"> <img loading="lazy" src="/sites/default/files/portfolio_implementation_snapshot_too.png" width="1199" height="931" alt="portfolio_implementation_snapshot_tool" title="portfolio_implementation_snapshot_tool" typeof="foaf:Image" class="img-responsive" /> </div> </div> </div> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Mon, 12/25/2017 - 12:56</span> Mon, 25 Dec 2017 20:56:12 +0000 Don Dill 1137 at https://www.freelock.com https://www.freelock.com/partners/portfolio/university-washington-center-reinventing-public-education-crpe#comments Seattle Humane Society https://www.freelock.com/partners/portfolio/seattle-humane-society <span>Seattle Humane Society</span> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Wed, 12/20/2017 - 13:16</span> Wed, 20 Dec 2017 21:16:54 +0000 Don Dill 1677 at https://www.freelock.com https://www.freelock.com/partners/portfolio/seattle-humane-society#comments Middle East Policy Council https://www.freelock.com/partners/portfolio/middle-east-policy-council <span>Middle East Policy Council</span> <div class="field field--name-field-portfolio-extrashots field--type-image field--label-above"> <div class="field--label">Additional Screenshots</div> <div class="field--items"> <div class="field--item"> <img loading="lazy" src="/sites/default/files/mepc_website_homepage.png" width="1599" height="2590" alt="MEPC homepage" typeof="foaf:Image" class="img-responsive" /> </div> </div> </div> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Wed, 11/01/2017 - 12:48</span> Wed, 01 Nov 2017 19:48:15 +0000 Don Dill 1177 at https://www.freelock.com https://www.freelock.com/partners/portfolio/middle-east-policy-council#comments American College for Healthcare Sciences (ACHS) https://www.freelock.com/partners/portfolio/american-college-healthcare-sciences-achs <span>American College for Healthcare Sciences (ACHS)</span> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Sun, 10/15/2017 - 15:26</span> Sun, 15 Oct 2017 22:26:21 +0000 Don Dill 1140 at https://www.freelock.com https://www.freelock.com/partners/portfolio/american-college-healthcare-sciences-achs#comments Peninsula College and Athletics Sites https://www.freelock.com/partners/portfolio/peninsula-college-and-athletics-sites <span>Peninsula College and Athletics Sites</span> <div class="field field--name-field-portfolio-extrashots field--type-image field--label-above"> <div class="field--label">Additional Screenshots</div> <div class="field--items"> <div class="field--item"> <img loading="lazy" src="/sites/default/files/pencol_homepage.png" width="1594" height="931" alt="Peninsula College" typeof="foaf:Image" class="img-responsive" /> </div> <div class="field--item"> <img loading="lazy" src="/sites/default/files/pencol_full_homepage.png" width="1049" height="1291" alt="Peninsula College" typeof="foaf:Image" class="img-responsive" /> </div> </div> </div> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Mon, 10/02/2017 - 13:09</span> Mon, 02 Oct 2017 20:09:37 +0000 Don Dill 1138 at https://www.freelock.com https://www.freelock.com/partners/portfolio/peninsula-college-and-athletics-sites#comments Seattle Children's Alliance https://www.freelock.com/partners/portfolio/seattle-childrens-alliance <span>Seattle Children&#039;s Alliance</span> <div class="field field--name-field-portfolio-extrashots field--type-image field--label-above"> <div class="field--label">Additional Screenshots</div> <div class="field--items"> <div class="field--item"> <img loading="lazy" src="/sites/default/files/childrensalliance.org_013_0.jpg" width="1890" height="2864" alt="Children&#039;s alliance homepage" typeof="foaf:Image" class="img-responsive" /> </div> </div> </div> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Sun, 01/15/2017 - 18:06</span> Mon, 16 Jan 2017 02:06:47 +0000 Don Dill 1154 at https://www.freelock.com https://www.freelock.com/partners/portfolio/seattle-childrens-alliance#comments Queen City Yacht Club https://www.freelock.com/partners/portfolio/queen-city-yacht-club <span>Queen City Yacht Club</span> <span><a title="View user profile." href="/users/don-dill" lang="" about="/users/don-dill" typeof="schema:Person" property="schema:name" datatype="">Don Dill</a></span> <span>Sat, 07/16/2016 - 00:00</span> Sat, 16 Jul 2016 07:00:00 +0000 Don Dill 1121 at https://www.freelock.com https://www.freelock.com/partners/portfolio/queen-city-yacht-club#comments A new approach to Drupal theming, just in time for Drupal 10 https://www.freelock.com/blog/john-locke/2022-11/new-approach-drupal-theming-just-time-drupal-10 <span>A new approach to Drupal theming, just in time for Drupal 10</span> <span><a title="View user profile." href="/users/john-locke" lang="" about="/users/john-locke" typeof="schema:Person" property="schema:name" datatype="">John Locke</a></span> <span>Sun, 11/06/2022 - 18:07</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>Over the past few months, I've fielded a lot of minor styling requests, and as I work through each problem, I've almost always ended up with substantially less code than was there before. When I look through our portfolio of sites, most of them use tons of CSS to style all the various parts of a site -- and in many cases, the same styling reappears a bunch of different places. This leads to inconsistent styling, slow page loads, and more effort needed to make minor changes.</p><p>This is a form of "<a href="https://en.wikipedia.org/wiki/Technical_debt">Technical Debt</a>". It comes from starting with a poorly documented, not-fully-understood starting point for a theme, and grows through each change built upon this poor foundation.</p><p>Now this is not a dire problem. We've worked with hundreds of sites built in similar ways, each one with slightly different quirks and gotchas, and they all work. Mostly. If you don't look too closely at the details.</p><p>Making changes to these sites that work and look good across all screen sizes is a game of Whack-a-mole. Our first line of defense has been a solid "visual regression testing" system, which runs on every release for all the sites we manage. We pick up pixel-level changes to our themes -- for the pages we have in our list to test. But all too often, our themers have chosen to limit the scope of their changes, targeting changes to only specific locations that the client requests, instead of making the bigger decision to define something new that intentionally changes the entire site.</p><h2>What we're doing now</h2><p>We just kicked off a theme sprint for a new upgrade project, and we're doing it much differently this time. The vast majority of our theme work up until now has been done in CSS. We occasionally update a Twig template to add some information we want to include, or change the format of a date, or render an image as a background image -- but the vast majority of customizations have happened in SASS files we compile to CSS.</p><p>This time, we're flipping that. We've added <a href="https://tailwindcss.com/">TailwindCSS</a> to the theme, and plan to make most of our customizations in the twig (HTML) templates and preprocess functions, instead of in custom CSS.</p><h3>What is Tailwind?</h3><p>Tailwind is a CSS framework that provides a ton of HTML classes that essentially are thin wrappers for individual CSS. It's a bit like using "style" tags inside your HTML elements, but labeling them as classes with shorter names. Now if you've been working with websites for a while you might've just retched a little -- sorry about that! But I've been using Tailwind on various presentations and front-end work for the past few months, and now I find myself cringing when I see deeply nested CSS selectors, and CSS definitions overriding other CSS overriding 3 more CSS definitions -- no wonder we have sites approaching a megabyte of CSS, or more!</p><p>With our previous approach, theming meant inspecting code, identifying CSS changes to make to change it to the way we want, and adding those by indirectly identifying a way to target a particular element, and then change the CSS stylesheets to add that change.</p><p>With Tailwind, instead of changing the CSS, you change the HTML -- you go straight to the template where you want to make the change, and add Tailwind classes to make the change.</p><p>But you're not done, in either scenario. What about mobile? Tablet? Super wide screens? With the old system, we would then either have to find the appropriate part of the stylesheet that has the responsive rules -- or, more often, create new ones. What was that breakpoint to target again? Did we have a Sass mixin to handle the breakpoint, or do we just hard-code in a pixel width? Programmers are lazy -- all too often we just put in what seems to work and look good to us, without going back to any kind of source or non-existent plan, and using the style this particular site used. And boom, now we have created more technical debt.</p><p>With Tailwind, all the positioning, margin, padding classes take prefixes for responsiveness. But, more than that, all tailwind classes can be prefixed with a breakpoint, to have that class only apply at screen sizes bigger than that breakpoint.</p><p>The end result is you have one place to go in the HTML DOM to change any style you want for that element: the list of classes on that element itself.</p><p>If you do this with CSS selectors, you may have a dozen different rules, a dozen different places in your tree of CSS or Sass files, that have an impact on the style of the very same element.</p><h3>Why we think this will be better</h3><p>Our goals for this change are:</p><ul><li>Make the theming process go faster</li><li>Improve the quality and consistency, particularly on mobile</li><li>Make the site load substantially quicker, with much smaller CSS files</li><li>Make future changes far easier to incorporate, with the same level of quality</li></ul><h3>Gotchas, problem areas</h3><p>We are not doing away with custom CSS entirely. One of the great things about Drupal is the separation between information and presentation. So we're not hopping entirely on the Tailwind bandwagon -- if we were to start using Tailwind classes inside content, that would lead to even more mess, when different editors choose different classes to add to specific chunks of text -- which could lead to wildly inconsistent look and feel of pages on your site.</p><blockquote><p>Tailwind is not an editor tool! Tailwind is for developers only.</p></blockquote><p>This is the balance to strike: Rapid, reliable development, versus editorial ease and ability to use components.</p><p>Drupal 10's CKEditor5 now supports a list of styles editors can quickly select to apply particular styles to text, as they edit. (This isn't new, but it is something we highly recommend using). We've experimented with adding a set of Tailwind classes to this dropdown, with a label -- but then realized this is going down the same path as WordPress with Gutenberg -- the presentation is getting stuffed into the content, which leads to much bigger challenges if you want to reskin the site, redefine the styling for a particular element.</p><p>So a key consideration here is, if you decide down the road to redefine what a "Highlight box" looks like on your site, how much manual work will you have to do to change everywhere you've used one?</p><p>If you define a "Highlight Box" as a single CSS class, you can just update that class. If you define it as a set of Tailwind classes, you'll need to go through all your content to find that set of classes and update them to the new look.</p><p>This leads us to our new...</p><h2>Implementation Principles</h2><p>We've identified several parts of this theme puzzle:</p><ul><li>Defaults - header styles, font styles, base size, base colors</li><li>Layouts, margins, paddings, responsiveness</li><li>Components - nested structures that can be reused</li><li>Styles</li></ul><p>Each of these has a different implementation strategy.</p><h3>Defaults</h3><p>Defaults can be specified in the Tailwind config file, along with classes on the body tag. Also, remember CSS variables -- CSS variables are a really powerful way to provide variations that use the same template. Define all the overall defaults first, along with base styles.</p><ul><li>Add default colors, font families, and typography size to the <a href="https://tailwindcss.com/docs/configuration">tailwind.config.js</a>.</li><li>Define base header styles in a base layer <a href="https://tailwindcss.com/docs/adding-base-styles">as described here</a>.</li></ul><h3>Layouts, margins, paddings, responsiveness</h3><p>If it has to do with boxes, it should be specified in a template. This is where we apply Tailwind the most -- on the Twig templates in the main theme. For the most part, use Tailwind here as much as possible, following <a href="https://tailwindcss.com/docs/utility-first">the reasoning they outline for the framework itself</a>.</p><h3>Components</h3><p>Here's where the grey areas come in. What is a component? Components are building blocks, often composed of other building blocks. In Drupal terms, it might be a block, a form, a specific set of nested HTML, a form element, a menu, or any number of different elements. This is the big new change we're making -- defining these individually.</p><p>Some are predefined, coming from Drupal core or various contributed modules. Some are self-contained widgets. There's a huge variety of different possible components.</p><p>This is where documentation comes in, and we've found a great place to document these: The <a href="https://www.drupal.org/project/simple_styleguide">Simple Style Guide</a> module. This creates a section in the admin menu where you can drop in the appropriate HTML for a component as an example, and document where the CSS is implemented.</p><p>So, as a general rule, when theming a component, avoid putting Tailwind classes into HTML that will end up in the database. Here's where we need to come up with a distinct name for the component, and define a CSS class to style it appropriately.</p><p>Where does this CSS go? Depends on where the component is being defined. If it's being defined in the theme, the best practice would be to put it in the main.css file, and use @apply to define the CSS using other Tailwind classes. Many components are defined by Drupal core or various contributed modules, though -- if it's code we "own", go ahead and update the CSS where it is defined. If we don't "own" the code, then go ahead and override the styling in the theme CSS, again using @apply.</p><p>How does an editor use a component? Primarily by placing a block, specifying a class name for a block, or something in layout builder. In some cases these become templates dropped into Views in a global text field, or inserted as HTML -- we're still working out best practices here.</p><p>The actual list of component classes should be kept as small as possible. And, instead of creating different class names for slight variations of a component, use another set of classes for the variation. For example, a card with several different color variations is still a card -- add a class for the variation to use, and have that variation set CSS variables that the component CSS uses.</p><h3>Styles</h3><p>Finally, we reach individual text styles. These are options added to the Wysiwyg dropdown to allow editors to highlight text, turn links into buttons, or other "simple" components (components that do not have nested HTML elements). These should get defined in a separate "ckeditor5.css" stylesheet, and added to the "Styles" dropdown in the text format configuration.</p><h2>Theme documentation</h2><p>This is the critical part to keep technical debt low: Document your theme decisions as you go. This post is our guide to the various moving parts -- defaults, templates, components, and styles. We're not fans of extra documentation or creating extra work -- the goal here is to put notes where you will find them when you come back years later.</p><p>First and foremost: There should be a README.md file at the top level of the theme, with the instructions for doing a build and where to find the specific documentation. This is the index that should point a new developer touching this site later to the right place.</p><p>Documentation for the defaults is the tailwind.config.js file, and the "Base" layer of the main.css file -- use comments in these files where the defaults themselves are not obvious.</p><p>Documentation for the templates are in the Twig templates themselves. Turning on Twig debugging makes it easy to find a template being used -- in that template, drop in the classes and any notes to explain things that are non-obvious.</p><p>Documentation for Components and Styles should go in the Simple Styleguide in the site itself -- this gets exported to configuration, so it can stay with the site. The description for each component should identify what module or theme defines the component, provide instructions for editors or site builders to use the component, and point themers to any locations they need to go to style the component or style.</p><h2>Getting started</h2><p>We're making use of the new Starter Theme functionality recommended for Drupal 10:</p><pre><code class="language-plaintext">php core/scripts/drupal generate-theme my_theme</code></pre><p>... and using Laravel Mix with PostCss, with a setup based on <a href="https://mglaman.dev/blog/migrating-tailwindcss-iteratively-your-drupal-theme">a blog post by Matt Glaman</a>:</p><pre><code class="language-plaintext">cd web/themes/my_theme npm install -D tailwindcss@latest postcss@latest npm install -D laravel-mix npx tailwindcss init touch webpack.mix.js</code></pre><p>Next, add the build scripts to the package.json so you can build for production with <code>npm run build</code>, or watch your changes with <code>npm run watch</code>:</p><pre><code class="language-plaintext"> "scripts": { "test": "echo \"Error: no test specified\" &amp;&amp; exit 1", "build": "mix --production", "dev": "mix", "watch": "mix watch" },</code></pre><h3>Configure Laravel Mix</h3><p>Here we're still basing on mglaman's configuration, but have made a couple specific changes:</p><pre><code class="language-javascript language-plaintext">// webpack.mix.js let mix = require('laravel-mix'); mix .disableSuccessNotifications() .postCss('./src/ckeditor5.css', 'build', [ require('tailwindcss') ]) .postCss('./src/main.css', 'build', [ require('tailwindcss'), // require('autoprefixer'), - enable this if too many conflicts with Drupal CSS -- prefixes everything with tw- ]) .browserSync({ proxy: 'mysite.freelock.net', files: [ 'build/main.css', 'templates/**/*', 'my_theme.theme', ] })</code></pre><p>You may or may not want to use the autoprefixer extension, which makes it so you need to prefix all the Tailwind styles with "tw-".</p><h3>Configure Tailwind</h3><p>Mglaman's tailwind.config.js is for an older version of Tailwind -- with a current Tailwind 3.x version, there are some differences:</p><pre><code class="language-javascript">/** @type {import('tailwindcss').Config} */ module.exports = { corePlugins: { preflight: false, }, content: [ './templates/**/*.html.twig', './js/**/*.js', './my_theme.theme' ], theme: { /* Defaults for typography, colors, etc go here */ extend: {}, }, plugins: [], safelist: [ /* Add any specific tailwind classes to always include. */ ] }</code></pre><p>The secret sauce of Tailwind is how it parses the files listed in the "content" key for tokens, and evaluates those at build time to include only the classes you actually use into the built CSS. Its tokenization process is relatively dumb -- it just parses all of the matching files for space- or quote-delimited words, and any that match a Tailwind pattern end up in the build/*.css files. We go ahead and include the .theme file to pick up any classes added in a preprocess function, along with any Javascript files or Twig templates.</p><h3>Configure the Drupal theme files</h3><p>With the configuration above, running a build will put CSS files into a ./build directory in the theme, based on the CSS added in a ./src directory.</p><p>To load these into the browser, they need to get added to the my_theme.libraries.yml file, and the CKEditor-specific file needs to be added to the my_theme.info.yml file:</p><pre><code class="language-plaintext"># my_theme.info.yml ... ckeditor5-stylesheets: - build/ckeditor5.css libraries: - my_theme/base - my_theme/messages - core/normalize</code></pre><pre><code class="language-plaintext"># my_theme.libraries.yml base: version: 1.0 css: component: ... theme: build/main.css: {} build/ckeditor5.css: {}</code></pre><p>Note that we are still using the starterkit CSS files in ./css/components, so we keep those in the base library.</p><h3>Main CSS file</h3><p>Finally, we get to where you actually start adding CSS! For the time being, this is going in a ./src directory</p><pre><code class="language-css">/* ./src/main.css */ @tailwind base; /* Put default CSS here. Don't wrap with @layer base {} here, because some elements may not be in templates alone. */ @tailwind components; /* Put component CSS here - again, skip @layer component {}. */ @tailwind utilities;</code></pre><p>... when this file gets longer than a few hundred lines, split out components into component files and @include them.</p><h3>Build for production</h3><p>... And now, to make it live, run <code>npm run build</code>, clear the Drupal cache, and load your page!</p><p>&nbsp;</p></div> <div class="field field--name-taxonomy-vocabulary-5 field--type-entity-reference field--label-hidden field--items"> <div class="field--item"><a href="/tags/drupal-planet" hreflang="en">Drupal Planet</a></div> <div class="field--item"><a href="/tags/performance" hreflang="en">Performance</a></div> <div class="field--item"><a href="/tags/technical" hreflang="en">Technical</a></div> <div class="field--item"><a href="/taxonomy/term/598" hreflang="en">Technical Debt</a></div> </div> <section> <article role="article" data-comment-user-id="0" id="comment-28696" class="comment js-comment by-anonymous clearfix"> <span class="hidden" data-comment-timestamp="1668106876"></span> <footer class="comment__meta"> <div class="col-sm-2 col-xs-4 comment-user-picture"> </div> </footer> <div class="comment-body col-sm-10 col-xs-8"> <div class="comment-arrow"></div> <div class="comment__content"> <div class="pull-left comment__author"><a rel="nofollow" href="https://wolstenhol.me" lang="" typeof="schema:Person" property="schema:name" datatype="">Phil Wolstenholme</a></div> <div class="pull-right"><drupal-render-placeholder callback="comment.lazy_builders:renderLinks" arguments="0=28696&amp;1=default&amp;2=en&amp;3=" token="D0RouybAyrlhdmG7v3bomOV1MDJlrs_lnd0hcBnrAgs"></drupal-render-placeholder></div> <div class="field field--name-comment-body field--type-text-long field--label-hidden field--item"><p>Sounds great! I gave a talk on a similar approach at DrupalCon a year or two back: <a href="https://www.youtube.com/watch?v=MYY1teFZ_Fk" rel="nofollow">https://www.youtube.com/watch?v=MYY1teFZ_Fk</a></p> </div> <div class="comment__time pull-right">10 Nov, 2022</div> </div> </div> </article> <div class="indented"> <article role="article" data-comment-user-id="5" id="comment-28700" class="comment js-comment by-node-author clearfix"> <span class="hidden" data-comment-timestamp="1668123105"></span> <footer class="comment__meta"> <div class="col-sm-2 col-xs-4 comment-user-picture"> </div> <p class="visually-hidden">In reply to <a href="/comment/28696#comment-28696" class="permalink" rel="bookmark" hreflang="en">Sounds great! I gave a talkā€¦</a> by <a rel="nofollow" href="https://wolstenhol.me" lang="" typeof="schema:Person" property="schema:name" datatype="">Phil Wolstenholme</a></p> </footer> <div class="comment-body col-sm-10 col-xs-8"> <div class="comment-arrow"></div> <div class="comment__content"> <div class="pull-left comment__author"><a title="View user profile." href="/users/john-locke" lang="" about="/users/john-locke" typeof="schema:Person" property="schema:name" datatype="">John Locke</a></div> <div class="pull-right"><drupal-render-placeholder callback="comment.lazy_builders:renderLinks" arguments="0=28700&amp;1=default&amp;2=en&amp;3=" token="p-8Pqv4uzBlNDlRp1f9XN4hsu8wkl8jrReZkW5Rxrv8"></drupal-render-placeholder></div> <div class="field field--name-comment-body field--type-text-long field--label-hidden field--item"><p>This looks like a great talk! Thanks for adding, I'll check it out...</p> </div> <div class="comment__time pull-right">10 Nov, 2022</div> </div> </div> </article> </div> <article role="article" data-comment-user-id="0" id="comment-28697" class="comment js-comment by-anonymous clearfix"> <span class="hidden" data-comment-timestamp="1668123047"></span> <footer class="comment__meta"> <div class="col-sm-2 col-xs-4 comment-user-picture"> </div> </footer> <div class="comment-body col-sm-10 col-xs-8"> <div class="comment-arrow"></div> <div class="comment__content"> <div class="pull-left comment__author"><span lang="" typeof="schema:Person" property="schema:name" datatype="">Perry Brown</span></div> <div class="pull-right"><drupal-render-placeholder callback="comment.lazy_builders:renderLinks" arguments="0=28697&amp;1=default&amp;2=en&amp;3=" token="X-EnllGfoeTQba5-jEwvnBcmq8Xwu6224aEmKySOlX8"></drupal-render-placeholder></div> <div class="field field--name-comment-body field--type-text-long field--label-hidden field--item"><p>You can add something like '../../../config/**/*.yml' to your tailwind.config.js to pick up any class used in Views, too. You do need to change the prefix separator to something besides ':' as this is currently invalid for class names in Views and they won't save properly (I use '--'), and then just run drush cex so the classes get exported to configuration where they'll be picked up and included. Still developer-centric, but now you don't have to make as many variations for Views templates. YMMV, of course.</p> </div> <div class="comment__time pull-right">10 Nov, 2022</div> </div> </div> </article> <div class="indented"> <article role="article" data-comment-user-id="5" id="comment-28701" class="comment js-comment by-node-author clearfix"> <span class="hidden" data-comment-timestamp="1668123434"></span> <footer class="comment__meta"> <div class="col-sm-2 col-xs-4 comment-user-picture"> </div> <p class="visually-hidden">In reply to <a href="/comment/28697#comment-28697" class="permalink" rel="bookmark" hreflang="en">Using TW classes in Views</a> by <span lang="" typeof="schema:Person" property="schema:name" datatype="">Perry Brown</span></p> </footer> <div class="comment-body col-sm-10 col-xs-8"> <div class="comment-arrow"></div> <div class="comment__content"> <div class="pull-left comment__author"><a title="View user profile." href="/users/john-locke" lang="" about="/users/john-locke" typeof="schema:Person" property="schema:name" datatype="">John Locke</a></div> <div class="pull-right"><drupal-render-placeholder callback="comment.lazy_builders:renderLinks" arguments="0=28701&amp;1=default&amp;2=en&amp;3=" token="jKjsPjVQ_ioywILNJbErJfvL78J9B5n-VQG_ial3z_Y"></drupal-render-placeholder></div> <div class="field field--name-comment-body field--type-text-long field--label-hidden field--item"><p>Nice tip!</p> <p>I've run across this restriction in block_class as well -- it sounds like using a ':' character in a class name violates the RFC for class names. I worked around this on one site by patching core to allow colons, but changing the separator sounds like a better fix.</p> <p>But some of this led to my decision to keep Tailwind classes out of the Drupal admin interface -- don't use in content or config. If you do start adding these to views, block classes, etc. then you still may have to rebuild your CSS anyway, so this is where I'm going ahead and adding a specific class to the main.css file, and then using Tailwind classes in its definition using @apply.</p> </div> <div class="comment__time pull-right">10 Nov, 2022</div> </div> </div> </article> </div> <h2>Add new comment</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=2154&amp;2=comment_node_blog&amp;3=comment_node_blog" token="b7JRR9aldh0dtVAxyjl5CQx0Xh11oQAEMBoEubegJIc"></drupal-render-placeholder> </section> Mon, 07 Nov 2022 02:07:47 +0000 John Locke 2154 at https://www.freelock.com 3 different ways to progressively enhance your website https://www.freelock.com/newsletter/3-different-ways-progressively-enhance-your-website <span>3 different ways to progressively enhance your website</span> <div class="field field--name-field-issue field--type-text field--label-hidden field--item">August 2022</div> <span><a title="View user profile." href="/users/john-locke" lang="" about="/users/john-locke" typeof="schema:Person" property="schema:name" datatype="">John Locke</a></span> <span>Wed, 08/31/2022 - 13:38</span> <div class="field field--name-field-news field--type-text-long field--label-above"> <div class="field--label">Freelock News</div> <div class="field--item"><h2>Limited Time Special!</h2> <p>While the "<a data-entity-substitution="canonical" data-entity-type="commerce_product" data-entity-uuid="18c18304-421b-4fa0-a7e3-92c976d0953e" href="/product/custom-navigation-puzzle" title="Custom Navigation Puzzle">custom navigation puzzle</a>" is fresh in our minds, we're offering a deep discount if you would like something along these lines added to your existing Drupal website, and you purchase before the end of September! Drupal 9 core has everything needed to drive this, besides your content. If you have a taxonomy with 2 - 4 levels of information, we can add this progressive enhancement to your site with some customization to make it fit your needs.</p> <h2>Website Effectiveness Engineering</h2> <p>At Freelock, we think people spend far too much time building new websites and having to re-do what they already have. If you build your website on a platform that's powerful enough to grow and change with your needs, your technology budget is far better spent addressing the specific needs you have right now, rather than re-doing something you've done several times already.</p> <p>We've broken down what makes websites effective into 6 key topics, and starting now, we're picking something related to one of those topics to highlight and do a deep dive on each month. Each month we plan to write 3 blog posts on the topic, create a special offering related to that topic, and summarize our findings in an email like this one.</p> <p>Next month's topic is Measuring Results. We will be exploring analytics, reporting systems, and what's worth measuring. If you have any questions related to analytics, <a data-entity-substitution="canonical" data-entity-type="node" data-entity-uuid="536075e7-4a5d-41fb-84fc-0a77109f6314" href="/get-started" title="Get Started">we'd love to hear them</a>! If you know anyone who might be interested, feel free to forward this message or point them to our signup form. And as always, if we can help you make your website more effective, <a href="https://cloud.freelock.com/apps/calendar/appointment/66aCXZeqdzjf">schedule a meeting</a> and we'll be happy to discuss!</p> </div> </div> Wed, 31 Aug 2022 20:38:25 +0000 John Locke 2150 at https://www.freelock.com https://www.freelock.com/newsletter/3-different-ways-progressively-enhance-your-website#comments