Shiny Application Layouts Are Changing
<p dir="auto">Shiny application layouts are changing. If you've been around web development since the 90s, you might remember how different building web page layouts used to look.</p> <p dir="auto">As the web evolved, so did the layout (and styling) options available, maturing and changing to make what used to be convoluted solutions and workarounds into simpler, cleaner approaches.</p> <p dir="auto"><img class="alignnone size-full wp-image-16209" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cd7fb4af06205118382_sidebarLayout.webp" alt="sidebar Shiny Web Layout example" width="2078" height="914" /></p> <p dir="auto">With Shiny for R reaching its 10-year anniversary, its <code>column()</code> and <code>fluidRow()</code> system is starting to show its age and limitations, especially when compared to newer solutions and techniques. But how does it measure against other layout solutions? What other options are even out there? And how can you leverage state-of-the-art web solutions to create truly impressive Shiny dashboard layouts?</p> <blockquote> <p dir="auto">Shiny app development has come a long way. Discover how to <a href="https://appsilon.github.io/rhino/" target="_blank" rel="noopener">create Shiny apps like a full-stack software engineer using Rhino</a>.</p> </blockquote> <p dir="auto">Join me for a tour of how web layouts got to where we are now; what kind of solutions you can use with Shiny; package recommendations to spice up your next Shiny dashboard, and a peek into what you might not even know you're missing out on.</p> <p dir="auto">Table of Contents:</p> <ul><li><a href="#weblayout">What is a web layout</a></li><li><a href="#purpose">Why do web layouts matter in Shiny</a></li><li><a href="#shiny">How does Shiny do web layouts now</a></li><li><a href="#history">How we got here: the history of web layouts</a></li><li><a href="#CSS">CSS Flex and CSS Grid: state-of-the-art web layouts</a></li><li><a href="#solutions">Flex and Grid solutions: web layouts for R developers</a></li></ul> <hr /> <h2 id="weblayout" dir="auto">What is a web layout?</h2> <p dir="auto">Web layouts are an integral part of web development. You can think of them as the website structure or the arrangement of all visual elements on a webpage. While common layout patterns are a thing, each website ends up being a bit different. And a good layout that fits your specific needs will often help you balance aesthetics with practicality.<img class="alignnone size-full wp-image-16215" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cd7824742cc351ce3d4_web-layouts.webp" alt="Web layout designs" width="1018" height="251" /></p> <p dir="auto">Layouts are usually defined and iterated upon during the early stages of the design process of an application. They can take many forms, from a simple draft picture to a full-blown wireframe. But their purpose is clear: To guide developers during the implementation stage of the project and to give some shape and consistency to the different views of your application.</p> <p dir="auto"><img class="alignnone size-full wp-image-16187" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cd84cedf11e5f96c8cf_design-process.webp" alt="Design process for Shiny application layouts" width="1347" height="470" /></p> <h2 id="purpose" dir="auto">Why do web layouts matter in Shiny?</h2> <p dir="auto">At its core, Shiny is a web application framework. Like any other web page, it heavily relies on HTML, CSS, and JavaScript for its structure, looks, and functionality.</p> <p dir="auto"><img class="alignnone size-full wp-image-16203" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cd960c4b5e759a8532f_shiny-is-web.webp" alt="Shiny is a web application framework" width="590" height="163" /></p> <p dir="auto">Users often experience Shiny applications via a browser. So it should come as no surprise that, like any other web page, users have certain expectations when it comes to the application's speed, look, and experience.</p> <p dir="auto">Making our users' experience as comfortable, familiar, and fulfilling as other pages can be extremely important. When it comes to user adoption, a well-organized layout can sometimes be the difference between a happy and a frustrated user.</p> <h2 id="shiny" dir="auto">How does Shiny do layouts now?</h2> <p dir="auto">If you ever used base Shiny to build the UI of your application, you might have used functions such as <code>fluidPage()</code>, <code>splitLayout()</code>, or <code>fixedPage()</code>. These are some of the built-in layout templates that come with base Shiny.</p> <h3 dir="auto">Shiny layouts</h3> <img class="alignnone size-full wp-image-16205" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cda9506383404c34dde_shiny-layouts.webp" alt="Built-in Shiny layout templates with base Shiny" width="1347" height="582" /> <p dir="auto">While these are a great way to get started, they offer little flexibility in creating something more unique. At this point, you might have experimented with <code>fluidRow()</code> or <code>column()</code>. Maybe even with the "12 column system" in Shiny that allows you to create different size elements based on a size from 1 to 12.</p> <p dir="auto"><img class="alignnone size-full wp-image-16183" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cdd2a228de4b21cf445_bootstrap-layout.webp" alt="12 column system for Shiny layouts" width="1368" height="538" /></p> <h3 dir="auto">Bootstrap layouts</h3> <p dir="auto">It should come with no surprise, but this is actually a layout system borrowed from web development.</p> <p dir="auto">In the case of Shiny, Shiny specifically leverages <strong>Bootstrap 3</strong> for both widget styles and the layout system.</p> <p dir="auto">There is nothing wrong with <strong>Bootstrap 3</strong>, it (mostly) gets the job done... Except it came out in <em><strong>2013</strong></em>. If fact, Bootstrap itself is already on version 5! That's 2 major versions, and 10 years of technical improvements that base Shiny does not make use of.</p> <p dir="auto">That being said, using <strong>Bootstrap 5</strong> with Shiny is possible. Simply using <a href="https://appsilon.com/r-shiny-bslib/" target="_blank" rel="noopener">bslib in your Shiny project</a> will bump bootstrap to a higher version, even if you're still stuck with the 12-column system.</p> <p dir="auto">But what if you want to go more custom? What about layouts not based on the 12-column system? Sometimes you need a very specific size for an element, or your ideal layout doesn't fit into the row/column model. Maybe you are looking to add completely different layouts depending on the size of the screen.</p> <p dir="auto">This is where things get a bit more tricky.</p> <p dir="auto">Now, it's worth mentioning that Bootstrap is <strong>not</strong> the only layout system available for Shiny. In fact, many packages made for Shiny over the years offer different layout systems that replace the 12-column system. Different CSS frameworks offer different approaches to building layouts. And I recommended trying them out if you are looking for something unique.</p> <p dir="auto">In fact, most offer not only layouts but also different looking-widgets. If you're looking to spice up your dashboards, these can be a quick way to get started. Some of these include:</p> <p dir="auto"><img class="alignnone size-full wp-image-16199" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cdde196d46b4e1c6feb_layout-packages.webp" alt="Shiny layout R packages" width="1309" height="494" /></p> <ul dir="auto"><li><a href="https://appsilon.github.io/shiny.semantic/" target="_blank" rel="noopener">shiny.semantic</a> - Shiny support for Semantic(Fomantic) UI library.</li><li><a href="https://rinterface.github.io/shinyMobile/" target="_blank" rel="nofollow noopener">shinyMobile</a> - Built on top of the latest Framework7 template.</li><li><a href="https://rinterface.github.io/bs4Dash/index.html" target="_blank" rel="nofollow noopener">bs4Dash</a> - Bootstrap 4 Shiny dashboards using AdminLTE 3.</li><li><a href="https://rinterface.github.io/argonDash/" target="_blank" rel="nofollow noopener">argonDash</a> - Bootstrap 4 Argon template for Shiny dashboards.</li><li><a href="https://rinterface.github.io/tablerDash/" target="_blank" rel="nofollow noopener">tablerDash</a> - Tabler dashboard template for Shiny with Bootstrap 4.</li></ul> <h2 id="history" dir="auto">How we got here: the history of web layouts</h2> <p dir="auto">So what <em><strong>is</strong></em> the state of the art when it comes to web layouts? To understand this, and where Shiny fits regarding available techniques and technologies, let's take a quick look at the story of web layouts. From the 80s until present day, a few techniques have been developed and taken center stage at different points in time:</p> <p dir="auto"><img class="alignnone size-full wp-image-16213" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cdfb1e58f77d3b164a4_timeline.webp" alt="a brief history of web layouts" width="1262" height="188" /></p> <h3 dir="auto">The early days (89 - 97)</h3> <p dir="auto">The original proposals for HTML, the standard for structuring web pages, started all the way back in 1989, lasting until early 1997. The practical realization of HTML was all about on-screen presentation. This included published recommendations, browsers & development tools, and actual websites.</p> <p dir="auto">At this point, web developers were mostly focused on document sharing. Leading focus toward document requirements such as headers, fonts, and paragraphs. After proposing the idea of controlling layouts via style sheets in 1993, it would still take some time for it to become mainstream.</p> <p dir="auto">Around this time (as well as during the reign of tables for layouts) the HTML document structure dictated the page layout. And the thought that you would need more than sequential content, was barely even considered.</p> <p dir="auto">Early HTML specs actually state that "The elements within the BODY element are in the order in which they should be presented to the reader."</p> <ul dir="auto"><li>Primarily for document sharing</li><li>Focused on document requirements such as headers, fonts, and paragraphs</li><li>HTML document structure dictated the page layout</li></ul> <img class="alignnone size-full wp-image-16201" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01cdf99f2296f27b47f05_nostalgia.webp" alt="Early days of web layouts" width="810" height="481" /> <h3 dir="auto">HTML Tables (late 90s)</h3> <p dir="auto">In 1991 <code>ViolaWWW</code> grew into the most sophisticated of the early Web browsers. It is claimed to have been the first browser with support for style sheets, tables, and nest-able HTML elements. Following in 1993 a proposal was made for "columns" in a presentation language for the web. This proposal did not directly turn into CSS. "The styles defined, specify the recommended behavior of HTML objects in terms of: .... page layout ... column ....".</p> <p dir="auto">These were the initial works of tables in HTML, and finally, in 1997, HTML 3.2 released as a W3C Recommendation. It stated that tables "can be used to markup tabular material or for layout purposes"... And oh boy did people take it literally. Tables became the base for most web pages and were considered the go-to when structuring content. It was a wild time of invisible gifs used for spacing, convoluted markup, and many more terrifying things.</p> <script src="https://gist.github.com/MicahAppsilon/668315c6e5ee4d499b69b6cdd5e8a683.js"></script> <p dir="auto"><img class="alignnone size-full wp-image-16211" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce0e196d46b4e1c721f_table-layout.webp" alt="Table web layout" width="1104" height="437" /></p> <ul dir="auto"><li>In 1993 a proposal was made for "columns" in web pages;</li><li>In 1997, HTML 3.2 released. It stated that tables "can be used to markup tabular material or for layout purposes";</li><li>Tables became the base for most web pages and were considered the go-to when structuring content.</li></ul> <h3 dir="auto">Floats and the first layout frameworks (00’s)</h3> <p dir="auto">A new CSS property made its way to the top, <code>float</code>. The idea of float was simple: you have an element and need text to wrap around it, float that element and you get exactly that! Simple right? Well...</p> <p dir="auto">If you couple this with fixed sizing for floated elements, a large dose of space-clearing techniques, and the CSS <code>position</code> property one could achieve A LOT. This was the conclusion that some clever developers reached in the early 2000s, allowing multi-column layouts and becoming the go-to for these times.</p> <p dir="auto">Eventually, frameworks using these techniques started gaining popularity that would hide these <em>hacks</em> behind CSS classes and HTML structures, making life even easier.</p> <p dir="auto">Bootstrap 3, the base for Shiny, is a great example of one such framework that, even now, can be found in millions of websites. Even though its newest iteration, bootstrap 5, no longer uses this approach and instead relies on flexbox for its layout system.</p> <script src="https://gist.github.com/MicahAppsilon/c1b89f0c0566f1f6e197e002196eb538.js"></script> <p dir="auto"><img class="alignnone size-full wp-image-16191" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce2487b2c34e79536b3_float-layout.webp" alt="Float web layout" width="1147" height="393" /></p> <ul dir="auto"><li>An old CSS property got a new life, <code>float</code>;</li><li>Float was <strong>not</strong> a layout property. Its intended use was for text to wrap around an element;</li><li>CSS Frameworks were able to abuse <code>float</code> and <code>position</code> to give us the first layout frameworks.</li></ul> <h3 id="CSS" dir="auto">CSS Flex/Flexbox (2012)</h3> <p dir="auto">The introduction of the <code>display: flex;</code> CSS property around 2012 was a real game changer, solving many existing layout problems, and being widely praised by both web developers and designers.</p> <p dir="auto">This was the first true CSS property to be 100% created for layouts, making its way into modern web development extremely fast.</p> <p dir="auto">It is especially powerful for page layouts that can define primarily in terms of either columns or rows. For instance, if we want to align a few elements in a single row, <code>display: flex;</code> provide us with a modern and easy way to do so. No tricks, clear spacing, or hacky solutions - just one line of CSS.</p> <p dir="auto">Not only that, flex came with built-in control of other CSS properties such as alignment and visual ordering of elements. All without having to change the HTML structure directly.</p> <p dir="auto">As HTML became more and more semantic-based, especially now with the release of HTML 5, this is even more important. Because we now have a way to fully decouple the presentation layer from the content itself.</p> <script src="https://gist.github.com/MicahAppsilon/a89fda86695629e299ef1ea7e1595cb2.js"></script> <p dir="auto"><img class="alignnone size-full wp-image-16189" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce3b4f97b8067c0b119_flex-layout.webp" alt="Flex web layout" width="1106" height="468" /></p> <ul dir="auto"><li>First CSS property focused on layouts;</li><li>Powerful for layouts that can define in either columns or rows (one dimension);</li><li>Control of element flow without having to change the HTML markup directly.</li></ul> <h3 dir="auto">CSS Grid (2018)</h3> <p dir="auto">As the world moved forward, web developers found themselves facing a new challenge - responsive design. Up until recently, screen sizes or different devices were not something in anyone's mind. In fact, while it was possible to write CSS for different screen sizes, this would often require building multiple pages multiple times, or creating one main layout and <em>tweak</em> it to different screens.</p> <p dir="auto">At the time of this article, <code>display: grid;</code> is the only CSS property designed and intended for building flexible responsive layouts. This sort of challenge requires a layout area that can be manipulated in two dimensions – both horizontally and vertically – and that is exactly what CSS Grid does.</p> <p dir="auto">While Flex gave us full control over either columns or rows, Grid goes one step forward and can handle both rows and columns at the same time. Meaning, that it will align items to both the horizontal and vertical tracks you have defined. Grid is also 'mostly' defined on the parent container, not the elements themselves as is the case with flexbox.</p> <script src="https://gist.github.com/MicahAppsilon/7173c7989e40911a2a3c0e246b885276.js"></script> <p dir="auto"><img class="alignnone size-full wp-image-16195" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce5d29d4bcb96856132_grid-layout.webp" alt="Grid web layout" width="1107" height="290" /></p> <ul dir="auto"><li>The only CSS property intended for building responsive layouts;</li><li>Grid handles both rows and columns (Two dimensions);</li><li>Mostly defined on the container, not the children as it is with flexbox;</li><li>Supports named areas.</li></ul> <h2 dir="auto">New is always better... Right?</h2> <p dir="auto">So CSS Grid wins! Well... No.</p> <p dir="auto">Flex and Grid serve different purposes and are both incredibly useful. Very often when creating a layout, mixing Flex and Grid will give you the most flexibility. And knowing what to use when can supercharge your development speed. I personally prefer to leverage both at the same time:</p> <p dir="auto">Flex when:</p> <ul dir="auto"><li>The content sets the size;</li><li>You need only horizontal or vertical alignment;</li><li>The layout is one-dimensional;</li><li>You require better support for older browsers.</li></ul> <p dir="auto">Grid when:</p> <ul dir="auto"><li>Things need a set width regardless of content;</li><li>The layout is two-dimensional;</li><li>Elements need to overlap/float above each other.</li></ul> <p dir="auto">A common rule of thumb is to use Grid for full-page layouts and Flex for smaller elements. Or consider whether the layout you plan to build is one-dimensional (Flex) or two-dimensional (Grid).</p> <h2 id="solutions" dir="auto">This sounds great, but I'm a Shiny developer, not a web developer!</h2> <p dir="auto">Well, if you are a Shiny developer I'm sorry, but you <strong>ARE</strong> a web developer!</p> <p dir="auto">In most cases, anything you can do on the web can be used with Shiny. In the worst cases, using HTML and CSS directly in Shiny is always an option. Meaning, that you can always leverage web technologies to get things done.</p> <p dir="auto">Fortunately, the R community is amazing at making R developers avoid using HTML and CSS directly, and, just like with packages that wrap other CSS frameworks than Bootstrap, CSS Grid and Flex R package solutions are becoming more popular!</p> <hr /> <p dir="auto">If you took part in rstudio::conf(2022), you might have even heard of RStudio's new visual builder for Shiny UI, <a href="https://rstudio.github.io/shinyuieditor/" target="_blank" rel="nofollow noopener">shinyuieditor</a>.</p> <p dir="auto">Under the hood, <code>shinyuieditor</code> actually uses CSS Grid, via a package, that you can also use without the visual editor, the <a href="https://rstudio.github.io/gridlayout/" target="_blank" rel="nofollow noopener">gridlayout</a> package.</p> <p dir="auto"><img class="alignnone size-full wp-image-16207" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce6db456a59ff5b9a6d_shinyuieditor-shiny-layout.webp" alt="Shiny UI Editor layout" width="1345" height="1127" /></p> <p dir="auto">But that's not all. There are other options out there!</p> <p dir="auto"><a href="https://rstudio.github.io/bslib/" target="_blank" rel="nofollow noopener">bslib</a> for example, allows you to upgrade to the newest versions of Bootstrap with minimal effort, and while you are still using the 12-column system, your application will actually be using CSS Flex.</p> <p dir="auto"><a href="https://appsilon.github.io/shiny.semantic/" target="_blank" rel="noopener">shiny.semantic</a> on the other hand comes with a built-in CSS Grid function in the form of <a href="https://appsilon.com/shiny-semantic-grid/" target="_blank" rel="noopener">shiny.semantic::grid()</a>.</p> <hr /> <p dir="auto">For pure usage of CSS Grid and Flex, there is also <a href="https://www.anatomyofcode.com/imola/" target="_blank" rel="nofollow noopener">imola</a> that aims at giving you the full functionality of CSS Grid and Flex containers from R, without the need to write CSS directly.</p> <p dir="auto">It also comes with templates and breakpoint systems built-in, making it a great tool for large projects that want to build and reuse their own responsive layout systems.</p> <blockquote> <p dir="auto">Add custom styling and layouts with <a href="https://appsilon.com/professional-shiny-app-ui/" target="_blank" rel="noopener">{imola} and {shiny.fluent}</a>.</p> </blockquote> <h3 dir="auto"><a id="user-content-what-layout-system-should-i-use-for-r-shiny" class="anchor" href="https://github.com/Appsilon/blog-posts-markdown/blob/pedro.weblayouts-history/web-layouts-and-shiny/Shiny-application-layouts.md#what-layout-system-should-i-use-for-r-shiny" aria-hidden="true"></a>What layout system should I use for R Shiny?</h3> <p dir="auto">In general, it really depends on what you are looking for, and how deep you want to get into the technologies. I do recommend trying out Grid and Flex in some form. Its browser support is outstanding, and it's one of those things that once you start using, it's hard to go back. :D</p> <h4 dir="auto">bslib</h4> <p dir="auto">Consider <a href="https://rstudio.github.io/bslib/" target="_blank" rel="nofollow noopener">bslib</a>, of a different framework layout system if you:</p> <ul dir="auto"><li>Are just looking to stay up to modern standards;</li><li>Are working on a layout that is simple enough that rows and columns will be enough;</li><li>Want mobile and responsive support, but simple support will do.</li></ul> <img class="alignnone size-full wp-image-16185" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce8e1a67d4ac38e6231_bslib-shiny-layout.webp" alt="bslib Shiny layout inputPanel()" width="2525" height="1248" /> <h4>gridlayout</h4> <p dir="auto">Check out <a href="https://rstudio.github.io/gridlayout/" target="_blank" rel="nofollow noopener">gridlayout</a> if you:</p> <ul dir="auto"><li>Are using <a href="https://rstudio.github.io/shinyuieditor/" target="_blank" rel="nofollow noopener">shinyuieditor</a> to scaffold your UI, and would like to do some code-based tweaks;</li><li>Need support for markdown documents;</li><li>Would like to get started with CSS Grid, but are less interested in CSS;</li><li>Have no need for CSS Flex, and Grid layouts will do just fine.</li></ul> <h4>imola</h4> <p dir="auto">Try out <a href="https://www.anatomyofcode.com/imola/" target="_blank" rel="nofollow noopener">imola</a> if you:</p> <ul dir="auto"><li>Would like access to both CSS Grid and Flex layouts from R (both at a page and panel level);</li><li>Are already familiar or interested in CSS and its options, but would like to do this from R (no CSS directly);</li><li>Are building a large application or UI package that requires reusing layouts, or defining custom breakpoints for different screen sizes;</li><li>Ability to save and reuse layouts (via a templating system);</li><li>Ability to change or create your own breakpoint systems (or pick from a few systems built-in).</li></ul> <img class="alignnone size-full wp-image-16193" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01ce8824742cc351cee26_gridlayout-vs-shinyuieditor-shiny-layout.webp" alt="gridlayout vs CSS flex, with shinyuieditor" width="1199" height="847" /> <h2 dir="auto">Wrapping up Shiny web app layouts</h2> <p dir="auto">Shiny is an amazing piece of technology that allows us to quickly build and create applications directly from R. Its limitations are nearly endless, and, as developers, keeping up to speed with web standards can be a great way of making your Shiny apps feel more modern and interesting.</p> <p dir="auto">Right now, for layouts, Grid and Flex are the state of the art. But who knows what will come next? I believe Grid and Flex will be around for a long time, so what better time to try out something new than right now? :)</p> <p dir="auto">Do you have a preferred layout or R package for your Shiny projects? Share your project by tagging us on <a href="http://twitter.com/appsilon" target="_blank" rel="nofollow noopener">Twitter</a> or <a href="https://www.linkedin.com/company/appsilon" target="_blank" rel="nofollow noopener">LinkedIn</a>. And be sure to <a href="https://appsilon.com/shiny-weekly-announcement/" target="_blank" rel="noopener">sign-up for Shiny Weekly</a> to stay up to date on all things Shiny - from user tests and UI/UX to community events and tutorials.</p>