Chris’ Corner: Useful HTML and CSS Patterns
The <table>
is one of the grand enemies of responsive design. They don’t wrap (that wouldn’t make much sense) so they can “blow out” the width of a mobile device pretty easily. The overflow
property also doesn’t work on them. So you gotta find a way, and it really depends on the data. Sometimes a row of table data is pretty independently useful (imagine a row of employee data) so making all the <tr>
and <th>
/<td>
element display: block
and stacking them works. But that doesn’t work for data that needs to be cross-referenced. I think there are 3-4 other patterns that involve shuffling the data around to be more narrow-screen friendly. The old group of jQuery plugins Tablesaw from Filament Group showcase some of them.
Lately, I find rather than dig around for a display-altering solution, people just wrap the table in a <div>
and let that <div>
have overflow
. So now you’ve got a table that you can scroll/swipe around without really changing how the table looks. I find myself consulting Under-Engineered Responsive Tables by Adrian Roselli on how best to do that regularly.
Ryan Mulligan has a cool take as well in Full-bleed Table Scrolling on Narrow Viewports. The “full bleed” part means using the edge of the browser window. Which you might otherwise not! Typically there is padding on the left/right (“inline”) edges of content, which would also be limiting the width of the table.
The blue line in the screenshot above shows the padding on the column of content, which limits the width of the content inside there, but the table is explicitly pulled out from it to the edge. It’s a little thing but it’s classy!
Josh Comeau’s tutorial Animated Pride Flags has lots of fun things to learn along the way of creating a controllable version of this:
Notice that staggering is a big part of the look here. That happens with slightly different values to animation-delay
. Since Josh used React to created the DOM for this, the loop can output those values as inline styles and use the number of iterations that map
provides to stagger the value.
But wait! Maybe CSS should be helping us here, rather than us having to invent our own way to stagger things, right? That’s what the sibling-count()
and sibling-index()
proposal is all about. I’m a fan.
Josh’s tutorial basically just starts here and then covers more and more details. I especially like the bits of also stagging how much any given column “billows”, which is another use-case of staggering a custom property value. Also don’t miss the bits about double-stop color gradients and rounding width values to prevent awkward pixel gaps.
How should I mark this up? is always fun trivia. For me, anyway, I’m a very exciting person. Sometimes HTML has pretty cut-and-dry right and wrong ways to do things, but sometimes it doesn’t. There are differents ways with styling tradeoffs, accessibility tradeoffs, amount of markup tradeoffs, etc.
Lea Verou found a good one in What is the best way to mark up an exclusive button group? In other words, a group of buttons where only one can be active at a time. A multi-toggle? Lea, and plenty of other people, assumed that a group of <input type="radio">
is the right answer (only one radio button can be active at once), and then style them like buttons. I thought about <select>
too which can only have one active choice, but no way are you going to be able to style that as buttons, even with the wildly more styleable <select-menu>
.
Léonie Watson stepped in with advice that essentially boiled down to: if they look like <button>
s, you should use <button>
s, so there isn’t “a mismatch of expectations in terms of keyboard interaction and shortcuts.” Interesting!
Lea thinks maybe we need a <button-group>
. Again, I’m a fan. I would have even kept <hgroup>
around, me, for grouping multiple headers.
Have you heard this (correct) advice? Placeholders aren’t labels. Like, don’t do this:
<input type="text" placeholder="Your Mastodon Profile" />
Do this:
<label for="mastodon-profile">Your Mastodon Profile</label>
<input type="text" id="mastodon-profile" placeholder="https://fosstodon.org/@codepen" />
A placeholder can be a little bonus hint or something, but even then, if that hint is important it should be accessible text which placeholder text is not.
I’m thinking of that because I saw Stanko Tadić’s CSS only floating labels. Floating labels is a pattern where text that looks like placeholder text (text within the input) moves away from the input but remains visible. This has gotten a bit easier as of late with the :placeholder-shown
pseudo-class.
What I like about the floating label pattern is that it continues to use <label>
, so the accessibility remains. It’s also just kind of clever and fun. What I don’t like about it is that I don’t think it does anything truly useful. I’ve heard proponents of it say that it “saves space” because the label is inside the input. But it’s only inside the input until it’s focused, then it moves out, and it moves out to somewhere where it needs to remain visible and have space. So……… why don’t you just put the labels where they move out to in the first place? Kinda feels like movement, for movement’s sake.
If you haven’t tried to create a password with Neal Agarwal’s * The Password Game yet, you really should give it a crack.
Chris’ Corner: Clever CSS Ideas & Explanations
If you think frosted glass effect in CSS, you probably think of the backdrop-filter
property. Just backdrop-filter: blur(10px);
will do the trick. I still think the look is kind of cool and fresh, but I should check myself a little here as the effect was popularized in the iOS 7 release which was 10 years ago 🫠.
Here is a fresh take though: Frosted Glass: Depth-based blur in CSS (make sure to mouse around to see the dynamic effect, and scroll down to see the effect on different backgrounds).
The how-to is that layered blurs are masked and the mask moves with the mouse. I love clever stuff like that, which ends up fairly simple.
The above demo is a nice demonstration of masking, actually, because it’s doing something that is uniquely mask-y: using a gradient. The other concept that can cut out parts of something is a clip-path
, but with a clipping path, any given part of an element is either clipped or not, whereas with a mask, an area can become partially transparent.
Ahmad Shadeed has a recent article on CSS Masking that does a good job of explaining how it all works and what you can do with it.
There is this little design concept that if you have nested elements that both have border-radius
, they can’t have the same border-radius
otherwise they tend to have a weird little hump in the middle and essentially just look off and not particulary professional. I wrote about this in 2011 and have had many people thank me over the years! (not that I’m the first.)
The general thinking is that you subtract one from the other, and it comes up from time to time. Adam Argyle recently noted that there is a way to solve this with no math at all, but it’s Chrome-only at this time.
This uses overflow: clip;
and overflow-clip-margin: content-box;
which this is the first I’m hearing of the latter! I like it!
I feel like we’re doing a good job of talking about paths this week so lemme slip another one in here: Jhey’s Circular Text with CSS?. To be clear: there isn’t a normal first-class CSS citizen kinda way to say “set this text on this path”. Unless that path is a straight line, I suppose. SVG has the <textPath>
element and that’s really what you want here if you’re going to this even semi-seriously. But there is some trickery to be had here!
This makes me feel like Captain Old again saying I wrote about this in 2012, but here we are. The trick then was to break the text into individual character <span>
s and then transform them all around a shared origin:
Jhey’s idea still uses a monospace font and breaking the characters up into spans, but there is more clever math involved. He’s got it set up so however many characters you use, the complete one full circle no matter what. The secret is trigonometric functions, which are only freshly available in CSS. Plus he took the time to make sure there is screen-reader-friendly text in there too, as text-as-spans is a nightmare that way.
If you read all the stuff above and felt some version of ughkg CSS is so hard, maybe you’ll find some solace in Mike Aparico’s Why we’re bad at CSS. Part of Mike’s point is that CSS gets harder the more you try to avoid it, or apply abstractions that are too heavy-handed.
We want our styles to be generic enough to reuse in different contexts but not so generic that we have to constantly repeat ourselves in those contexts.
I feel like there is a tendency for people who feel like they have a handle on CSS to have essentially invented their own methodology (whether they choose to share it or not). That might seem like a failing of CSS or something that you need to invent your own system to be effective with it, but ultimately I think that’s true of any language. You build up your own ways of doing things that works for you and run with it.
Redefining Element Positioning With CSS Inset Property
Building responsive web pages is essential if you want your website to run flawlessly on multiple browsers without hiccups. However, websites can’t be fully responsive without a proper layout. Here the CSS position property lets you do this.
The CSS position properties set a specified element relative to its parent or the viewport. The CSS position properties take in five values, namely,
Spring Sale!
🌻 Save 30% on our WordPress books with coupon code SPRING2023
. Combine discount with any COMBO deals and save up to 50% on books. Shop books »
🌻 Bonus! Code SPRING2023
also good for 25% off all pro WordPress plugins, including BBQ Pro, Blackhole Pro, USP Pro, SAC Pro, and more. Shop plugins »
Discount code expires June 26th, 2023
Mastering CSS Variables and Unlocking Their Full Potential
CSS Variables, also known as Custom Properties, have revolutionized the way we manage styles and build maintainable, flexible stylesheets. They enable developers to store and reuse values throughout a stylesheet, making it easier to change themes, colors, fonts, and more with just a few updates. In this article, we’ll explore the best practices for using CSS variables, along with some helpful code examples.
Your Designer Toolbox Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
1. Defining and Using CSS Variables
To define a CSS variable, you must use the double hyphen (–) syntax. Typically, you’ll want to create your variables within the :root pseudo-class, which refers to the highest-level parent element in the DOM tree. This ensures that your variables are globally accessible.
:root { --primary-color: #3498db; --secondary-color: #2ecc71; --font-size: 16px; } body { font-size: var(--font-size); } a { color: var(--primary-color); } button { background-color: var(--secondary-color); }
In the example above, we’ve defined three CSS variables: –primary-color, –secondary-color, and –font-size. To use these variables, we use the var() function, which accepts the variable name as its argument.
2. Fallback Values
One of the great features of CSS variables is their ability to provide a fallback value. This is helpful when a variable may not be defined or supported by a particular browser. To provide a fallback value, include a second argument within the var() function.
body { font-size: var(--font-size, 16px); }
In this example, if the –font-size variable isn’t defined, the browser will use the fallback value of 16px.
3. Leveraging Variables in Media Queries and Theming
CSS variables are incredibly useful when combined with media queries and theming. You can quickly and easily update your styles for different devices or themes by redefining the variable values.
:root { --font-size: 16px; } @media screen and (min-width: 768px) { :root { --font-size: 18px; } } body { font-size: var(--font-size); }
In this example, we’ve updated the –font-size variable within a media query. When the screen width is at least 768px, the font size will automatically adjust to 18px.
4. Working with Calculated Values
CSS variables can be combined with the calc() function to create dynamic and flexible values.
:root { --base-padding: 10px; } .container { padding: calc(var(--base-padding) * 2); }
In the example above, we’ve defined a base padding value and used it in combination with the calc() function to double the padding for the .container element.
5. Handling Colors with HSL and CSS Variables
When working with colors, using the HSL color format in combination with CSS variables makes it easier to create color schemes and adjust hues, saturation, and lightness.
:root { --primary-hue: 210; --primary-color: hsl(var(--primary-hue), 50%, 50%); --primary-color-light: hsl(var(--primary-hue), 50%, 75%); --primary-color-dark: hsl(var(--primary-hue), 50%, 25%); } a { color: var(--primary-color); } a:hover { color: var(--primary-color-light); } a:active { color: var(--primary-color-dark); }
In this example, we’ve used the HSL color format and CSS variables to create a primary color and its lighter and darker variations. By adjusting the –primary-hue value, you can change the color scheme throughout your stylesheet with ease.
6. JavaScript Interoperability
CSS variables can be accessed and manipulated using JavaScript, providing an additional layer of flexibility and dynamism. For instance, you can create user-customizable themes by modifying variables through JavaScript.
<button onclick="changeTheme()">Change Theme</button> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%20%20function%20changeTheme()%20%7B%0A%20%20%20%20let%20root%20%3D%20document.documentElement%3B%0A%20%20%20%20let%20currentHue%20%3D%20parseInt(root.style.getPropertyValue('--primary-hue'))%3B%0A%20%20%20%20let%20newHue%20%3D%20(currentHue%20%2B%2030)%20%25%20360%3B%0A%20%20%20%20root.style.setProperty('--primary-hue'%2C%20newHue)%3B%0A%20%20%7D%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
In the example above, clicking the “Change Theme” button will change the –primary-hue variable, effectively updating the primary color and its variations.
Wrapping Up
Variables have transformed the way we approach theming, responsiveness, and maintainability in our stylesheets. By following best practices such as global variable declaration, using fallback values, leveraging variables in media queries, working with calculated values, handling colors with HSL, and harnessing JavaScript interoperability, you’ll unlock their full potential.
With this newfound understanding, you can create more efficient, flexible, and dynamic stylesheets that adapt to different devices, user preferences, and themes with minimal effort.
Mastering CSS Border Style: A Comprehensive Guide
CSS Borders refers to the line outside the padding and inside the margin of the CSS Box Model. This line wraps around the padding and content in every HTML Element. That is both semantic and non-semantic elements.
Borderlines don’t have to be a solid straight line. We can apply different styles to it to change its looks and feel, as you will see as we learn more about it in this blog on CSS Borders.
Learn CSS Grid “The Easy Way”!
CSS Grid is a layout system for the web, allowing developers to create complex, responsive designs using rows and columns. Grid is used to make complex web design layouts more easily. In this article, we will explore the basics of CSS Grid with a step-by-step guide. Readers will discover how to create complex, responsive web designs using rows and columns with CSS Grid.
First things first, we have to make a div and give it a class of containers or anything you want.
CSS Basics: Visibility: Hidden vs. Display: None
visibility: hidden
and display: none
are two CSS properties that can be used to hide elements. While they may seem similar at first glance, there are some significant differences between them. In this article, we’ll explore these differences and provide some examples to illustrate their use.
The UX Designer Toolbox
Unlimited Downloads: 500,000+ Wireframe & UX Templates, UI Kits & Design Assets Starting at only $16.50 per month!
visibility: hidden
The visibility
property in CSS determines whether or not an element is visible on the web page. If set to hidden
, the element will be hidden from view, but it will still occupy space on the page. This means that any other elements that would normally be positioned after it will still be positioned as if the hidden element were still visible.
Here’s an example of how visibility: hidden
works:
<!DOCTYPE html> <html> <head> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20%20%20%23hidden-element%20%7B%0A%20%20%20%20%20%20%20%20visibility%3A%20hidden%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> </head> <body> <p>This is some text before the hidden element.</p> <div id="hidden-element"> <p>This element is hidden using visibility.</p> </div> <p>This is some text after the hidden element.</p> </body> </html>
In this example, the #hidden-element
is hidden using visibility: hidden
. Notice that the element still occupies space on the page, and the text after it is still positioned as if it were visible.
display: none
The display
property in CSS determines how an element is displayed on the web page. If set to none
, the element will be completely removed from the page and will not occupy any space. This means that any other elements that would normally be positioned after it will be repositioned as if the hidden element were not present.
Here’s an example of how display: none
works:
<!DOCTYPE html> <html> <head> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20%20%20%23hidden-element%20%7B%0A%20%20%20%20%20%20%20%20display%3A%20none%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> </head> <body> <p>This is some text before the hidden element.</p> <div id="hidden-element"> <p>This element is hidden using display.</p> </div> <p>This is some text after the hidden element.</p> </body> </html>
In this example, the #hidden-element
is hidden using display: none
. Notice that the element does not occupy any space on the page, and the text after it is repositioned as if the element were not present.
When to use visibility: hidden
vs. display: none
Now that we’ve seen how visibility: hidden
and display: none
work, it’s important to consider when to use one over the other.
Use visibility: hidden
when you want to hide an element from view but still want it to occupy space on the page. This can be useful when you want to reveal the element later or when you want to maintain the layout of the page.
Use display: none
when you want to completely remove an element from the page and don’t want it to occupy any space. This can be useful when you want to completely hide an element and don’t plan to reveal it later.
Practical Example of Using CSS Layer
Let’s say we are developing a component library.
Let’s say we are using React.
How To Use CSS To Maintain Aspect Ratio For Responsive Design
Maintaining the Aspect ratio of a div is a common requirement when creating responsive web designs. In this article, we’ll explore how to use CSS to maintain the Aspect ratio of a div as the window’s width changes.
To achieve this, we’ll use the padding hack. The padding hack is a technique that uses a percentage value for padding-top or padding-bottom to maintain the Aspect ratio of an element. The percentage value is calculated based on the width of the parent element. As the width of the parent element changes, the padding value will adjust to maintain the Aspect ratio of the child element.
Your Web Designer Toolbox
Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
Let’s start by creating a div element with a background color.
<div class="aspect-ratio"></div> <style> .aspect-ratio { background-color: #ccc; } </style>
To maintain the Aspect ratio of this div, we’ll set its padding-top
to a percentage value. The percentage value will be calculated based on the desired Aspect ratio of the div. For example, if we want the Aspect ratio to be 16:9, we’ll set the padding-top
to 56.25% (9/16 * 100).
.aspect-ratio { background-color: #ccc; padding-top: 56.25%; }
Now, as the width of the parent element changes, the padding value will adjust as desired.
Here’s an example that shows how to use the padding hack on a div with a background image.
<div class="aspect-ratio" style="background-image: url('image.jpg')"></div> <style> .aspect-ratio { background-position: center; background-repeat: no-repeat; background-size: cover; position: relative; } .aspect-ratio:before { content: ""; display: block; padding-top: 56.25%; } .aspect-ratio > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style>
In this example, we are again using the padding hack, and we’re also using a pseudo-element (:before
) to create the padding. We’re setting the position
of the parent element to relative and the position
of the child element to absolute
to position the child element inside the parent element. We’re also setting the width
and height
of the child element to 100% to fill the parent element.
In conclusion, the padding hack is a simple and effective technique for maintaining the Aspect ratio of a div as the window’s width changes. By using a percentage value for padding-top or padding-bottom, we can calculate the padding value based on the desired Aspect ratio of the div. This technique is widely used in responsive web design and can be used to create a variety of layouts and designs. Be sure to check out our library of CSS articles and tutorials while you’re here!
The Difference Between the :where() and :is() CSS Selectors
The CSS selectors :where()
and :is()
are two pseudo-classes that allow you to select elements based on their relationship with other elements. Although they sound similar, they are different in terms of functionality and syntax.
Your Web Designer Toolbox
Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
The :where()
pseudo-class was introduced as part of the CSS Selectors Level 4 specification and allows you to select elements based on the presence of other elements that match a specific condition. In other words, you can select elements based on the relationship between elements in a DOM tree. For example, you can use the :where()
selector to select a list item li
only if it is the first child of an unordered list ul
:
li:where(:first-child of ul) { background-color: yellow; }
On the other hand, the :is() pseudo-class is part of the CSS Selectors Level 3 specification and allows you to select an element if it is one of several different selectors. It is similar to the logical OR
operator, in CSS. For example, you can use the :is()
selector to select a p
element if it is either the first child of its parent or has a class of highlight
:
p:is(:first-child, .highlight) { background-color: yellow; }
It’s important to note that the :where()
selector has better browser support than the :is()
selector, and that the :is()
selector should not be used in conjunction with the :not()
pseudo-class.
A Guide to CSS Color Functions
Hey, there fellow developers! Today, we’re going to dive into the world of CSS color functions.
You might have used CSS to change the color of an element on a web page, but have you ever heard of CSS color functions? If not, tighten your seat belts because you’re about to learn something new and super useful!
Quick Tip: How To Disable Resizing of a Textarea in HTML or CSS
In this quick tip, we’re going to show you 2 different ways to disable the resizing of a textarea
, for those times when you don’t want the user to be able to control it in this manner. It’s a relatively quick process, with just some simple CSS using the resize
CSS property.
Your Designer Toolbox Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
HTML
The HTML textarea
element provides a resizable property by default. To disable it, you can use the CSS property resize: none
in the textarea
element. Here is an example:
<textarea style="resize: none;"></textarea>
CSS
You can also disable the resizable property of a textarea
by using CSS that is not inline. You can add a class to the textarea
element and then add the CSS property resize: none
to the class. Here is an example:
<textarea class="no-resize"></textarea> <style> .no-resize { resize: none; } </style>
Increase Site Performance With CSS Hardware Acceleration
Did you know that we can hardware-accelerate graphics-intensive CSS features by offloading them to the GPU (Graphics Processing Unit) for better rendering performance in the browser? Computers have graphics cards suitable for CSS hardware acceleration. Because of this, we can...
The post Increase Site Performance With CSS Hardware Acceleration appeared first on Treehouse Blog.
How To Build A Magazine Layout With CSS Grid Areas
In this article, I want to talk about the amazing possibilities of a CSS grid and how it allows for complex layouts that are closer to a print design. The design we’ll discuss is actually one I got to work on for a client (modified slightly to a demo case). It will cover two big use cases of a CSS grid:
- Having a static grid where we define the specified start and end points for each element;
- Using CSS grid template areas to reorder a simple HTML layout easily without updating the HTML.
As a bonus, we will also touch on object-fit
and aspect-ratio
, which come in handy as well.
Here you can see the design we will be implementing: desktop on the left and a cropped version for mobile on the right (imagine the mobile view to continue with sections 3 and 4). There is quite a lot going on here, and nothing really fits into neat rows and columns. The images are laid out on an uneven grid, sometimes even overlapping, and we have some narrow text and a numbering element that double as a design element.
Artisanal Image LayoutsLet us first look at the image grid elements inside each colored component. While we have four colored components, there are only two variants that get repeated. For easier comparison, I have cut the desktop version in half and put the two halves next to one another — this makes it easier to compare. As you can see, the first and third are the same, as are the second and fourth. If we compare just the first and second variants, they differ, but the basic building blocks are very similar (a full-sized background color, a big image block, a column with a number, and some text). Due to this, we can consider it the same component, just with two alternatives.
In the olden days, we would have had to do the image grid in Photoshop and then add it as one image to the page. Obviously, we could still do this, but that solution has never been particularly good for responsive websites, and using the picture element would work, but we would have to do several layouts in Photoshop and redo everything if we want to change a picture. We would need to do this every time this element gets added with different pictures.
But we wouldn’t be at this part in this article if there wasn’t an alternative! For a while now, it has been safe to use CSS grid, and it is able to solve this layout quite neatly with only a few lines of CSS.
CSS Grid allows us to define a formal grid definition — columns and rows — on the parent element and specify for the children where they should go within the grid. We also get the same justify and align capabilities that flex offers. This removes a lot of the need for wrapping div
s and also makes the CSS slimmer.
One thing to note: As a result, your graphical layout can be different from the document structure in HTML.
Screen readers will still rely on the HTML structure, though, so put the most important information first and try to keep everything in a sensible order.
Now let’s get to our images. What is it that we need at a minimum? A container for the images and the images themselves. And you know what? With CSS Grid, that is actually enough — say goodbye to five layers of wrapping div
s!
<div class="grid image-grid-3-m4">
<img class="image-0 " src="" />
<img class="image-1 " src="" />
<img class="image-2 " src="" />
<img class="image-3 " src="" />
</div>
A bit more on the markup. To make the styling easier, I added an index to each image (since we want to re-use them, it has to be a class, not an ID) and two classes on the surrounding div
, which we will use to define the base styling: a grid utility class and a second one used for identifying the variant. For the variant with three images on the left and a fourth on the right in desktop view, I spent some time thinking about how to best solve the fourth image’s problem: do we add it to the container with the other images and try and move it to the other side, or do we move it on mobile, and so on. In the end, I decided to add the fourth image in the container for the images but hide it on the desktop via CSS and have a separate div
in a second location with the same image for displaying in the desktop version. Using display:none
will also hide that version from screen readers.
Now that we have the basic HTML and our images in place, it is time to focus on the CSS. If you are completely new to a CSS grid, this helpful article goes into the full syntax and explains it in detail. Unfortunately, I cannot describe the full syntax in this article.
First off, we need to define our grid. Since I had a design to work with, I used a tool that allowed me to put lines on top of the image, position one line at each edge of the image, and see the pixel dimensions in between. It would have been great if the designer had already used a formal grid and told me about it, but unfortunately, that was not the case, so I used the proportionate dimensions as an approximation of what I should use in the grid. Basically, I asked myself what the smallest common divisible number was for each — with some wiggle room — and used that. (Welcome to math class.) My goal was to have the same size for all grid columns and rows while being flexible on the number of columns or rows.
With this method, I determined that I wanted to have 14 columns on mobile and 7 rows plus some uniform gaps. This allowed me to approximate the distribution in the layout while keeping the Aspect ratios close to what they had envisioned. Based on that, we get the following CSS:
.grid {
display: grid;
}
.image-grid-3-m4 {
grid-template-rows: repeat(7, 1fr);
grid-template-columns: repeat(14, 1fr);
gap: 0.5rem;
}
With these four lines of CSS, we have a grid that is ready to be filled. If you follow along, you will notice that the images are now filling one grid cell each in the first row. This is the automatic layout mechanism that the browser uses, and depending on what you want to do, it can be ideal for defining an evenly laid-out design in seconds.
What is the minimum HTML for that? Again we do not need a lot of extras; a surrounding div
and then one for each part is all that we need:
<div class="container">
<div class="images"></div>
<div class="numbering"></div>
<div class="text"></div>
<div class="single-image"></div>
</div>
For our example, all areas have a class name that identifies what they will hold later. If we look at the mobile layout, though, the number is on top of the images! The cool thing about a CSS grid is that you can layer elements. We already used that for the images above. As you can see, two of them overlap, and we can also do that for whole areas. The layering will be controlled by our old friend, the z-index. Same rules as always: the higher z-index wins and comes to the front.
With that in mind, let’s create two areas: one at the top with the images filling the area and the number as a top layer with most of it transparent to show the images, and the second area below for the text. We could use the grid columns and rows syntax we used earlier, but in this case, we can make our lives even easier with grid-template-areas
. With this, you can add names to parts of your grid and then decide for each element which grid area it should appear in. Especially for the page or component frame, this is a much easier and faster way to work and be able to read it all again later than using all of the non-descript numbers.
I think this will be easier to understand with an example.
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(2, 1fr);
gap: 1.2rem;
grid-auto-flow: row;
grid-template-areas:
"numerology"
"text";
}
.images { grid-area: numerology; }
.numbering { grid-area: numerology; }
.text { grid-area: text; }
.single-image {display:none}
We define the container as a grid once again, add two rows to it, and then use ‘grid-template-areas’ to give these rows a name. The syntax for this is very unusual for CSS, but it gives you a mini-view of your layout: Numerology
is the name of the cell in the first row and Text
in the second.
With those rows now having names, we can easily position our elements. Both the images and the container for the number go into the first row, and the text will go to the second row. So in the example above, we add the grid-area
to the CSS for the class we applied to the div
in the HTML. With those few lines, we have defined the layout.
To achieve the overlay effect for the number, the white box will be in its container and gets a fixed width and height. We can then use flex
to center it in the container.
But how do we get from this to the desktop version, you may ask? Pretty easily, actually! For the overall design of the website, we are already using a 14-column grid on the desktop for all elements. If we overlay the design with some grid markers, we see the widths everything should take approximately.
Obviously, our named areas from the mobile view will not really help us for this version, but we can simply update them in a media query for our desktop view and also define different area names:
.container { display: grid;
grid-template-columns: repeat(14, minmax(0, 1fr));
grid-template-rows: repeat(2, 1fr);
gap: 1.2rem;
grid-auto-flow: row;
grid-template-areas:
"images images images images images . numbering numbering numbering single-image single-image single-image single-image single-image"
"images images images images images . text text text single-image single-image single-image single-image single-image";
}
.images { grid-area: images; }
.numbering { grid-area: numbering; }
.text { grid-area: text; }
.single-image { grid-area: single-image; }
Let me be the first one to say that, yes, this is really not a pretty way of defining this, but unfortunately, the template-areas
syntax does not include the repeat keyword as the column definition does.
But take a moment and have a closer look. What you can see is that we define the first five columns to belong to the images
name in both rows, then we have a period, which means nothing goes here, then we have three columns for the numbering
in row one and three for the text
in row two, and at the end, five columns for single-image
. Personally, I like to use an online generator that allows me to visually define these areas and copy the needed CSS.
Now with just under 20 lines of code, we have completely changed the layout without having touched the very simple HTML structure at all! But what about the alternative version for 2 and 4? They only use a slightly different layout, so why not add some classes for .version-a
and .version-b
on the container and have the grid-template-areas
defined by that on the desktop? It is that simple. Look at the following:
.version-1 {
grid-template-areas:
"images images images images images . numbering numbering numbering single-image single-image single-image single-image single-image"
"images images images images images . text text text single-image single-image single-image single-image single-image";
}
.version-1 .single-image {
grid-area: single-image;
display:block;
}
.version-2 {
grid-template-areas:
". numbering numbering numbering . . images images images images images images images images"
". text text text . . images images images images images images images images";
}
To me, this is still pretty crazy, to be honest. For the longest time, a layout like this would have been completely out of reach or very complicated to make and having shared HTML between versions 1 and 2 would have been near impossible, at least for the complete HTML. Now we can just wave a magic wand and update where it should show up. Pretty heady stuff.
Another practical example where this helped me a lot was defining areas for a product detail page on an e-commerce website. Being able to move elements around to where they make sense in different contexts is amazing, but it also means that you need to adjust your mental model a bit to how HTML and CSS are connected. And this is even just the beginning. With container queries and layers, there is much on the horizon that will open up a lot more possibilities in the future, and I am totally here for it!
Finally, here is the full version of the design with everything pulled together:
See the Pen Untitled [forked] by Pfenya.
Additionally, if you are curious about the final live webpage, it can be found here.
Quick Tip: How to Disable Text Selection Highlighting in CSS
There are two main CSS properties that control text selection highlighting: user-select
and -webkit-user-select
. These properties are used to specify whether or not users are able to select text on the web page.
UNLIMITED DOWNLOADS: Email, admin, landing page & website templates
Starting at only $16.50 per month!To disable text selection highlighting in CSS, you can set the value of the user-select
property to none
:
body { -webkit-user-select: none; /* for Safari */ -moz-user-select: none; /* for Firefox */ -ms-user-select: none; /* for Internet Explorer */ user-select: none; /* for modern browsers */ }
In this example, the user-select
property is applied to the body
element, which means that text selection highlighting will be disabled for the entire page. If you want to disable text selection highlighting for a specific element, simply apply the property to that element instead of the body
element.
It’s important to note that the -webkit-user-select
and -moz-user-select
properties are vendor-specific extensions, and are used to ensure compatibility with Safari and Firefox, respectively. The -ms-user-select
property is used for compatibility with Internet Explorer. The standard user-select
property should work in all modern browsers.
Subscribers: Update Your Feed URLs
To our feed subscribers. In case you haven’t heard. Feedburner is dead man walking. As a result, we changed our RSS and Atom feed URLs to host them directly at DigWP.com. So if you want to continue getting our awesome WP-related content delivered to your feed reader, take a moment to update your feed URLs. Our new (and permanent) feed URLs:
Visit the DigWP Archives for more feed options.