

{"id":12561,"date":"2019-12-18T10:38:56","date_gmt":"2019-12-18T15:38:56","guid":{"rendered":"https:\/\/rud.is\/b\/?p=12561"},"modified":"2019-12-18T14:15:28","modified_gmt":"2019-12-18T19:15:28","slug":"quickly-create-mostly-responsive-html-columns-with-htmltools","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/","title":{"rendered":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools}"},"content":{"rendered":"<p>I had need to present a wall-of-text to show off a giant list of SSL certificate alternate names and needed the entire list to fit on one slide (not really for reading in full, but to show just how many there were in a way that a simple count would not really convey).<\/p>\n<p>Keynote, PowerPoint, and gslides all let you make tables or draw boxes but I really didn&#8217;t want to waste time fiddling as much as I&#8217;d need to with those tools just for this one slide.<\/p>\n<p>Thankfully, I remembered that HTML5 <code>&lt;div&gt;<\/code> elements can be styled with a <code>column-count<\/code> attribute and we can use <code>{htmltools}<\/code> to make quick work of this task.<\/p>\n<p>To show it off, first we&#8217;ll need some words, so let&#8217;s make some using <code>stringi::stri_rand_lipsum()<\/code>:<\/p>\n<pre><code class=\"language-r\">library(stringi)\nlibrary(htmltools)\nlibrary(tidyverse)\n\nset.seed(201912)\n\nstri_rand_lipsum(5) %&gt;%\n  stri_paste(collapse = \" \") %&gt;%\n  stri_split_boundaries() %&gt;%\n  flatten_chr() %&gt;%\n  stri_trim_both() -&gt; words\n\nhead(words)\n## [1] \"Lorem\"  \"ipsum\"  \"dolor\"  \"sit\"    \"amet,\"  \"sapien\"\n\nlength(words)\n## [1] 514\n<\/code><\/pre>\n<p>Now, we&#8217;ll make a function &#8212; <code>columnize()<\/code> &#8212; that we can reuse in the future and have it take in a character vector, the column count we want and some CSS styling, then use some <code>{htmltools}<\/code> tag functions to make quick work of this task:<\/p>\n<pre><code class=\"language-r\">columnize &lt;- function(words, ncol = 5,\n                      style = \"p { font-family:'Roboto Condensed';font-size:12pt;line-height:12.5pt;padding:0;margin:0}\") {\n\n  tagList(\n    tags$style(style[1]),\n    tags$div(\n      words %&gt;%\n        map(tags$p) %&gt;%\n        tagList(),\n      style = sprintf(\"column-count:%d\", as.integer(ncol[1]))\n    )\n  )\n\n}\n<\/code><\/pre>\n<p>In this function we turn the <code>style<\/code> param into a <code>&lt;style&gt;<\/code> section in the generated HTML, then turn <code>words<\/code> into <code>&lt;p&gt;<\/code> tags wrapped in <code>&lt;div&gt;<\/code>.<\/p>\n<p>This function can be used in a R Markdown code block (set block parameters to <code>results='markup'<\/code>) to have the columns appear automagically in the resultant HTML document output. You can also use it in standalone fashion by using <code>html_print()<\/code> on the results:<\/p>\n<pre><code class=\"language-r\">html_print(\n  columnize(words, 10)\n)\n<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12562\" data-permalink=\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/10cols\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=2928%2C1624&amp;ssl=1\" data-orig-size=\"2928,1624\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=300%2C166&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=510%2C283&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=510%2C283&#038;ssl=1\" alt=\"10 columns of example text made with R\" width=\"510\" height=\"283\" class=\"aligncenter size-full wp-image-12562\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?w=2928&amp;ssl=1 2928w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=300%2C166&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=530%2C294&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=150%2C83&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=768%2C426&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=1536%2C852&amp;ssl=1 1536w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=2048%2C1136&amp;ssl=1 2048w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=500%2C277&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=1200%2C666&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=400%2C222&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=800%2C444&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?resize=200%2C111&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>The above is an image just for easier blog display purposes. You can test out a working example from a spun R script over at <a href=\"https:\/\/rud.is\/rpubs\/columnize.html\">https:\/\/rud.is\/rpubs\/columnize.html<\/a> that has some different column count examples. Grow and shrink the browser width to see how the columns shrink and grow with it.<\/p>\n<h3>FIN<\/h3>\n<p>Hopefully this helps others save time and effort like it did for me today. You can experiment with making the <code>columnize()<\/code> function more robust by having it work with all the other column-formatting properties:<\/p>\n<ul>\n<li><code>column-count<\/code>:  Specifies the number of columns an element should be divided into<\/li>\n<li><code>column-fill<\/code>: Specifies how to fill columns<\/li>\n<li><code>column-gap<\/code>:  Specifies the gap between the columns<\/li>\n<li><code>column-rule<\/code>: A shorthand property for setting all the column-rule-* properties<\/li>\n<li><code>column-rule-color<\/code>: Specifies the color of the rule between columns<\/li>\n<li><code>column-rule-style<\/code>: Specifies the style of the rule between columns<\/li>\n<li><code>column-rule-width<\/code>: Specifies the width of the rule between columns<\/li>\n<li><code>column-span<\/code>: Specifies how many columns an element should span across<\/li>\n<li><code>column-width<\/code>:  Specifies a suggested, optimal width for the columns<\/li>\n<li><code>columns<\/code>: A shorthand property for setting column-width and column-count<\/li>\n<\/ul>\n<p>You can find out more about these properties (and play with some examples) over at <a href=\"https:\/\/www.w3schools.com\/css\/css3_multiple_columns.asp\">https:\/\/www.w3schools.com\/css\/css3_multiple_columns.asp<\/a>.<\/p>\n<h3>POST-FIN<\/h3>\n<p>I robustified the function a bit:<\/p>\n<pre><code class=\"language-r\">#' Make a responsive columnar text div\n#'\n#' @param words character vector of text to present in a columnar div\n#' @param div_id tag `id` attribute to assign to the `&lt;div&gt;` (which can help you style it with the `style` param).\n#' @param div_class tag `class` attribute to assign to the `&lt;div&gt;` (which can help you style it with the `style` param)\n#' @param ncol number of columns\n#' @param width  specifies the column width; one of \"`auto`\" (the default) which leaves it up to the\n#'        browser implementation, a _length_ CSS size value that specifies the width of the columns.\n#'        The number of columns will be the minimum number of columns needed to show all the content\n#'        across the element., \"`initial`\" or \"`inherit`\" (see `fill` for descriptions of those).\n#' @param fill how to fill columns, balanced or not. One of \"`balance`\", \"`auto`\", \"`initial`\", \"`inherit`\".\n#'        Defaults to \"`balance`\" which fills each column with about the same amount of content, but will not\n#'        allow the columns to be taller than the height (so, columns might be shorter than the height as the\n#'        browser distributes the content evenly horizontally). \"`auto`\" fills each column until it reaches\n#'        the height, and do this until it runs out of content (so, this value will not necessarily fill all\n#'        the columns nor fill them evenly). \"`initial`\" sets this property to its default value; and\n#'        \"`inherit`\" inherits this property from its parent element.\n#' @param gap either a textual value (e.g. \"`10px`\") for the spacing gap between columns, or \"`normal`\"\n#'        (the default) which uses a `1em` gap on most browsers, \"`initial`\" or \"`inherit`\" (see `fill` for descriptions\n#'        of those).\n#' @param rule_color specifies the CSS color value of the rule between columns; also can be \"`initial`\" or \"`inherit`\"\n#'        (see `fill` for descriptions of those).\n#' @param rule_style specifies the style of the rule between columns; valid values are \"`none`\" (the default) for no\n#'        rule, \"`hidden`\", \"`dotted`\", \"`dashed`\", \"`solid`\", \"`double`\", \"`groove`\" for 3D grooved rule, \"`ridge`\"\n#'        for a 3D ridged rule, \"`inset`\" for a 3D inset rule, \"`outset`\" for a 3D outset rule, \"`initial`\" or\n#'        \"`inherit`\" (see `fill` for descriptions of those).\n#' @param rule_width specifies the width of the rule between columns; one of \"`medium`\" (the default), \"`thin`\", \"`thick`\",\n#'        a _length_ CSS size value, `initial`\" or \"`inherit`\" (see `fill` for descriptions of those).\n#' @param span specifies how many columns an element should span across; one of \"`none`\" (the default) so the element spans\n#'        across one column, \"`all`\" (spans across all columns), \"`initial`\" or \"`inherit`\"\n#'        (see `fill` for descriptions of those).\n#' @param style CSS style properties (complete text spec) that will be put into an `{htmltools}` `tags$style()` call that\n#'        will come along for the ride with the `&lt;div&gt;`; useful for specifying `&lt;p&gt;` properties for each item of the\n#'        `words` vector\n#' @note No validation is done on inputs\n#' @export\n#' @examples\n#' columnize(state.name, ncol = 3, rule_color = \"black\", rule_width = \"0.5px\")\ncolumnize &lt;- function(words,\n                      div_id = NULL,\n                      div_class = NULL,\n                      ncol = 5,\n                      width = \"auto\",\n                      fill = \"balance\",\n                      gap = \"normal\",\n                      rule_color = \"initial\",\n                      rule_style = \"none\",\n                      rule_width = \"medium\",\n                      span = \"none\",\n                      style = \"p {font-family:'Roboto Condensed';font-size:12pt;line-height:12.5pt;padding:0;margin:0}\") {\n\n  tagList(\n    tagList(\n     do.call(tags$style, as.list(style)),\n    ),\n    tags$div(\n      id = div_id,\n      class = div_class,\n      words %&gt;%\n        map(tags$p) %&gt;%\n        tagList(),\n      style = sprintf(\n        paste0(c(\n          \"column-count:%s\",\n          \"column-fill: %s\",\n          \"column-gap: %s\",\n          \"column-rule-color: %s\",\n          \"column-rule-style: %s\",\n          \"column-rule-width: %s\",\n          \"column-span: %s\",\n          \"column-width: %s\"\n        ), collapse = \";\"),\n        ncol, fill, gap, rule_color, rule_style, rule_width, span, width\n      )\n    )\n  )\n\n}\n<\/code><\/pre>\n<p>So now you can do something like:<\/p>\n<pre><code class=\"language-r\">columnize(\n  div_id = \"states\",\n  words = state.name, \n  ncol = 3, \n  rule_color = \"black\", \n  rule_style = \"solid\", \n  rule_width = \"2px\",\n  style = c(\n    \"#states { width: 50%; text-align: center };\\np {font-family:'Roboto Condensed'}\",\n    \"p { font-family: 'sans-serif'}\"\n  )\n) %&gt;% \n  htmltools::html_print()\n<\/code><\/pre>\n<p>and get:<\/p>\n<style>\n  #states { width: 50%; text-align: center };\np {font-family:'Roboto Condensed'}\n  p { font-family: 'sans-serif'}\n<\/style>\n<div id=\"states\" style=\"column-count:3;column-fill: balance;column-gap: normal;column-rule-color: black;column-rule-style: solid;column-rule-width: 2px;column-span: none;column-width: auto\">\n  Alabama<br \/>\n  Alaska<br \/>\n  Arizona<br \/>\n  Arkansas<br \/>\n  California<br \/>\n  Colorado<br \/>\n  Connecticut<br \/>\n  Delaware<br \/>\n  Florida<br \/>\n  Georgia<br \/>\n  Hawaii<br \/>\n  Idaho<br \/>\n  Illinois<br \/>\n  Indiana<br \/>\n  Iowa<br \/>\n  Kansas<br \/>\n  Kentucky<br \/>\n  Louisiana<br \/>\n  Maine<br \/>\n  Maryland<br \/>\n  Massachusetts<br \/>\n  Michigan<br \/>\n  Minnesota<br \/>\n  Mississippi<br \/>\n  Missouri<br \/>\n  Montana<br \/>\n  Nebraska<br \/>\n  Nevada<br \/>\n  New Hampshire<br \/>\n  New Jersey<br \/>\n  New Mexico<br \/>\n  New York<br \/>\n  North Carolina<br \/>\n  North Dakota<br \/>\n  Ohio<br \/>\n  Oklahoma<br \/>\n  Oregon<br \/>\n  Pennsylvania<br \/>\n  Rhode Island<br \/>\n  South Carolina<br \/>\n  South Dakota<br \/>\n  Tennessee<br \/>\n  Texas<br \/>\n  Utah<br \/>\n  Vermont<br \/>\n  Virginia<br \/>\n  Washington<br \/>\n  West Virginia<br \/>\n  Wisconsin<br \/>\n  Wyoming\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>I had need to present a wall-of-text to show off a giant list of SSL certificate alternate names and needed the entire list to fit on one slide (not really for reading in full, but to show just how many there were in a way that a simple count would not really convey). Keynote, PowerPoint, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[91],"tags":[],"class_list":["post-12561","post","type-post","status-publish","format-standard","hentry","category-r"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is\" \/>\n<meta property=\"og:description\" content=\"I had need to present a wall-of-text to show off a giant list of SSL certificate alternate names and needed the entire list to fit on one slide (not really for reading in full, but to show just how many there were in a way that a simple count would not really convey). Keynote, PowerPoint, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2019-12-18T15:38:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-12-18T19:15:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Quickly Create (Mostly) Responsive HTML Columns With {htmltools}\",\"datePublished\":\"2019-12-18T15:38:56+00:00\",\"dateModified\":\"2019-12-18T19:15:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\"},\"wordCount\":510,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png\",\"articleSection\":[\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\",\"url\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\",\"name\":\"Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png\",\"datePublished\":\"2019-12-18T15:38:56+00:00\",\"dateModified\":\"2019-12-18T19:15:28+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=2928%2C1624&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=2928%2C1624&ssl=1\",\"width\":2928,\"height\":1624,\"caption\":\"10 columns of example text made with R\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/rud.is\/b\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Quickly Create (Mostly) Responsive HTML Columns With {htmltools}\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/rud.is\/b\/#website\",\"url\":\"https:\/\/rud.is\/b\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/rud.is\/b\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\/\/rud.is\"],\"url\":\"https:\/\/rud.is\/b\/author\/hrbrmstr\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/","og_locale":"en_US","og_type":"article","og_title":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is","og_description":"I had need to present a wall-of-text to show off a giant list of SSL certificate alternate names and needed the entire list to fit on one slide (not really for reading in full, but to show just how many there were in a way that a simple count would not really convey). Keynote, PowerPoint, [&hellip;]","og_url":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/","og_site_name":"rud.is","article_published_time":"2019-12-18T15:38:56+00:00","article_modified_time":"2019-12-18T19:15:28+00:00","og_image":[{"url":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png","type":"","width":"","height":""}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools}","datePublished":"2019-12-18T15:38:56+00:00","dateModified":"2019-12-18T19:15:28+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/"},"wordCount":510,"commentCount":0,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png","articleSection":["R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/","url":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/","name":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools} - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png","datePublished":"2019-12-18T15:38:56+00:00","dateModified":"2019-12-18T19:15:28+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=2928%2C1624&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/12\/10cols.png?fit=2928%2C1624&ssl=1","width":2928,"height":1624,"caption":"10 columns of example text made with R"},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2019\/12\/18\/quickly-create-mostly-responsive-html-columns-with-htmltools\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Quickly Create (Mostly) Responsive HTML Columns With {htmltools}"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p23idr-3gB","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":4980,"url":"https:\/\/rud.is\/b\/2017\/02\/06\/strung-out-on-string-ops-a-brief-comparison-of-stringi-and-stringr\/","url_meta":{"origin":12561,"position":0},"title":"Strung Out On String Ops &#8211; A Brief Comparison of stringi and stringr","author":"hrbrmstr","date":"2017-02-06","format":false,"excerpt":"I made a promise to someone that my next blog would be about stringi vs stringr and I intend to keep said promise. stringr and stringi do \"string operations\": find, replace, match, extract, convert, transform, etc. The stringr package is now part of the tidyverse and is 100% focused on\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":12804,"url":"https:\/\/rud.is\/b\/2020\/08\/07\/quick-hit-comparison-of-whole-file-reading-methods\/","url_meta":{"origin":12561,"position":1},"title":"Quick Hit: Comparison of &#8220;Whole File Reading&#8221; Methods","author":"hrbrmstr","date":"2020-08-07","format":false,"excerpt":"(This is part 1 of n posts using this same data; n will likely be 2-3, and the posts are more around optimization than anything else.) I recently had to analyze HTTP response headers (generated by a HEAD request) from around 74,000 sites (each response stored in a text file).\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13391,"url":"https:\/\/rud.is\/b\/2022\/04\/04\/update-on-esc-pos-package-work\/","url_meta":{"origin":12561,"position":2},"title":"Update On ESC\/POS Package Work","author":"hrbrmstr","date":"2022-04-04","format":false,"excerpt":"The morning before work was super productive and there is a nigh-complete DSL for ESC\/POS commands along with the ability to just print {ggplot2}\/{grid} object. I changed the package name to {escpos} since it is no longer just plot object focused, and the DSL looks a bit like this: library(stringi)\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3127,"url":"https:\/\/rud.is\/b\/2014\/11\/26\/visualizing-historical-most-likely-first-snowfall-dates-for-u-s-regions\/","url_meta":{"origin":12561,"position":3},"title":"Visualizing Historical &#038; Most-likely First Snowfall Dates for U.S. Regions","author":"hrbrmstr","date":"2014-11-26","format":false,"excerpt":"UPDATE: You can now run this as a local Shiny app by entering shiny::runGist(\"95ec24c1b0cb433a76a5\", launch.browser=TRUE) at an R prompt (provided all the dependent libraries (below) are installed) or use it interactively over at Shiny Apps. The impending arrival of the first real snowfall of the year in my part of\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":10834,"url":"https:\/\/rud.is\/b\/2018\/05\/29\/the-fix-is-in-finding-infix-functions-inside-contributed-r-package-utilities-files\/","url_meta":{"origin":12561,"position":4},"title":"The Fix Is In: Finding infix functions inside contributed R package &#8220;utilities&#8221; files","author":"hrbrmstr","date":"2018-05-29","format":false,"excerpt":"Regular readers will recall the \"utility belt\" post from back in April of this year. This is a follow-up to a request made asking for a list of all the % infix functions in those files. We're going to: collect up all of the sources parse them find all the\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3498,"url":"https:\/\/rud.is\/b\/2015\/07\/09\/faceted-world-population-by-income-choropleths-in-ggplot\/","url_meta":{"origin":12561,"position":5},"title":"Faceted &#8220;World Population by Income&#8221; Choropleths in ggplot","author":"hrbrmstr","date":"2015-07-09","format":false,"excerpt":"Poynter did a nice interactive piece on world population by income (i.e. \"How Many Live on How Much, and Where\"). I'm always on the lookout for optimized shapefiles and clean data (I'm teaching a data science certificate program starting this Fall) and the speed of the site load and the\u2026","rel":"","context":"In &quot;cartography&quot;","block_context":{"text":"cartography","link":"https:\/\/rud.is\/b\/category\/cartography\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/12561","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=12561"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/12561\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=12561"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=12561"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=12561"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}