ASP.NET Core 2.2 - Free Themes For Bootstrap 4
Update 03/27/2019
I found and corrected a misspelling for the sandstone theme parameter in the dropdown menu.
Update 02/28/2019
I updated KenHaggerty.Com to Bootstrap 4.3.1, therefore I updated the article with the correct cdn paths and integrity hashes for version 4.3.1. The files at the asp-fallback-href paths also have to be updated or the integrity checks will fail if the cdn is not available.
The ASP.NET Core 2.2 template creates a basic functional web application. The new template includes Bootstrap 4 rather than Bootstrap 3 as in earlier versions. There are plenty of articles about the main differences between 3 and 4 like Bootstrap 3 or Bootstrap 4? Which one to choose? so I won't cover it here. I'll just say there are a few changes we all should take advantage of.
You can definitely see a difference even with the default theme installed by the template. It is lighter. brighter and has a simplistic appeal over the previous default theme. If you want to use Bootstrap 3 with the new Identity UI, it appears you will have to replace the Bootstrap files and change the setting in Startup.cs > ConfigureServices > services.AddDefaultIdentity<IdentityUser>() from (UIFramework.Bootstrap4) to (UIFramework.Bootstrap3). I haven't tried this because I am learning Bootstrap 4.
I have used Free themes for Bootstrap from Bootswatch with v3 and decided to add a theme picker to this site using v4. You may select a theme from the navigation bar which sets a 1 day theme cookie. This article is about how I did this.
Let us start in Pages > Shared > _Layout.cshtml from the top down:
Add the cookie get just above <!DOCTYPE html> replacing YOURGOMAIN.COM with your own identifier:
@{ Context.Request.Cookies.TryGetValue("<YOURDOMAIN.COM>.Theme", out string theme); }
Remove the Bootstrap css references. I will use the new themes in development because some of themes have varying effects on layout.
<environment include="Development"> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" /> </environment> <environment exclude="Development"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" crossorigin="anonymous" integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/> </environment>
Add a css reference dependent on the theme, setting your favorite if none is set:
@{ if (string.IsNullOrEmpty(theme)) { theme = "cosmo"; } switch (theme) { case "default": <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" asp-fallback-href = "~/lib/bootstrap/dist/css/default/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha256-YLGeXaapI0/5IgZopewRJcFXomhRMlYYjugPLSyNjTY=" /> crossorigin="anonymous" case "cerulean": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cerulean/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/cerulean/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-C++cugH8+Uf86JbNOnQoBweHHAe/wVKN/mb0lTybu/NZ9sEYbd+BbbYtNpWYAsNP" crossorigin="anonymous"> break; case "cosmo": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cosmo/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/cosmo/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-uhut8PejFZO8994oEgm/ZfAv0mW1/b83nczZzSwElbeILxwkN491YQXsCFTE6+nx" crossorigin="anonymous"> break; case "cyborg": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cyborg/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/cyborg/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-mtS696VnV9qeIoC8w/PrPoRzJ5gwydRVn0oQ9b+RJOPxE1Z1jXuuJcyeNxvNZhdx" crossorigin="anonymous"> break; case "darkly": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/darkly/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/darkly/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-w+8Gqjk9Cuo6XH9HKHG5t5I1VR4YBNdPt/29vwgfZR485eoEJZ8rJRbm3TR32P6k" crossorigin="anonymous"> break; case "flatly": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/flatly/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/flatly/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-T5jhQKMh96HMkXwqVMSjF3CmLcL1nT9//tCqu9By5XSdj7CwR0r+F3LTzUdfkkQf" crossorigin="anonymous"> break; case "journal": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/journal/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/journal/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-ciphE0NCAlD2/N6NUApXAN2dAs/vcSAOTzyE202jJx3oS8n4tAQezRgnlHqcJ59C" crossorigin="anonymous"> break; case "litera": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/litera/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/litera/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-D/7uAka7uwterkSxa2LwZR7RJqH2X6jfmhkJ0vFPGUtPyBMF2WMq9S+f9Ik5jJu1" crossorigin="anonymous"> break; case "lumen": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/lumen/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/lumen/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-iqcNtN3rj6Y1HX/R0a3zu3ngmbdwEa9qQGHdkXwSRoiE+Gj71p0UNDSm99LcXiXV" crossorigin="anonymous"> break; case "lux": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/lux/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/lux/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-hVpXlpdRmJ+uXGwD5W6HZMnR9ENcKVRn855pPbuI/mwPIEKAuKgTKgGksVGmlAvt" crossorigin="anonymous"> break; case "materia": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/materia/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/materia/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-SYbiks6VdZNAKT8DNoXQZwXAiuUo5/quw6nMKtFlGO/4WwxW86BSTMtgdzzB9JJl" crossorigin="anonymous"> break; case "minty": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/minty/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/minty/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-9NlqO4dP5KfioUGS568UFwM3lbWf3Uj3Qb7FBHuIuhLoDp3ZgAqPE1/MYLEBPZYM" crossorigin="anonymous"> break; case "pulse": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/pulse/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/pulse/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-/uQFqO50IaQu2rNJYKPpV7zwsWJtd6V4DGX4wMw1ATz4KPuZEV96qQ2heVAw2kr2" crossorigin="anonymous"> break; case "sandstone": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/sandstone/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/sandstone/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-G3Fme2BM4boCE9tHx9zHvcxaQoAkksPQa/8oyn1Dzqv7gdcXChereUsXGx6LtbqA" crossorigin="anonymous"> break; case "simplex": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/simplex/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/simplex/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-1OYccka9EByiS23wvPFiYHBPRAgU91xYVFb8g8sen6vRiBI5Uko6+B87q8zPGUnA" crossorigin="anonymous"> break; case "sketchy": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/sketchy/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/sketchy/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-N8DsABZCqc1XWbg/bAlIDk7AS/yNzT5fcKzg/TwfmTuUqZhGquVmpb5VvfmLcMzp" crossorigin="anonymous"> break; case "slate": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/slate/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/slate/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-FBPbZPVh+7ks5JJ70RJmIaqyGnvMbeJ5JQfEbW0Ac6ErfvEg9yG56JQJuMNptWsH" crossorigin="anonymous"> break; case "solar": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/solar/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/solar/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-8nq3OiMMgrVFAHyRMMO+DTfMEciSY+c3Awhj/5ljQ1xck1Uv2BUtMjsjLD8GT5Er" crossorigin="anonymous"> break; case "spacelab": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/spacelab/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/spacelab/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-sZG5VVk41YqhJjYXgJFoRVd3d2AdDgy4oyIytQJMGx/Mizz1N+5bgKQBSCGfKQnP" crossorigin="anonymous"> break; case "superhero": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/superhero/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/superhero/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-LS4/wo5Z/8SLpOLHs0IbuPAGOWTx30XSoZJ8o7WKH0UJhRpjXXTpODOjfVnNjeHu" crossorigin="anonymous"> break; case "united": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/united/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/united/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-WTtvlZJeRyCiKUtbQ88X1x9uHmKi0eHCbQ8irbzqSLkE0DpAZuixT5yFvgX0CjIu" crossorigin="anonymous"> break; case "yeti": <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/yeti/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/yetibootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-w6tc0TXjTUnYHwVwGgnYyV12wbRoJQo9iMlC2KdkdmVvntGgzT9jvqNEF/uKaF4m" crossorigin="anonymous"> break; default: <link href = "https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cosmo/bootstrap.min.css" rel="stylesheet" asp-fallback-href="~/lib/bootstrap/dist/css/cosmo/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha384-uhut8PejFZO8994oEgm/ZfAv0mW1/b83nczZzSwElbeILxwkN491YQXsCFTE6+nx" crossorigin="anonymous"> break; } }
Section references: BootstrapCDN
Add a dropdown nav item to the navigation bar for your list of themes:
<li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" id="navbarDropdownTheme" data-target="#" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Theme</a> <ul class="dropdown-menu" aria-labelledby="navbarDropdownTheme"> <li><a class="dropdown-item theme @(theme == "default" ? "active" : "")" data-theme="default" href="#">Default</a></li> <li><a class="dropdown-item theme @(theme == "cerulean" ? "active" : "")" data-theme="cerulean" href="#">Cerulean</a></li> <li><a class="dropdown-item theme @(theme == "cosmo" ? "active" : "")" data-theme="cosmo" href="#">Cosmo</a></li> <li><a class="dropdown-item theme @(theme == "cyborg" ? "active" : "")" data-theme="cyborg" href="#">Cyborg</a></li> <li><a class="dropdown-item theme @(theme == "darkly" ? "active" : "")" data-theme="darkly" href="#">Darkly</a></li> <li><a class="dropdown-item theme @(theme == "flatly" ? "active" : "")" data-theme="flatly" href="#">Flatly</a></li> <li><a class="dropdown-item theme @(theme == "journal" ? "active" : "")" data-theme="journal" href="#">Journal</a></li> <li><a class="dropdown-item theme @(theme == "litera" ? "active" : "")" data-theme="litera" href="#">Litera</a></li> <li><a class="dropdown-item theme @(theme == "lumen" ? "active" : "")" data-theme="lumen" href="#">Lumen</a></li> <li><a class="dropdown-item theme @(theme == "lux" ? "active" : "")" data-theme="lux" href="#">Lux</a></li> <li><a class="dropdown-item theme @(theme == "materia" ? "active" : "")" data-theme="materia" href="#">Materia</a></li> <li><a class="dropdown-item theme @(theme == "minty" ? "active" : "")" data-theme="minty" href="#">Minty</a></li> <li><a class="dropdown-item theme @(theme == "pulse" ? "active" : "")" data-theme="pulse" href="#">Pulse</a></li> <li><a class="dropdown-item theme @(theme == "sandstone" ? "active" : "")" data-theme="sandstone" href="#">Sandstone</a></li> <li><a class="dropdown-item theme @(theme == "simplex" ? "active" : "")" data-theme="simplex" href="#">Simplex</a></li> <li><a class="dropdown-item theme @(theme == "sketchy" ? "active" : "")" data-theme="sketchy" href="#">Sketchy</a></li> <li><a class="dropdown-item theme @(theme == "slate" ? "active" : "")" data-theme="slate" href="#">Slate</a></li> <li><a class="dropdown-item theme @(theme == "solar" ? "active" : "")" data-theme="solar" href="#">Solar</a></li> <li><a class="dropdown-item theme @(theme == "spacelab" ? "active" : "")" data-theme="spacelab" href="#">Spacelab</a></li> <li><a class="dropdown-item theme @(theme == "superhero" ? "active" : "")" data-theme="superhero" href="#">Superhero</a></li> <li><a class="dropdown-item theme @(theme == "united" ? "active" : "")" data-theme="united" href="#">United</a></li> <li><a class="dropdown-item theme @(theme == "yeti" ? "active" : "")" data-theme="yeti" href="#">Yeti</a></li> </ul> </li>
I got the most of the Navbar Dropdown from Craig Watson's Code Pen. The data-theme I will cover next.
Section references: Craig Watson's Code Pen
Now the JavaScript part:
I use a cookie helper called js-cookie but you can set the theme cookie as you prefer.
Download and add the js-cookie script to the bottom of _Layout.cshtml but before site.js:
<script src="~/js/js.cookie.js"></script>
Section references: js-cookie
In site.js, add the jQuery on click event for each of the dropdown-items using the class theme and set the cookie value based on the data-theme attribute. Be sure to set the cookie identifier as before. I set the cookie to expire in 1 day.
$('.theme').on('click', function () { Cookies.set('<YOURDOMAIN.COM>.Theme', $(this).data('theme'), { expires: 1 }); location.reload(); });
Update the bootstrap.bundle.min.js script towards the bottom of _Layout.cshtml after the jQuery script link:
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js" asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js" asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal" asp-suppress-fallback-integrity="true" integrity="sha256-fzFFyH01cBVPYzl16KT40wqjhgPtq6FFUB6ckN2+GGw=" crossorigin="anonymous"> </script>
Here is the bonus:
Because we set the theme in C# code, we can use it to add the active class to the current theme in our dropdown list. This is the function of @(theme == "cerulean" ? "active" : "").
You can check out all of the themes on this site and pick a favorite. I kinda like Spacelab. Let me know your thoughts or issues in the new comments section. Thanks for reading.
Comments(0)