{"id":266050,"date":"2018-02-06T07:21:32","date_gmt":"2018-02-06T14:21:32","guid":{"rendered":"http:\/\/css-tricks.com\/?p=266050"},"modified":"2018-02-09T08:18:02","modified_gmt":"2018-02-09T15:18:02","slug":"counting-css-counters-css-grid","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/counting-css-counters-css-grid\/","title":{"rendered":"Counting With CSS Counters and CSS Grid"},"content":{"rendered":"

You\u2019ve heard of CSS Grid<\/a>, I\u2019m sure of that. It would be hard to miss it considering that the whole front-end developer universe has been raving about it for the past year.<\/p>\n

Whether you\u2019re new to Grid or have already spent some time with it, we should start this post with a short definition directly from the words of W3C<\/a>:<\/p>\n

Grid Layout is a new layout model for CSS that has powerful abilities to control the sizing and positioning of boxes and their contents. Unlike Flexible Box Layout, which is single-axis\u2013oriented, Grid Layout is optimized for 2-dimensional layouts: those in which alignment of content is desired in both dimensions.<\/p><\/blockquote>\n

<\/p>\n

In my own words, CSS Grid is a mesh of invisible horizontal and vertical lines.<\/strong> We arrange elements in the spaces between those lines to create a desired layout. An easier, stable, and standardized way to structure contents in a web page. <\/p>\n

Besides the graph paper foundation, CSS Grid also provides the advantage of a layout model that\u2019s source order independent<\/strong>: irrespective of where a grid item is placed in the source code, it can be positioned anywhere<\/em> in the grid across both<\/em> the axes on screen. This is very<\/em> important, not only for when you\u2019d find it troublesome to update HTML while rearranging elements on page but also at times when you\u2019d find certain source placements being restrictive to layouts.<\/p>\n

Although we can always move an element to the desired coordinate on screen using other techniques like translate<\/code>, position<\/code>, or margin<\/code>, they\u2019re both harder to code and to update for situations like building a responsive design, compared to true layout mechanisms like CSS Grid.<\/p>\n

In this post, we\u2019re going to demonstrate how we can use the source order independence of CSS Grid to solve a layout issue that\u2019s the result of a source order constraint. Specifically, we’re going to look at checkboxes and CSS Counters<\/a>.<\/p>\n

Counting With Checkboxes<\/h3>\n

If you\u2019ve never used CSS Counters, don\u2019t worry, the concept is pretty simple! We set a counter to count a set of elements at the same DOM level. That counter is incremented in the CSS rules of those individual elements, essentially counting them.<\/p>\n

Here\u2019s the code to count checked and unchecked checkboxes:<\/p>\n

<input type=\"checkbox\">Checkbox #1<br>\r\n<input type=\"checkbox\">Checkbox #2\r\n<!-- more checkboxes, if we want them -->\r\n\r\n<div class=\"total\">\r\n  <span class=\"totalChecked\"> Total Checked: <\/span><br>\r\n  <span class=\"totalUnChecked\"> Total Unchecked: <\/span>\r\n<\/div><\/code><\/pre>\n
::root {\r\n  counter-reset: checked-sum, unchecked-sum;\r\n}\r\n\r\ninput[type=\"checkbox\"] {\r\n  counter-increment: unchecked-sum;\r\n}\r\n\r\ninput[type=\"checkbox\"]:checked {\r\n  counter-increment: checked-sum;\r\n}\r\n\r\n.totalUnChecked::after {\r\n  content: counter(unchecked-sum);\r\n}\r\n\r\n.totalChecked::after {\r\n  content: counter(checked-sum);\r\n}<\/code><\/pre>\n

In the above code, two counters are set at the root element using the counter-reset<\/code><\/a> property and are incremented at their respective rules, one for checked and the other for unchecked checkboxes, using counter-increment<\/code><\/a>. The values of the counters are then shown as contents of two empty <span><\/code>s’ pseudo elements using counter()<\/code>.<\/p>\n

Here’s a stripped-down version of what we get with this code:<\/p>\n

See the Pen CSS Counter Grid<\/a> by CSS-Tricks (@css-tricks<\/a>) on CodePen<\/a>.<\/p>\n

This is pretty cool. We can use it in to-do lists, email inbox interfaces, survey forms, or anywhere where users toggle boxes and will appreciate being shown how many items are checked and how many are unselected. All this with just CSS! Useful, isn\u2019t it?<\/p>\n

But the effectiveness of counter()<\/code> wanes when we realize that an element displaying the total count can only appear after<\/em> all the elements to be counted in the source code. This is because the browser first needs the chance to count all the elements, before showing the total. Hence, we can\u2019t simply change the markup to place the counters above the checkboxes like this:<\/p>\n

<!-- This will not work! -->\r\n<div class=\"total\">\r\n  <span class=\"totalChecked\"> Total Checked: <\/span><br>\r\n  <span class=\"totalUnChecked\"> Total Unchecked: <\/span>\r\n<\/div>\r\n<input type=\"checkbox\">Checkbox #1<br>\r\n<input type=\"checkbox\">Checkbox #2<\/code><\/pre>\n

Then, how else can we get the counters above<\/em> the checkboxes in our layout? This is where CSS Grid and its layout-rendering powers come into play.<\/p>\n

Adding Grid<\/h3>\n

We’re basically wrapping the previous HTML in a new <div><\/code> element that\u2019ll serve as the grid container:<\/p>\n

<div class=\"grid\">\r\n\r\n  <input type=checkbox id=\"c-1\">\r\n  <label for=\"c-1\">checkbox #1<\/label> \r\n  <input type=checkbox id=\"c-2\">\r\n  <label for=\"c-2\">checkbox #2<\/label> \r\n  <input type=checkbox id=\"c-3\">\r\n  <label for=\"c-3\">checkbox #3<\/label> \r\n  <input type=checkbox id=\"c-4\">\r\n  <label for=\"c-4\">checkbox #4<\/label> \r\n  <input type=checkbox id=\"c-5\">\r\n  <label for=\"c-5\">checkbox #5<\/label> \r\n  <input type=checkbox id=\"c-6\">\r\n  <label for=\"c-6\">checkbox #6<\/label>\r\n\r\n  <div class=total>\r\n    <span class=\"totalChecked\"> Total Checked: <\/span>\r\n    <span class=\"totalUnChecked\"> Total Unchecked: <\/span>\r\n  <\/div>\r\n\r\n<\/div><\/code><\/pre>\n

And, here is the CSS for our grid:<\/p>\n

.grid { \r\n  display: grid; \/* creates the grid *\/\r\n  grid-template-columns: repeat(2, max-content); \/* creates two columns on the grid that are sized based on the content they contain *\/\r\n}\r\n\r\n.total { \r\n  grid-row: 1; \/* places the counters on the first row *\/\r\n  grid-column: 1 \/ 3;  \/* ensures the counters span the full grid width, forcing other content below *\/\r\n}<\/code><\/pre>\n

This is what we get as a result (with some additional styling):<\/p>\n

See the Pen CSS Counter Grid<\/a> by Preethi (@rpsthecoder<\/a>) on CodePen<\/a>.<\/p>\n

See that? The counters are now located above the checkboxes!<\/p>\n

We defined two columns on the grid element in the CSS, each accommodating its own content to their maximum size.<\/p>\n

When we grid-ify an element, its contents (text including) block-ify, meaning they acquire a grid-level box (similar to block-level box) and are automatically placed in the available grid cells.<\/p>\n

In the demo above, the counters take up both the grid cells in the first row as specified, and following that, every checkbox resides in the first column and the text after each checkbox stays in the last column.<\/p>\n

\"\"
The checkboxes are forced below the counters without changing the actual source order!<\/figcaption><\/figure>\n

Since we didn\u2019t change the source order, the counter works and we can see the running total count of checked and unchecked checkboxes at the top the same way we did when they were at the bottom. The functionality is left unaffected!<\/p>\n

To be honest, there\u2019s a staggering number of ways to code and implement a CSS Grid<\/a>. You can use grid line numbers, named grid areas, among many other methods. The more you know about them, the easier it gets and the more useful they become. What we covered here is just the tip of the iceberg and you may find other approaches to create a grid that work equally well (or better).<\/p>\n","protected":false},"excerpt":{"rendered":"

In this post, we’re going to demonstrate how we can use the source order independence of CSS Grid to solve a layout issue that’s the result of a source order constraint. Specifically, we’re going to look at checkboxes and CSS Counters—two concepts that rely on source order when used together.<\/p>\n","protected":false},"author":250902,"featured_media":266051,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[1378,686],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/01\/counter-grid.jpg?fit=1048%2C434&ssl=1","jetpack-related-posts":[{"id":333038,"url":"https:\/\/css-tricks.com\/the-holy-grail-layout-with-css-grid\/","url_meta":{"origin":266050,"position":0},"title":"The Holy Grail Layout with CSS Grid","date":"January 27, 2021","format":false,"excerpt":"How to build a very common layout with CSS grid. Header on the top, footer on the bottom. Two columns, sidebar and main content. This one has navigation above the main content but within that same column.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/01\/holy-grail-wire.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":305295,"url":"https:\/\/css-tricks.com\/4-css-grid-properties-and-one-value-for-most-of-your-layout-needs\/","url_meta":{"origin":266050,"position":1},"title":"4 CSS Grid Properties (and One Value) for Most of Your Layout Needs","date":"March 30, 2020","format":false,"excerpt":"CSS Grid provides us with a powerful layout system for websites. The CSS-Tricks guide gives you a comprehensive overview of Grid\u2019s properties with layout examples. What we\u2019re going to do here is a reverse approach to show you the smallest possible set of grid properties you need to know to\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/03\/css-grid-properties.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":372634,"url":"https:\/\/css-tricks.com\/using-grid-named-areas-to-visualize-and-reference-your-layout\/","url_meta":{"origin":266050,"position":2},"title":"Using Grid Named Areas to Visualize (and Reference) Your Layout","date":"August 26, 2022","format":false,"excerpt":"Whenever we build simple or complex layouts using CSS Grid, we're usually positioning items with line numbers. Grid layouts contain grid lines that are automatically indexed with positive and negative line numbers (that is unless we explicitly name them). Positioning items with line numbers is a fine way to lay\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2022\/08\/Modern-Desktop-Breakpoint.jpg?fit=1200%2C720&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":317548,"url":"https:\/\/css-tricks.com\/accordion-rows-in-css-grid\/","url_meta":{"origin":266050,"position":3},"title":"Accordion Rows in CSS Grid","date":"July 23, 2020","format":false,"excerpt":"I'd bet grid-template-columns is used about 10\u00d7 more than grid-template-rows, but maybe everyone has just been missing out. Eric Meyer chucks a bunch of row lines onto his main site layout grid like this: grid-template-rows: repeat(7, min-content) 1fr repeat(3, min-content); That way, if you need to use them they are\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/07\/fig06.png?fit=860%2C1156&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":314446,"url":"https:\/\/css-tricks.com\/grid-for-layout-flexbox-for-components\/","url_meta":{"origin":266050,"position":4},"title":"Grid for layout, flexbox for components","date":"June 25, 2020","format":false,"excerpt":"When should we reach for CSS grid and when should we use flexbox? Rachel Andrew wrote about this very conundrum way back in 2016: Flexbox is essentially for laying out items in a single dimension \u2013 in a row OR a column. Grid is for layout of items in two\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/grid-vs-flexbox.png?fit=1200%2C592&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":326473,"url":"https:\/\/css-tricks.com\/native-css-masonry-layout-in-css-grid\/","url_meta":{"origin":266050,"position":5},"title":"Native CSS Masonry Layout In CSS Grid","date":"November 30, 2020","format":false,"excerpt":"Rachel Andrew introducing the fact that masonry layout is going to be a thing in native CSS via CSS grid layout. The thing with masonry is that we can already do it for the most part, but there is just one thing that makes it hard: doing the vertical-staggering and\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/11\/pure-css-masonry.jpg?fit=1200%2C825&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/01\/counter-grid.jpg?fit=1024%2C424&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/266050"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/250902"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=266050"}],"version-history":[{"count":17,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/266050\/revisions"}],"predecessor-version":[{"id":266457,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/266050\/revisions\/266457"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/266051"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=266050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=266050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=266050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}