Responsive website with ASP.NET Core

This post describes how you can create a responsive website in ASP.NET Core. A responsive website adapts to different screen sizes, this makes your website easy to read on a smartphone, a tablet, a monitor or a TV.

Responsive web design means that you need to create adjustable styles to your front-end. A responsive website should adapt to screen sizes and not depend on devices used.

HTML Layout and @Media

Your website needs a layout view and one or more CSS-files. A layout view determines the design for your entire website, it sets the structure for your website and imports resources that your entire website needs. Other views in your project use your shared layout view and this means less code to write for each view.

You find all your views in the “Views” folder. In the root of this folder you find a “_ViewImports.cshtml” file, this file includes resources that is imported to all your views. The leading underscore in the filename is used for shared views and partial views, the leading underscore means that the file not should be part of routing and that it not should be served directly. The “_ViewImports.cshtml” file should import tag helpers and can include imports of other namespaces in your project.

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using Annytab.Common.Models

Our shared layout view is named “_standard_layout.cshtml” and is added to a “shared_front” folder in the “Views” folder. This is the contents of the layout file.

@using Microsoft.AspNetCore.Hosting
@using Annytab.Repositories
@using Annytab.Models
@inject IHostingEnvironment environment
@inject IStaticPageRepository static_page_repository
@inject ICommonServices tools
@{
    // Get form values
    List<BreadCrumb> breadCrumbs = ViewBag.BreadCrumbs;
    KeyStringList imageUrls = this.tools.GetDomainImageUrls(false);
    IList<StaticPage> staticPages = this.static_page_repository.GetAllActiveLinks("sort_value", "ASC");
}

