DNN Blogs

Written for the Community, by the Community

Creating DNN Themes With Tailwind CSS - Part 2

Written By Steve Krantzman
2020-08-18

In Part 2 of this blog, we will take a look at a new tool called DNN_Tailwind, which allows you to create DNN themes based on the Tailwind CSS framework. If you have not yet read Part 1 Tailwhat?, read it here

DNN Themes and Tailwind

Tailwind CSS may not be for everyone. Compared to other CSS frameworks, it is still relatively in its infancy. However, if you are reading Part-2 of this blog, like me you see the potential of Tailwind CSS.

The Motivation

I really like Bootstrap, for the most part. It was a huge leap forward in making our DNN websites responsive for mobile devices. Its pre-styled components made building themes quick and easy. What I do not like about Bootstrap, is its dependency on jQuery and JavaScript (which can make upgrading DNN versions difficult), and its overuse (to me anyway) of "!important". While Bootstrap 5 will be doing away with its jQuery/JavaScript dependence, which is a step in the right direction, I am not sure if it addresses my second dislike (regardless it is still in Alpha.)

If you have used Bootstrap for any length of time, you have most likely come across this scenario. It is not uncommon for sites built upon the Bootstrap framework to have a similar look and feel, so you take it upon yourself to customize your site. In doing so you inevitably style an element or component, only to not have that style reflected on your webpage. After too many wasted minutes and much digging, you come across a Bootstrap style with a property value appended with !important. You then must come up with a creative way to work around this hurdle. I have had this happen more times than I would have preferred (maybe that is more of a reflection on my CSS knowledge than it is on Bootstrap.)

So why not use Tailwind CSS instead of Bootstrap for our DNN websites? After all, you will never run into the issue of trying to override Tailwind's styling, because as a non-opinionated framework, there really isn't any styling to override. Likewise, due to this lack of out-of-the-box styling, chances are your site will not look like any other site that uses the Tailwind framework. For a static website, using Tailwind is not a problem; but DNN websites are not static and are built on the best .NET CMS out there! As many may be aware, styling themes for any CMS, let alone DNN, presents its own challenges.

The Birth of DNN_Tailwind DT-32px

To get around these challenges, the talented staff over at nvisionative (when they were not playing ping pong Winking smile) came up with nvQuickTheme, a DNN theme building framework and developer workflow that utilizes the Bootstrap CSS framework. If only something like this existed for Tailwind CSS… light bulb Light bulb moment. So instead of recreating the wheel, I took this outstanding platform, and ported it over from Bootstrap 4 to Tailwind, to create DNN_Tailwind.

DNN_Tailwind-bg-white

Like nvQuickTheme, DNN_Tailwind comes with a starter (Out-Of-Box) theme that you can either use as is or modify to your hearts content. It is lightweight, responsive, and performant. It is identical to nvQuickTheme's Out-Of-Box theme so that you can compare the differences between how it is styled in Tailwind vs Bootstrap. Just as easily, you can use DNN_Tailwind to create your DNN theme from scratch based on Tailwind CSS. This avenue gives you total control over your DNN theme styling and build.

If you already know Tailwind CSS, and have used nvQuickTheme, transitioning to DNN_Tailwind should be easy. If you don’t know Tailwind CSS, I would highly recommend that you not only read up on it, but that you play around with it as well. I have created a basic Tailwind playground that does not require a DNN install or DNN_Tailwind to use (see resources below.)

Drawbacks to Working With Tailwind In DNN Themes

Are there drawbacks to using Tailwind as the CSS framework for DNN themes? Yes, there is one major drawback you may want to consider before switching. You need to ask yourself the question: "Will my end users need access to all the Tailwind CSS utility-classes?" As I mentioned in the previous post, there are thousands of utility classes, and that is what makes Tailwind so useful. The downside is a very large style.css file. To get around this, we purge our style.css file of any unused Tailwind utility classes before we minify and package it for production (a feature built into DNN_Tailwind.) The drawback is, if you have any power users who want to go into the source code of their html module and create some custom styles with Tailwind, they most likely will not be able to do so, as the classes they need may have been purged.

The only other drawback for me is the limited ability to animate elements using Tailwind out of the box. Tailwind's animation classes are very new and are limited to certain properties. There are some third-party plugins you can install to extend Tailwind's animation capabilities. In addition, the crew over at TailwindLabs is constantly releasing new updates to improve existing features and add new ones. As a matter of fact, I just checked, and they came out with a new release today.

Moving Forward

With TailwindLabs constantly updating the framework, I will be doing my best to keep DNN_Tailwind as up to date as possible. I welcome the DNN Community's participation in helping with further development by posting issues, improvements, new feature requests, and pull-requests.

I predict you will really enjoy Tailwind as much as I do, after all you made it this far in the blog. If you find Tailwind is for you, take DNN_Tailwind out for a test flight,

Happy Theming!


Resources:

Total: 3 Comment(s)
Great blog series - so good to see this new option for DNN theming!
Tuesday, August 25, 2020 ·

Error: Object reference not set to an instance of an object.

In: at DotNetNuke.Modules.Blog.Templating.LazyLoadingUser.GetProperty(String strPropertyName, String strFormat, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, Boolean& PropertyNotFound) at DotNetNuke.Modules.Blog.Templating.BaseCustomTokenReplace.replacedTokenValue(String strObjectName, String strPropertyName, String strFormat) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokenMatch(Match m) at System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.GenericTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.Template.ReplaceContents()

Error: Object reference not set to an instance of an object.

In: at DotNetNuke.Modules.Blog.Templating.LazyLoadingUser.GetProperty(String strPropertyName, String strFormat, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, Boolean& PropertyNotFound) at DotNetNuke.Modules.Blog.Templating.BaseCustomTokenReplace.replacedTokenValue(String strObjectName, String strPropertyName, String strFormat) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokenMatch(Match m) at System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.GenericTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.Template.ReplaceContents()

Would you like to help us?

Awesome! Simply post in the forums using the link below and we'll get you started.

Get Involved