<!DOCTYPE html>
<html lang="sv" prefix="og: http://ogp.me/ns#">
<head>
    @*Title and meta tags*@
    <title>@(ViewBag.Title + " - Fotbollstabeller.nu")</title>
    <meta name="description" content="@ViewBag.MetaDescription" />
    <meta name="keywords" content="@ViewBag.MetaKeywords" />
    <link rel="canonical" href="@ViewBag.MetaCanonical" />
    <meta name="robots" content="@(Context.Request.Host.Value != "fotbollstabeller.azurewebsites.net" ? ViewBag.MetaRobots : "noindex, nofollow")" />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,user-scalable=yes" />
    <meta name="google" content="notranslate">

    @*Facebook meta tags*@
    <meta property="og:title" content="@ViewBag.Title" />
    <meta property="og:description" content="@ViewBag.MetaDescription" />
    <meta property="og:type" content="website">
    <meta property="og:url" content="@ViewBag.MetaCanonical" />
    <meta property="og:image" content="@($"http://www.fotbollstabeller.nu{imageUrls.Get("big_icon")}")" />
    <meta property="og:site_name" content="Fotbollstabeller.nu" />

    @*Resources*@
    <environment names="Development">
        <link href="@this.tools.GetFilePath(imageUrls.Get("small_icon"))" rel="icon" type="image/x-icon" />
        <link href="@this.tools.GetFilePath("/css/standard_layout.css")" media="screen and (min-width:1344px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/medium_layout.css")" media="only screen and (min-width:1024px) and (max-width:1343px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/mobile_layout.css")" media="only screen and (max-width:1023px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/default_style.css")" rel="stylesheet" />
    </environment>
    <environment names="Staging,Production">
        <link href="@this.tools.GetFilePath(imageUrls.Get("small_icon"))" rel="icon" type="image/x-icon" />
        <link href="@this.tools.GetFilePath("/css/standard_layout.min.css")" media="screen and (min-width:1344px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/medium_layout.min.css")" media="only screen and (min-width:1024px) and (max-width:1343px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/mobile_layout.min.css")" media="only screen and (max-width:1023px)" rel="stylesheet" />
        <link href="@this.tools.GetFilePath("/css/default_style.min.css")" rel="stylesheet" />
    </environment>

    @*Google mobile ads*@
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <script>
        (adsbygoogle = window.adsbygoogle || []).push({
            google_ad_client: "ca-pub-3070633924070834",
            enable_page_level_ads: true
        });
    </script>
</head>
<body>
    @*Cookie consent*@
    <div class="annytab-cookie-consent">
        <div class="annytab-basic-padding">
            <span class="annytab-cookie-consent-text">Cookies hjälper oss att tillhandahålla våra tjänster. Genom att använda våra tjänster samtycker du till att vi använder cookies.</span>
            <button id="btnCookieConsent" type="button" class="annytab-basic-button">Jag förstår</button>
            <a href="/home/page/sekretesspolicy" class="cookie-consent-text">Läs mer</a>
        </div>
    </div>

    @*The background image*@
    <img id="backgroundImage" alt="Fotbollstabeller.nu, bakgrundsbild" src="@this.tools.GetFilePath(imageUrls.Get("background_image"))" class="annytab-background-image" />

    @*Master outer container*@
    <div class="annytab-layout-outer-container">

        @*Master inner container*@
        <div class="annytab-layout-inner-container">

            @*Standard header*@
            <div class="annytab-layout-standard-header">
                <a href="/"><img alt="Fotbollstabeller.nu, logotype" class="annytab-logotype" src="@this.tools.GetFilePath(imageUrls.Get("default_logotype"))" /></a>
            </div>

            @*Mobile header*@
            <div class="annytab-layout-mobile-header">
                <div id="toggleMobileMenu" class="annytab-layout-header-left"><i class="fas fa-bars fa-2x" aria-hidden="true"></i></div>
                <div class="annytab-basic-divider annytab-layout-header-right"></div>
                <a href="/"><img alt="Fotbollstabeller.nu, logotype" class="annytab-logotype" src="@this.tools.GetFilePath(imageUrls.Get("mobile_logotype"))" /></a>
            </div>

            @* Breadcrumbs *@
            @if (breadCrumbs.Count > 0)
            {
                <div class="annytab-breadcrumb-container">
                    @for (int i = 0; i < breadCrumbs.Count; i++)
                    {
                        if (i > 0)
                        {
                            <span class="annytab-basic-text-normal"> // </span>
                        }
                        <a href="@breadCrumbs[i].link" rel="nofollow" class="annytab-basic-text-normal">@breadCrumbs[i].name</a>
                    }
                </div>
            }

            @*Menu*@
            <div id="menu" class="annytab-layout-menu">
                <div class="annytab-layout-menu-padding">
                    @*Links*@
                    <a href="@("/")" class="annytab-menu-link not-hover">Startsidan</a>
                    @foreach (StaticPage post in staticPages)
                    {
                        <a href="@("/home/page/" + post.page_name)" class="annytab-menu-link not-hover">@post.link_name</a>
                    }
                </div>
            </div>

            @*Middle container*@
            <div class="annytab-layout-main-content">
                <div class="annytab-basic-padding">
                    @RenderBody()
                </div>
            </div>

            @*Footer*@
            <div class="annytab-layout-footer">
                <div class="annytab-basic-padding">
                    <span>@Html.Raw("© 2015 | Fotbollstabeller.nu")</span>
                </div>
            </div>
        </div>

        @*Right container*@
        <div class="annytab-layout-right-content">
            <div class="annytab-layout-right-ad">
                <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
                <!-- fotbollstabeller.nu - 300x600 -->
                <ins class="adsbygoogle"
                     style="display:block;width:300px;height:600px"
                     data-ad-client="ca-pub-3070633924070834"
                     data-ad-slot="3508160602"></ins>
                <script>
                    (adsbygoogle = window.adsbygoogle || []).push({});
                </script>
            </div>
        </div>

        @* Bottom spacing *@
        <div class="annytab-layout-bottom-spacing"></div>

    </div>

    <div id="fb-root"></div>

    @*Shared scripts*@
    @await Html.PartialAsync("/Views/shared_front/_shared_scripts.cshtml")

    @*Scripts*@
    <environment names="Development">
        <script src="/js/jquery/v3.3.1/jquery.js"></script>
        <script src="/js/font-awesome/v5.0.8/fontawesome-all.js"></script>
        <script src="@this.tools.GetFilePath("/js/annytab-front/annytab.default-functions.js")"></script>
    </environment>
    <environment names="Staging,Production">
        <script src="/js/jquery/v3.3.1/jquery.min.js"></script>
        <script src="/js/font-awesome/v5.0.8/fontawesome-all.min.js"></script>
        <script src="@this.tools.GetFilePath("/js/annytab-front/annytab.default-functions.min.js")"></script>
    </environment>
    @RenderSection("scripts", required: false)
</body>
</html>

This layout is responsive and can handle 3 types of screen sizes by using 3 different CSS-files and media queries. The first thing to mention is a meta-tag named “viewport”, this meta-tag tells browser that this website is responsive. The other thing to mention is the media queries used to load CSS-files, the first CSS-file is loaded if the width of the screen is at least 1344px (min-width:1344px), the second CSS-file is loaded if the width is between 1024px and 1344px, the third CSS-file is loaded if the width is less than 1024px.

I have also used 2 different headers, a standard header and a mobile header. These headers is different in structure and they are hidden or visible depending on the CSS-file loaded. The layout file also loads a partial view “_shared_scripts.cshtml”, a common CSS-file and JavaScript files. Other views will have there contents injected to @RenderBody() in the middle container.

CSS

Elements in your layout structure can have a fixed size, a maximum size and/or a minimum size, elements with a maximum size or a percentage size can adjust to the screen size. We have 3 different CSS-layouts, the standard and medium layouts have fixed width and the mobile layout have a responsive width.

Standard layout

/* Layout containers */
.annytab-layout-outer-container{margin:40px auto 0px auto;width:1344px;}
.annytab-layout-inner-container{float:left;width:1024px;background-color:#ffffff;border-radius:12px;}
.annytab-layout-standard-header{clear:both;overflow:hidden;width:auto;background-color:transparent;margin:0px 0px 0px 0px;border-radius:8px 8px 0px 0px;}
.annytab-layout-mobile-header{display:none;}
.annytab-layout-menu{display:block;margin:0px;text-align:left;background-color:#f2f2f2;}
.annytab-layout-menu-padding{padding:10px 10px 10px 10px;}
.annytab-layout-main-content{float:left;width:1024px;margin:0px;}
.annytab-layout-footer{clear:both;overflow:hidden;width:1024px;color:#ffffff;background-color:#267F00;border-radius:0px 0px 8px 8px;}
.annytab-layout-right-content{float:left;width:300px;}
.annytab-layout-right-ad {
    position: absolute;
    padding: 0px;
    margin: 0px 0px 0px 20px;
}
.annytab-layout-bottom-spacing{display:block;clear:both;margin-bottom:40px;}

/* Master page styling */
.annytab-background-image {
    position: fixed;
    z-index: -1;
    top: 0;
    left: 0;
    min-height: 100%;
    min-width: 100%;
    margin: 0px;
    padding: 0px;
}
.annytab-logotype{max-width:100%;}
.annytab-menu-link{display:inline-block;padding:5px 10px 5px 10px;background-color:#267F00;margin-right:5px;border-radius:2px;font-size:14px;line-height:14px;font-weight:normal;color:#ffffff;text-shadow:1px 1px 2px #000000;text-decoration:none;cursor:pointer;}
.annytab-menu-link:hover{text-decoration:none;background-color:#3DCE00;}

/* Display groups */
.annytab-list-table{display:inline-block;width:310px;height:420px;padding:0px;margin:10px;background-color:#ffffff;color:#000000;border-radius:4px;box-shadow:0px 0px 2px #000000;overflow:hidden;}

/* Ads */
.annytab-ad-slot-container-top{overflow:hidden;margin:10px 0px 10px 0px;}
.annytab-ad-slot-container-bottom{overflow:hidden;margin:10px 0px 10px 0px;}

Medium layout

/* Layout containers */
.annytab-layout-outer-container{margin:40px auto 0px auto;width:1024px;}
.annytab-layout-inner-container{float:left;width:1024px;background-color:#ffffff;border-radius:12px;}
.annytab-layout-standard-header{clear:both;overflow:hidden;width:auto;background-color:transparent;margin:0px 0px 0px 0px;border-radius:8px 8px 0px 0px;}
.annytab-layout-mobile-header{display:none;}
.annytab-layout-menu{display:block;margin:0px;text-align:left;background-color:#f2f2f2;}
.annytab-layout-menu-padding{padding:10px 10px 10px 10px;}
.annytab-layout-main-content{float:left;width:1024px;margin:0px;}
.annytab-layout-footer{clear:both;overflow:hidden;width:1024px;color:#ffffff;background-color:#267F00;border-radius:0px 0px 8px 8px;}
.annytab-layout-right-content{display:none;}
.annytab-layout-bottom-spacing{display:block;clear:both;margin-bottom:40px;}

/* Master page styling */
.annytab-background-image {
    position: fixed;
    z-index: -1;
    top: 0;
    left: 0;
    min-height: 100%;
    min-width: 100%;
    margin: 0px;
    padding: 0px;
}
.annytab-logotype{max-width:100%;}
.annytab-menu-link{display:inline-block;padding:5px 10px 5px 10px;background-color:#267F00;margin-right:5px;border-radius:4px;font-size:14px;line-height:14px;font-weight:normal;color:#ffffff;text-shadow:1px 1px 2px #000000;text-decoration:none;cursor:pointer;}
.annytab-menu-link:hover{text-decoration:none;background-color:#3DCE00;}

/* Display groups */
.annytab-list-table{display:inline-block;width:310px;height:420px;padding:0px;margin:10px;background-color:#ffffff;color:#000000;border-radius:4px;box-shadow:0px 0px 2px #000000;overflow:hidden;}

/* Ads */
.annytab-ad-slot-container-top{overflow:hidden;margin:10px 0px 10px 0px;}
.annytab-ad-slot-container-bottom{overflow:hidden;margin:10px 0px 10px 0px;}

Mobile layout

/* Layout containers */
.annytab-layout-container{margin:0px auto 0px auto;max-width:1024px;}
.annytab-layout-inner-container{max-width:1024px;background-color:#ffffff;}
.annytab-layout-standard-header{display:none;}
.annytab-layout-mobile-header{clear:both;position:relative;overflow:hidden;width:auto;height:42px;text-align:center;background-color:#267F00;margin:0px;}
.annytab-layout-header-left {
    z-index: 1;
    height: 100%;
    cursor: pointer;
    position: absolute;
    left: 5px;
    top: 0px;
    height: 33px;
    width: 42px;
    text-align: center;
    color: #ffffff;
    padding-top: 9px;
}

.annytab-layout-header-right {
    position: absolute;
    left: 47px;
    top: 0px;
    height: 42px;
    margin-left: 5px;
}
.annytab-layout-menu{display:block;background-color:#ffffff;z-index:5;position:absolute;width:100%;top:42px;margin:0px;display:none;border-bottom:1px solid #267F00;}
.annytab-layout-menu-padding{padding:20px 10px 0px 10px;}
.annytab-layout-main-content{clear:both;width:100%;max-width:1024px;margin:0px 0px 0px 0px;}
.annytab-layout-footer{clear:both;overflow:hidden;max-width:1024px;color:#ffffff;background-color:#267F00;}
.annytab-layout-right-content{display:none;}
.annytab-layout-bottom-spacing{display:block;clear:both;}

/* Master page styling */
.annytab-background-image {display:none;}
.annytab-logotype{max-width:100%;}
.annytab-menu-link{display:block;font-size:14px;line-height:14px;margin-bottom:20px;font-weight:bold;color:#267F00;text-decoration:none;cursor:pointer;}
.annytab-menu-link:hover{text-decoration:underline;}

/* Display groups */
.annytab-list-table{display:inline-block;width:280px;height:420px;padding:0px;margin:10px;background-color:#ffffff;color:#000000;border-radius:4px;box-shadow:0px 0px 2px #000000;overflow:hidden;}

/* Ads */
.annytab-ad-slot-container-top{display:none;}
.annytab-ad-slot-container-bottom{overflow:hidden;margin:10px 0px 10px 0px;}

Leave a Reply

Your email address will not be published. Required fields are marked *