Preethi – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Thu, 08 Dec 2022 15:36:22 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.2 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 Preethi – CSS-Tricks https://css-tricks.com 32 32 45537868 Animated Background Stripes That Transition on Hover https://css-tricks.com/animated-background-stripes-transition-hover/ https://css-tricks.com/animated-background-stripes-transition-hover/#comments Thu, 08 Dec 2022 15:36:21 +0000 https://css-tricks.com/?p=375697 How often to do you reach for the CSS background-size property? If you’re like me — and probably lots of other front-end folks — then it’s usually when you background-size: cover an image to fill the space of an entire …


Animated Background Stripes That Transition on Hover originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
How often to do you reach for the CSS background-size property? If you’re like me — and probably lots of other front-end folks — then it’s usually when you background-size: cover an image to fill the space of an entire element.

Well, I was presented with an interesting challenge that required more advanced background sizing: background stripes that transition on hover. Check this out and hover it with your cursor:

There’s a lot more going on there than the size of the background, but that was the trick I needed to get the stripes to transition. I thought I’d show you how I arrived there, not only because I think it’s a really nice visual effect, but because it required me to get creative with gradients and blend modes that I think you might enjoy.

Let’s start with a very basic setup to keep things simple. I’m talking about a single <div> in the HTML that’s styled as a green square:

<div></div>
div {
  width: 500px;
  height: 500px;
  background: palegreen;
}
Perfect square with a pale green background color.

Setting up the background stripes

If your mind went straight to a CSS linear gradient when you saw those stripes, then we’re already on the same page. We can’t exactly do a repeating gradient in this case since we want the stripes to occupy uneven amounts of space and transition them, but we can create five stripes by chaining five backgrounds on top of our existing background color and placing them to the top-right of the container:

div {
  width: 500px;
  height: 500px;
  background: 
    linear-gradient(black, black) top right,
    linear-gradient(black, black) top 100px right,
    linear-gradient(black, black) top 200px right,
    linear-gradient(black, black) top 300px right,
    linear-gradient(black, black) top 400px right, 
    palegreen;
}

I made horizontal stripes, but we could also go vertical with the approach we’re covering here. And we can simplify this quite a bit with custom properties:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
}

So, the --gt value is the gradient and --n is a constant we’re using to nudge the stripes downward so they are offset vertically. And you may have noticed that I haven’t set a true gradient, but rather solid black stripes in the linear-gradient() function — that’s intentional and we’ll get to why I did that in a bit.

One more thing we ought to do before moving on is prevent our backgrounds from repeating; otherwise, they’ll tile and fill the entire space:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
  background-repeat: no-repeat;
}

We could have set background-repeat in the background shorthand, but I decided to break it out here to keep things easy to read.

Offsetting the stripes

We technically have stripes, but it’s pretty tough to tell because there’s no spacing between them and they cover the entire container. It’s more like we have a solid black square.

This is where we get to use the background-size property. We want to set both the height and the width of the stripes and the property supports a two-value syntax that allows us to do exactly that. And, we can chain those sizes by comma separating them the same way we did on background.

Let’s start simple by setting the widths first. Using the single-value syntax for background-size sets the width and defaults the height to auto. I’m using totally arbitrary values here, so set the values to what works best for your design:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
  background-repeat: no-repeat;
  background-size: 60%, 90%, 70%, 40%, 10%;
}

If you’re using the same values that I am, you’ll get this:

Doesn’t exactly look like we set the width for all the stripes, does it? That’s because of the auto height behavior of the single-value syntax. The second stripe is wider than the others below it, and it is covering them. We ought to set the heights so we can see our work. They should all be the same height and we can actually re-use our --n variable, again, to keep things simple:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
    background-repeat: no-repeat;
    background-size: 60% var(--n), 90% var(--n), 70% var(--n), 40% var(--n), 10% var(--n); // HIGHLIGHT 15
}

Ah, much better!

Adding gaps between the stripes

This is a totally optional step if your design doesn’t require gaps between the stripes, but mine did and it’s not overly complicated. We change the height of each stripe’s background-size a smidge, decreasing the value so they fall short of filling the full vertical space.

We can continue to use our --n variable, but subtract a small amount, say 5px, using calc() to get what we want.

background-size: 60% calc(var(--n) - 5px), 90% calc(var(--n) - 5px), 70% calc(var(--n) - 5px), 40% calc(var(--n) - 5px), 10% calc(var(--n) - 5px);

That’s a lot of repetition we can eliminate with another variable:

div {
  --h: calc(var(--n) - 5px);
  /* etc. */
  background-size: 60% var(--h), 90% var(--h), 70% var(--h), 40% var(--h), 10% var(--h);
}

Masking and blending

Now let’s swap the palegreen background color we’ve been using for visual purposes up to this point for white.

div {
  /* etc. */
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    #fff;
  /* etc. */
}

A black and white pattern like this is perfect for masking and blending. To do that, we’re first going to wrap our <div> in a new parent container and introduce a second <div> under it:

<section>
  <div></div>
  <div></div>
</section>

We’re going to do a little CSS re-factoring here. Now that we have a new parent container, we can pass the fixed width and height properties we were using on our <div> over there:

section {
  width: 500px;
  height: 500px;
} 

I’m also going to use CSS Grid to position the two <div> elements on top of one another. This is the same trick Temani Afif uses to create his super cool image galleries. The idea is that we place both divs over the full container using the grid-area property and align everything toward the center:

section {
  display: grid;
  align-items: center;
  justify-items: center;
  width: 500px;
  height: 500px;
} 

section > div {
  width: inherit;
  height: inherit;
  grid-area: 1 / 1;
}

Now, check this out. The reason I used a solid gradient that goes from black to black earlier is to set us up for masking and blending the two <div> layers. This isn’t true masking in the sense that we’re calling the mask property, but the contrast between the layers controls what colors are visible. The area covered by white will remain white, and the area covered by black leaks through. MDN’s documentation on blend modes has a nice explanation of how this works.

To get that working, I’ll apply the real gradient we want to see on the first <div> while applying the style rules from our initial <div> on the new one, using the :nth-child() pseudo-selector:

div:nth-child(1) { 
  background: linear-gradient(to right, red, orange); 
}

div:nth-child(2)  {
  --gt: linear-gradient(black, black);
  --n: 100px;
  --h: calc(var(--n) - 5px);
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    white;
  background-repeat: no-repeat;
  background-size: 60% var(--h), 90% var(--h), 70% var(--h), 40% var(--h), 10% var(--h);
}

If we stop here, we actually won’t see any visual difference from what we had before. That’s because we haven’t done the actual blending yet. So, let’s do that now using the screen blend mode:

div:nth-child(2)  {
  /* etc. */
  mix-blend-mode: screen;
}

I used a beige background color in the demo I showed at the beginning of this article. That slightly darker sort of off-white coloring allows a little color to bleed through the rest of the background:

The hover effect

The last piece of this puzzle is the hover effect that widens the stripes to full width. First, let’s write out our selector for it. We want this to happen when the parent container (<section> in our case) is hovered. When it’s hovered, we’ll change the background size of the stripes contained in the second <div>:

/* When <section> is hovered, change the second div's styles */
section:hover > div:nth-child(2){
  /* styles go here */
}

We’ll want to change the background-size of the stripes to the full width of the container while maintaining the same height:

section:hover > div:nth-child(2){
  background-size: 100% var(--h);
}

That “snaps” the background to full-width. If we add a little transition to this, then we see the stripes expand on hover:

section:hover > div:nth-child(2){
  background-size: 100% var(--h);
  transition: background-size 1s;
}

Here’s that final demo once again:

I only added text in there to show what it might look like to use this in a different context. If you do the same, then it’s worth making sure there’s enough contrast between the text color and the colors used in the gradient to comply with WCAG guidelines. And while we’re touching briefly on accessibility, it’s worth considering user preferences for reduced motion when it comes to the hover effect.

That’s a wrap!

Pretty neat, right? I certainly think so. What I like about this, too, is that it’s pretty maintainable and customizable. For example, we can alter the height, colors, and direction of the stripes by changing a few values. You might even variablize a few more things in there — like the colors and widths — to make it even more configurable.

I’m really interested if you would have approached this a different way. If so, please share in the comments! It’d be neat to see how many variations we can collect.


Animated Background Stripes That Transition on Hover originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/animated-background-stripes-transition-hover/feed/ 2 375697
How to Make a Folder “Slit” Effect With CSS https://css-tricks.com/how-to-make-a-folder-slit-effect-with-css/ https://css-tricks.com/how-to-make-a-folder-slit-effect-with-css/#comments Wed, 19 Oct 2022 12:56:37 +0000 https://css-tricks.com/?p=374376 When you put something — say a regular sheet of paper — in a manilla folder, a part of that thing might peek out of the folder a little bit. The same sort of thing with a wallet and credit …


How to Make a Folder “Slit” Effect With CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
When you put something — say a regular sheet of paper — in a manilla folder, a part of that thing might peek out of the folder a little bit. The same sort of thing with a wallet and credit cards. The cards poke out just a smidge so you can get a quick glance of which cards you’re carrying.

Credit: Stephen Phillips on Unsplash

I call this sort of thing a “slit”. A slit is where we create the illusion of an opening through which we can tease a visual element peeking out of it. And we can do that in CSS!

The crucial part of the design is the shadow, which is what gives the visual cue of there being a slit. Then there’s the cover for the slit which provides the space for the exhibited element to peek through from under.

Here’s what we’re going to make together:

Let’s begin with creating the shadow

You might be surprised that the shadow in the example is not created with an actual CSS shadow, like box-shadow or a drop-shadow() filter. Instead, the shadow is a separate element in itself, dark and blurred out. This is important in order to make the design more adaptable, both in its default and animated states.

The cover is the other element in the design. The cover is what I call the element that overlaps the shadow. Here’s a figure depicting how the shadow and cover come together.

The shadow is made from a small upright rectangle that has a gradient background. The gradient is darker in the middle. So when the element is blurred, it creates a shadow that’s darker in the middle; hence more dimensional.

Now, the left half of the recreated shadow is covered with a rectangle on top, colored exactly the same as the background of its container.

Both the cover and the shadow are then moved to the left ever so slightly so it appears to be layered

Working on the cover

For the cover to blend with the design’s background, its background color is inherited from its containing element. Alternatively, you can also try to blend the cover to its background using standards like CSS masks and blend modes, depending on your design choices and requirements.

To learn some basics on how these standards might be applied, you can refer to these articles: Sarah Drasner’s “Masking vs. Clipping: When to Use Each” provides an excellent primer on masks. I’ve also written about CSS blend modes in this article where you can brush up on the topic.

In the source code of my example, you’ll notice that I aligned and stacked the elements inside the <main> element using CSS Grid, which is a layout standard I often use in my demos. If you’re recreating a similar design, use a layout method that fits the best for your application to align the different parts of the design. In this case, I’ve set up a single-column grid on the <main> element which allows me to center align the cover, shadow, and image.

What CSS Grid also allows me to do is set all three of those divs so they are all full-width in the <main> container:

main > div {
  grid-area: 1 / 1;
}

This gets everything to stack on top of one another. Normally, we work hard to avoid covering elements with other elements in a grid. But this example relies on it. I’ve given the .slit-cover at width of 50% which naturally reveals the image underneath it. From there, I set a transform on it that moves it 50% in the negative direction, plus the small amount I shifted the shadow earlier (25px) to make sure that is revealed as well.

.slit-cover {
  width: 50%;
  transform: translatex(calc(-50% - 25px));
  /* etc. */
}

And there we have it! A pretty natural-looking slit that mimics something peeking out of a folder, wallet, or whatever.

There are more ways to do this! For one, Flexbox can get elements to line up in a row and align in the center like this. There are lots of ways to get things side-by-side. And maybe you have a way to use the box-shadow property, drop-shadow() filter, or even SVG filters to get the same sort of shadow effect that really sells the illusion.

And you can totally riff on this to get your own look and feel. For example, try swapping the position of the shadow and image. Or play with the color combinations and change the blur() filter value. The shape of the cover and the shadow can also be tweaked — I bet you can create a curved shadow instead of a straight one and share it with us in the comments!


How to Make a Folder “Slit” Effect With CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-make-a-folder-slit-effect-with-css/feed/ 2 374376
CSS Checkerboard Background… But With Rounded Corners and Hover Styles https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/ https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/#comments Tue, 20 Sep 2022 13:19:24 +0000 https://css-tricks.com/?p=373167 On one hand, creating simple checkered backgrounds with CSS is easy. On the other hand, though, unless we are one of the CSS-gradient-ninjas, we are kind of stuck with basic patterns.

At least that’s what I thought while staring at …


CSS Checkerboard Background… But With Rounded Corners and Hover Styles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
On one hand, creating simple checkered backgrounds with CSS is easy. On the other hand, though, unless we are one of the CSS-gradient-ninjas, we are kind of stuck with basic patterns.

At least that’s what I thought while staring at the checkered background on my screen and trying to round those corners of the squares just a little…until I remembered my favorite bullet point glyph — — and figured that if only I could place it over every intersection in the pattern, I’ll surely get the design I want.

Turns out it’s possible! Here’s the proof.

Let’s start with the basic pattern:

<div></div>
div {
 background: 
  repeating-linear-gradient(
    to right, transparent, 
    transparent 50px, 
    white 50px, 
    white 55px
  ),
  repeating-linear-gradient(
    to bottom, transparent,  
    transparent 50px, 
    white 50px, 
    white 55px
  ),
  linear-gradient(45deg, pink, skyblue);
  /* more styles */
}

What that gives us is a repeating background of squares that go from pink to blue with 5px white gaps between them. Each square is fifty pixels wide and transparent. This is created using repeating-linear-gradient, which creates a linear gradient image where the gradient repeats throughout the containing area.

In other words, the first gradient in that sequence creates white horizontal stripes and the second gradient creates white vertical stripes. Layered together, they form the checkered pattern, and the third gradient fills in the rest of the space.

Now we add the star glyph I mentioned earlier, on top of the background pattern. We can do that by including it on the same background property as the gradients while using an encoded SVG for the shape:

div {
  background: 
    repeat left -17px top -22px/55px 55px
    url("data:image/svg+xml,
    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
      <foreignObject width='35px' height='35px'>
        <div xmlns='http://www.w3.org/1999/xhtml' style='color: white; font-size: 35px'>✦</div>
      </foreignObject>
    </svg>"
    ), 
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    linear-gradient(45deg, pink, skyblue);
  /* more style */
}

Let’s break that down. The first keyword, repeat, denotes that this is a repeating background image. Followed by that is the position and size of each repeating unit, respectively (left -17px top -22px/55px 55px). This offset position is based on the glyph and pattern’s size. You’ll see below how the glyph size is given. The offset is added to re-position the repeating glyph exactly over each intersection in the checkered pattern.

The SVG has an HTML <div> carrying the glyph. Notice that I declared a font-size on it. That ultimately determines the border radius of the squares in the checkerboard pattern — the bigger the glyph, the more rounded the squares. The unrolled SVG from the data URL looks like this:

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
  <foreignObject width='35px' height='35px'>
    <div xmlns='http://www.w3.org/1999/xhtml' style='color:white;font-size:35px'>✦</div>
  </foreignObject>
</svg>

Now that a CSS pattern is established, let’s add a :hover effect where the glyph is removed and the white lines are made slightly translucent by using rgb() color values with alpha transparency.

div:hover {
  background:
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      rgb(255 255 255 / 0.5) 50px,
      rgb(255 255 255 / 0.5) 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      rgb(255 255 255 / 0.5) 50px,
      rgb(255 255 255 / 0.5) 55px
    ),
  linear-gradient(45deg, pink, skyblue);
  box-shadow: 10px 10px 20px pink;
}

There we go! Now, not only do we have our rounded corners, but we also have more control control over the pattern for effects like this:

Again, this whole exercise was an attempt to get a grid of squares in a checkerboard pattern that supports rounded corners, a background gradient that serves as an overlay across the pattern, and interactive styles. I think this accomplishes the task quite well, but I’m also interested in how you might’ve approached it. Let me know in the comments!


CSS Checkerboard Background… But With Rounded Corners and Hover Styles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/feed/ 4 373167
Why (and How) I Write Code With Pencil and Paper https://css-tricks.com/why-and-how-i-write-code-with-pencil-and-paper/ https://css-tricks.com/why-and-how-i-write-code-with-pencil-and-paper/#comments Wed, 17 Aug 2022 13:21:17 +0000 https://css-tricks.com/?p=367045 If the thought of handwriting code seems silly, it might surprise you to know that it’s inevitable. If you’re unsure, think about the last job interview you did, and remember how there was no computer around in the interview room …


Why (and How) I Write Code With Pencil and Paper originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
If the thought of handwriting code seems silly, it might surprise you to know that it’s inevitable. If you’re unsure, think about the last job interview you did, and remember how there was no computer around in the interview room — just your interviewers, a blank sheet of paper, and a blue ball-point pen.

For the students among you, it’s even a bigger deal as your grades hang in by the lines of code you had strategically squeezed into the available space in your answer sheet.

And not just that, experienced programmers can point you to the bundle of A4 sheets they had removed from the office copy machine to scribble down a particularly complex algorithm they had been working on.

So whether you’re an exam student, potential job interviewee, or someone wanting to resolve their programming dead ends, I hope this article helps you out when you put your pen to the paper to code.

Although I will focus on the analog aspect of writing code, you can apply these steps to coding in any form or language. So consider this to be also like a generic coding guideline that works specifically for me but can also be very useful to you in your work.

Why write it down?

Before we start, it’s essential to understand that no one expects you to jot down production-ready code in a notebook. It’s not like you can drop that into a code editor and compile it without an error. If producing perfect code was the goal, you would be seated in front of a computer in the interview rooms and exam halls.

The purpose of handwriting code is to work through logic in advance. There’s s desire to “get in the browser” as soon as possible in design, but there is conventional wisdom in sketching designs by hand. A low-fidelity medium encourages quick experimentation and inexpensive mistakes.

White lined paper with cursive handwritten notes on using :nth-child.
The toil of trying to figure out how to affect surrounding items with one click (from my last article)

The same can be true of code, mainly when working out syntax and semantics. That said, getting the correct syntax and semantics is always a plus point, though not the sole focus of the whole handwriting exercise.

Let’s see where we can start when it comes to handwriting code.

Know your question

During my final year in college, I couldn’t do an internship or even attend campus interviews because of health reasons. As a result, my very first job interview was quite literal with high stakes.

When I look back now, the interview was pretty easy. But having never attended one before, I was anxious beyond reason. The first thing the interviewers asked about programming was if I could output an inverted triangle made of asterisks. As I said, it was easy — nothing a for loop can’t handle, right? But like I said, my anxiety was through the roof as well.

I took a deep breath, pressed my palm against the blank sheet of paper they had laid out for me, slid it as slow as possible towards me on the table (buying time, of course), clicked the pen, and then I did something right.

I first drew an inverted triangle made of asterisks. That’s how I found my feet on the ground to start answering their question.

I’ve seen otherwise brilliant developers get something wrong simply because they never fully grasp what it is they are solving.

The questions we work with are not like the questions physicists or mathematicians solve. They get a set of parameters and find the missing ones; our questions are also our results. We are already told what our results are — we have to figure out how to reach them. That’s why it’s imperative to know the question well because you’ll see the result.

Writing down or drawing out what you want to output is one of the best ways to start your coding. I understand that in our fast-paced industry, the expectation is that we have to jump right into the programming by running a “hello world” demo. And that’s great to familiarize yourself with an unfamiliar syntax and shake off your anxiousness about trying something new.

But when someone asks you a question and gives you a result to work up to, wouldn’t it just be better to put that down first? That question/result is not only your starting point but also your point of reference. At any step in your coding, you can look at it to ensure you’re working towards it and that you’re on the right track.

So whether in your answer sheets or in that blank A4 paper you’re about to write in, start by taking a second and writing down what it is you’re trying to output. You can put it in the margins or a corner if you don’t want it to be a part of your answer. Just make sure it’s somewhere where you can keep referencing it.

Outline your code

This step is like a double-edged sword. It can get you a roadmap to your program or waste your time. My job is to make sure it’s the former.

So, first and foremost, I like to say: outlining code is unnecessary if the scope of your problem or question is small. Again, this practice is neither prescriptive nor universal to all projects or situations. Imagine I’m your interviewer, and I ask you to write how to center an element in a web page using CSS in as many ways as possible. You won’t exactly be needing an outline for this. The code snippets are relatively small for each method.

But now, let’s say I assign you to write a web application that captures user signatures via a touchscreen interface and then saves the signature on the server. Not so straightforward, right? You’ve more than one thing to figure out. Perhaps, a little outline can help.

  1. UI for capturing signature — HTML Canvas? WebGL?
  2. Disable pointer events on the rest of the web page when the user is signing
  3. Convert and save the captured image to a PNG file — JS
  4. Then convert it to blob (maybe) and save it to the visitor’s log data table.

I’ve written a rough sequence of actions I think I might have to code. It could’ve been shorter or longer, depending on what I wanted from it.

I highly recommend outlining code for client projects. Write the outline along with your user requirements or on the back of wireframes you’ve printed out.

Your quick snapshot of bullet points gives you a map, a to-do list, and a checklist to verify against when you reach the end of the project — pretty much your whole project’s summary in a low-fidelity list. It can also become a template to start your next similar project.

But like I said before, this step is like a double-edged sword. You’ll have to keep this short for examinees and interviewees when there are time constraints.

If you don’t know where to start, write down just three essential functions you’ll have to code in your application, and if you have got the time, make it five.

But that’s about it. Spend as little time as possible on this, and don’t sweat over the details. The outline is not going to score you extra points. It’s there only to help you make sure you have everything covered. It captures your initial gut reaction and keeps you honest throughout the project’s life.

Longhand vs. shorthand

White lined paper with cursive handwritten notes in black ink.
A quick reference to disable text selection

Time to start coding. So, what do you write? “Bdrs” or “border-radius“; “div -> p” or “<div><p></div></p>“; “pl()” or “println()“; “q()” or “querySelector()“?

If someone else is grading your code, then there’s no choice. Leave out abbreviations, pseudo-codes, Emmet shortcuts, and any other form of shorthand writing. Otherwise, there’s no reason to assume that anyone reading this knows what your abbreviations mean.

It’s really up to you.

If you’ve gotten out of touch with writing by hand — and many of us have — it’s better not to go overboard with the longhand notations, as they get tedious. At the same time, there’s no such thing as being too frugal with your writing. Not if you want to be able to look back on it one day and understand what you’d written down.

I have an open file in my note-taking app and a lined notepad on my desk where I write down code snippets I want to save for later reference. They are unorganized, just a long stream of snippets. That’s why when I browse through older notes, I wouldn’t know what I meant to write if I had not written them down clearly.

I forget syntaxes all the time. For instance, I’ve been using the arrow notation for JavaScript functions since it was introduced (because it’s shorter), and I’m pretty sure if someone suddenly asks me to define a function using the function keyword, I might even misplace the parentheses or the function name, inciting a syntax error.

It’s not unusual for us to forget syntaxes we haven’t used in a while. That’s why it’s better to write your notes clearly when you know you need them for future reference.

The non-sequential flow of code

Unlike the last step, which doesn’t apply to those of you interviewees and test-takers, this one is catered especially to you.

Most programming languages are interpreted, compiled, and executed so that sometimes pre-written code in the source is executed later when called. We do it in JavaScript, for example, with function calling — functions can be defined initially, then executed later. Examinees and interviewees can use this to start working on the critical point of your answer first.

As I’ve said from the very beginning, the purpose of handwriting code is to work through or test the logic of whatever it is you program. It’s best when you focus on resolving that first.

Let’s take a classic textbook example — a program to find the nth Fibonacci number. If I were to write a simple outline for it, it would be something like this:

  1. Get the input.
  2. Calculate the Fibonacci number.
  3. Summarise the output.
  4. Print the output.

All the steps in that outline are essential; however, 1, 3, and 4 are more obligatory. They are necessary but not important enough to focus on right away.

It’s better to start writing down the code to calculate the Fibonacci number rather than to fetch the input. Wrap it in a function, then go ahead and write the code sequentially and write down a line to call that function where appropriate.

Spend your time writing code that focuses on the heart of the problem.

Real professionals can skip ahead. Let’s say I have a client project, and I have to work with some triangle geometry — got two sides, opposite angle, and gotta find the third side’s length. And I’ve decided to scribble on paper to get started rather than opening my IDE.

First, I would draw the triangle, of course (that’s something I’m very experienced with, as you can tell). I would write down some sample lengths and angles. Then I’d write the formula (compliments of online searching, for sure), and then I’d jump right to the code for the function.

There’s no point in me writing down the obligatory steps even though I’ll need them in production-ready code. But it would be different if I had to write that on an answer sheet in an exam. I can’t skip the other steps; however, I can still start with the code for the formula.

Pseudo-code

Chris has already written a handy article on pseudo-code that I highly recommend you give a solid read.

For all those professionals who feel like the whole handwriting code thing doesn’t seem like your cup of tea but still might be curious if it can help you, then pseudo-code might be the balance you’re looking for.

It’s similar to outlining the code, as I mentioned in one of the previous steps. However, it’s briefer and feels more like shorthand coding. It’s sometimes also referred to as “skeleton code.”

Here’s some quick pseudo-code for a CSS grid layout:

Grid
5 60px rows
6 100px columns

There isn’t much to write! So, even though putting a pencil to paper is excellent for this sort of thing, it’s just as effective, fast, and inexpensive to jot some pseudo code into whatever program you’re using.

Space and comments

I believe code is 90% keywords and 10% tabs. Withoutspacesthereadabilityofwordsdecreases. Indentations are necessary for handwritten code as well. However, please don’t use it for every level because the width of the paper will limit you. Use spaces judiciously, but use them.

Yellow unlined paper with code handwritten in cursive in black ink.
Prized OG snippet, written with extra TLC

If you’re writing code for your use, I also believe that if you’ve followed everything I’ve mentioned so far and have already written down your output and an outline on the page, you may not even need to include comments. Comments tell you quickly what its following set of code does. If you have already written and read an outline for the code, then comments are redundant notes.

However, if your judgment says to put down one, then do it. Add it to the right side of the code (since you won’t be able to insert it between already written lines the way you could in, say, VS Code). Use forward slashes, brackets, or arrows to denote that they are comments.

For examinees who are unconfident with a certain syntax, write down comments. This way, at least, you’re letting the person grading your paper know your intention with that incorrectly formatted code. And use only the correct delimiters to denote comments — for example, that would be the forward slashes for JavaScript.

Analog vs. digital

As I mentioned earlier, everything I’m providing here can is generic coding advice. If you don’t want to try this with physical paper, any note-taking application also works.

But if you’re going to try the digital route, my recommendation is to try using something other than a straight note-taking app. Work with more visual digital tools — flow diagrams, mind maps, wireframes, etc. They can help you visualize your result, the outlines, and the code itself.

I am not much of a digital citizen (except for working on the web and recently converting to reading e-books), so I stick to physical notebooks.

My favorite tools for handwriting code

Any pencil and paper will do! But there are lots of options out there, and these are a few choice tools I use:

There is no “write” way to code

I hope, if nothing else, my little way of handwriting code with pencil and paper makes you evaluate the way you already plan and write code. I like knowing how other developers approach their work, and this is my way of giving you a peek into the way I do things.

Again, nothing here is scientific or an exact art. But if you want to give handwritten code planning a try, here’s everything we’ve covered in a nice ordered list:

  1. Start by writing down (with sample data, if needed) the output of your code.
  2. Write an outline for the code. Please keep it to three steps for small projects or ones that are less complex.
  3. Use longhand notations. Developers writing for themselves can use shorthand notations as long as the writing is legible and makes sense to you when you refer to it later.
  4. When under a time constraint, consider writing the code that tackles the heart of the problem first. Later, write down a call to that code at the right place in your sequential code.
  5. If you feel confident, try writing pseudo code addressing the main idea.
  6. Use proper indentations and spaces — and be mindful of the paper’s width.

That’s it! When you’re ready to try writing code by hand, I hope this article makes it easy for you to start. And if you’re sitting down for an exam or an interview, I hope this helps you focus on getting the questions right.


Why (and How) I Write Code With Pencil and Paper originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/why-and-how-i-write-code-with-pencil-and-paper/feed/ 8 367045
Conditionally Styling Selected Elements in a Grid Container https://css-tricks.com/conditionally-styling-selected-elements-in-a-grid-container/ https://css-tricks.com/conditionally-styling-selected-elements-in-a-grid-container/#comments Wed, 15 Jun 2022 14:15:50 +0000 https://css-tricks.com/?p=366252 Calendars, shopping carts, galleries, file explorers, and online libraries are some situations where selectable items are shown in grids (i.e. square lattices). You know, even those security checks that ask you to select all images with crosswalks or whatever.

🧐…


Conditionally Styling Selected Elements in a Grid Container originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Calendars, shopping carts, galleries, file explorers, and online libraries are some situations where selectable items are shown in grids (i.e. square lattices). You know, even those security checks that ask you to select all images with crosswalks or whatever.

🧐

I found a neat way to display selectable options in a grid. No, not recreating that reCAPTCHA, but simply being able to select multiple items. And when two or more adjoining items are selected, we can use clever :nth-of-type combinators, pseudo elements, and the :checked pseudo-class to style them in a way where they look grouped together.

The whole idea of combinators and pseudos to get the rounded checkboxes came from a previous article I wrote. It was a simple single-column design:

This time, however, the rounding effect is applied to elements along both the vertical and horizontal axes on a grid. You don’t have to have read my last article on checkbox styling for this since I’m going to cover everything you need to know here. But if you’re interested in a slimmed down take on what we’re doing in this article, then that one is worth checking out.

Before we start…

It’ll be useful for you to take note of a few things. For example, I’m using static HTML and CSS in my demo for the sake of simplicity. Depending on your application you might have to generate the grid and the items in it dynamically. I’m leaving out practical checks for accessibility in order to focus on the effect, but you would definitely want to consider that sort of thing in a production environment.

Also, I’m using CSS Grid for the layout. I’d recommend the same but, of course, it’s only a personal preference and your mileage may vary. For me, using grid allows me to easily use sibling-selectors to target an item’s ::before and ::after pseudos.

Hence, whatever layout standard you might want to use in your application, make sure the pseudos can still be targeted in CSS and ensure the layout stays in tact across different browsers and screens.

Let’s get started now

As you may have noticed in the earlier demo, checking and unchecking a checkbox element modifies the design of the boxes, depending on the selection state of the other checkboxes around it. This is possible because I styled each box using the pseudo-elements of its adjacent elements instead of its own element.

The following figure shows how the ::before pseudo-elements of boxes in each column (except the first column) overlap the boxes to their left, and how the ::after pseudo-elements of boxes in each row (except the first row) overlap the boxes above.

Two grids of checkboxes showing the placement of before and after pseudos.

Here’s the base code

The markup is pretty straightforward:

<main>
  <input type=checkbox> 
  <input type=checkbox> 
  <input type=checkbox>
  <!-- more boxes -->
</main>

There’s a little more going on in the initial CSS. But, first, the grid itself:

/* The grid */
main {
  display: grid;
  grid:  repeat(5, 60px) / repeat(4, 85px);
  align-items: center;
  justify-items: center;
  margin: 0;
}

That’s a grid of five rows and four columns that contain checkboxes. I decided to wipe out the default appearance of the checkboxes, then give them my own light gray background and super rounded borders:

/* all checkboxes */
input {
  -webkit-appearance: none;
  appearance: none;
  background: #ddd;
  border-radius: 20px;
  cursor: pointer;
  display: grid;
  height: 40px;
  width: 60px;
  margin: 0;
}

Notice, too, that the checkboxes themselves are grids. That’s key for placing their ::before and ::after pseudo-elements. Speaking of which, let’s do that now:

/* pseudo-elements except for the first column and first row */
input:not(:nth-of-type(4n+1))::before,
input:nth-of-type(n+5)::after {
  content: '';        
  border-radius: 20px;
  grid-area: 1 / 1;
  pointer-events: none;
}

We’re only selecting the pseudo-elements of checkboxes that are not in the first column or the first row of the grid. input:not(:nth-of-type(4n+1)) starts at the first checkbox, then selects the ::before of every fourth item from there. But notice we’re saying :not(), so really what we’re doing is skipping the ::before pseudo-element of every fourth checkbox, starting at the first. Then we’re applying styles to the ::after pseudo of every checkbox from the fifth one.

Now we can style both the ::before and ::after pseudos for each checkbox that is not in the first column or row of the grid, so that they are moved left or up, respectively, hiding them by default.

/* pseudo-elements other than the first column */
input:not(:nth-of-type(4n+1))::before { 
  transform: translatex(-85px);
}

/* pseudo-elements other than the first row */
input:nth-of-type(n+5)::after {
 transform: translatey(-60px); 
}

Styling the :checked state

Now comes styling the checkboxes when they are in a :checked state. First, let’s give them a color, say a limegreen background:

input:checked { background: limegreen; }

A checked box should be able to re-style all of its adjacent checked boxes. In other words, if we select the eleventh checkbox in the grid, we should also be able to style the boxes surrounding it at the top, bottom, left, and right.

A four-by-five grid of squares numbered one through 20. 11 is selected and 7, 10, 12, and 15 are highlighted.

This is done by targeting the correct pseudo-elements. How do we do that? Well, it depends on the actual number of columns in the grid. Here’s the CSS if two adjacent boxes are checked in a 5⨉4 grid:

/* a checked box's right borders (if the element to its right is checked) */
input:not(:nth-of-type(4n)):checked + input:checked::before { 
  border-top-right-radius: 0; 
  border-bottom-right-radius: 0; 
  background: limegreen;
}
/* a checked box's bottom borders (if the element below is checked) */
input:nth-last-of-type(n+5):checked + * + * + * + input:checked::after {
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
  background: limegreen;
}
/* a checked box's adjacent (right side) checked box's left borders */
input:not(:nth-of-type(4n)):checked + input:checked + input::before {         
  border-top-left-radius: 0; 
  border-bottom-left-radius: 0; 
  background: limegreen;
}
/* a checked box's adjacent (below) checked box's top borders */
input:not(:nth-of-type(4n)):checked + * + * + * +  input:checked + input::before { 
  border-top-left-radius: 0; 
  border-top-right-radius: 0; 
  background: limegreen;
}

If you prefer you can generate the above code dynamically. However, a typical grid, say an image gallery, the number of columns will be small and likely a fixed number of items, whereas the rows might keep increasing. Especially if designed for mobile screens. That’s why this approach is still an efficient way to go. If for some reason your application happens to have limited rows and expanding columns, then consider rotating the grid sideways because, with a stream of items, CSS Grid arranges them left-to-right and top-to-bottom (i.e. row by row).

We also need to add styling for the last checkboxes in the grid — they’re not all covered by pseudo-elements as they are the last items in each axis.

/* a checked box's (in last column) left borders */
input:nth-of-type(4n-1):checked + input:checked {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
/* a checked box's (in last column) adjacent (below) checked box's top borders */
input:nth-of-type(4n):checked + * + * + * + input:checked {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

Those are some tricky selectors! The first one…

input:nth-of-type(4n-1):checked + input:checked

…is basically saying this:

A checked <input> element next to a checked <input> in the second last column.

And the nth-of-type is calculated like this:

4(0) - 1 = no match
4(1) - 1 = 3rd item
4(2) - 1 = 7th item
4(3) - 1 = 11th item
etc.

So, we’re starting at the third checkbox and selecting every fourth one from there. And if a checkbox in that sequence is checked, then we style the checkboxes adjacent, too, if they are also checked.

And this line:

input:nth-of-type(4n):checked + * + * + * + input:checked

Is saying this:

An <input> element provided that is checked, is directly adjacent to an element, which is directly adjacent to another element, which is also directly adjacent to another element, which, in turn, is directly adjacent to an <input> element that is in a checked state.

What that means is we’re selecting every fourth checkbox that is checked. And if a checkbox in that sequence is checked, then we style the next fourth checkbox from that checkbox if it, too, is checked.

Putting it to use

What we just looked at is the general principle and logic behind the design. Again, how useful it is in your application will depend on the grid design.

I used rounded borders, but you can try other shapes or even experiment with background effects (Temani has you covered for ideas). Now that you know how the formula works, the rest is totally up to your imagination.

Here’s an instance of how it might look in a simple calendar:

Again, this is merely a rough prototype using static markup. And, there would be lots and lots of accessibility considerations to consider in a calendar feature.


That’s a wrap! Pretty neat, right? I mean, there’s nothing exactly “new” about what’s happening. But it’s a good example of selecting things in CSS. If we have a handle on more advanced selecting techniques that use combinators and pseudos, then our styling powers can reach far beyond the styling one item — as we saw, we can conditionally style items based on the state of another element.


Conditionally Styling Selected Elements in a Grid Container originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/conditionally-styling-selected-elements-in-a-grid-container/feed/ 3 366252
Creating Realistic Reflections With CSS https://css-tricks.com/creating-realistic-reflections-with-css/ https://css-tricks.com/creating-realistic-reflections-with-css/#comments Mon, 02 May 2022 14:14:07 +0000 https://css-tricks.com/?p=365491 In design, reflections are stylized mirror images of objects. Even though they are not as popular as shadows, they have their moments — just think about the first time you explored the different font formats in MS Word or PowerPoint: …


Creating Realistic Reflections With CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
In design, reflections are stylized mirror images of objects. Even though they are not as popular as shadows, they have their moments — just think about the first time you explored the different font formats in MS Word or PowerPoint: I bet reflection was your second-most-used style, next to shadow, foregoing others like outline and glow. Or perhaps you remember when reflections were all the rage back when Apple used them on just about everything.

Old iPod Touch product image showing the front, back, and profile of the device with subtle reflections beneath each.

Reflections are still cool! And unlike years past, we can actually make reflections with CSS! Here’s what we’ll be making in this article:

There are two steps to a reflection design:

  1. Create a copy of the original design.
  2. Style that copy.

The most authentic and standardized way to get a mirror image in CSS now would be to use the element() property. But it’s still in its experimental phase and is only supported in Firefox, at the time of writing this article. If you’re curious, you can check out this article I wrote that experiments with it.

So, rather than element(), I’m going to add two of the same designs and use one as the reflection in my examples. You can code this part to be dynamic using JavaScript, or use pseudo-elements, but in my demos, I’m using a pair of identical elements per design.

<div class="units">
  <div>trinket</div>
  <div>trinket</div>
</div>
.units > * {
  background-image: url('image.jpeg');
  background-clip: text;
  color: transparent;
  /* etc. */
}

The original design is a knock-out text graphic created from the combination of a background image, transparent text color, and the background-clip property with its text value.

The bottom element of the pair is then turned upside-down and moved closer to the original design using transform. This is the reflection:

.units > :last-child {
  transform: rotatex(180deg) translatey(15px); 
}

The now upturned bottom element will take on some styles to create fades and other graphic effects on the reflection. A gradual fading of reflection can be achieved with a linear gradient image used as a mask layer on the upturned element.

.units > :last-child {
  transform: rotatex(180deg) translatey(15px); 
  mask-image: linear-gradient(transparent 50%, white 90%);
}

By default, the mask-mode of the mask-image property is alpha. That means the transparent parts of an image, when the image is used as a mask layer for an element, turn their corresponding areas of the element transparent as well. That’s why a linear-gradient with transparent gradation at the top fades out the upside-down reflection at the end.

We can also try other gradient styles, with or without combining them. Take this one with stripes, for example. I added the pattern along with the fade effect from before.

.units > :last-child {
  /* ... */
  mask-image: 
    repeating-linear-gradient(transparent, transparent 3px, white 3px, white 4px),
    linear-gradient( transparent 50%, white 90%);
}

Or this one with radial-gradient:

.units > :last-child {
  /* ... */
  mask-image: radial-gradient(circle at center, white, transparent 50%);
}

Another idea is to morph the mirror image by adding skew() to the transform property. This gives some movement to the reflection.

.units > :last-child {
  /* ... */
  transform: rotatex(180deg) translatey(15px) skew(135deg) translatex(30px);
}

When you need the reflection to be subtle and more like a shadow, then blurring it out, brightening it, or reducing its opacity, can do the trick.

.units > :last-child {
  /* ... */
  filter: blur(4px) brightness(1.5);
}

Sometimes a reflection can also be shadowy itself, so, instead of using the background image (from the original design) or a block color for the text, I tried giving the reflection a series of translucent shadows of red, blue and green colors that go well with the original design.

.units > :last-child {
  /* ... */
  text-shadow: 
    0 0 8px rgb(255 0 0 / .4),
    -2px -2px 6px rgb(0 255 0 / .4),
    2px 2px 4px rgb(0 255 255 / .4);
}

Do those rgb()values look weird? That’s a new syntax that’s part of some exciting new CSS color features.

Let’s bring all of these approaches together in one big demo:

Wrapping up

The key to a good reflection is to go with effects that are subtler than the main object, but not so subtle that it’s difficult to notice. Then there are other considerations, including the reflection’s color, direction, and shape.

I hope you got some inspirations from this! Sure, all we looked at here was text, but reflections can work well for any striking element in a design that has a sensible enough space around it and can benefit from a reflection to elevate itself on the page.


Creating Realistic Reflections With CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creating-realistic-reflections-with-css/feed/ 6 365491
A Serene CSS Dappled Light Effect https://css-tricks.com/css-dappled-light-effect/ https://css-tricks.com/css-dappled-light-effect/#comments Wed, 19 Jan 2022 22:46:39 +0000 https://css-tricks.com/?p=360899 There’s a serene warmth to the early evening sunlight peaking through rustling leaves. Artists use dappled light to create a soft, hypnotic effect.

Bedford Dwellings by Ron Donoughe (2013)

We can create the same sort of dappled light effect in …


A Serene CSS Dappled Light Effect originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There’s a serene warmth to the early evening sunlight peaking through rustling leaves. Artists use dappled light to create a soft, hypnotic effect.

An oil painting of a tall rectangular orange building with six windows, two by two, and a faint full-width fence in front of it. There is a similar building off in the distance. A tall birch tree is in the foreground with light green and yellow leaves, casting the dappled light effect that is being covered in this article. The shadows cover the green grass between the tree and building, and they extend to the building.
Bedford Dwellings by Ron Donoughe (2013)

We can create the same sort of dappled light effect in web design, using it on photos and illustrations to add that magic touch to what might otherwise be drab walls of content to bring them back to life.

I’ll give you one easy, quick way to add this effect… with just CSS.

Before we get into the code, it’s important to know the composition of dappled light. It’s made up of large spots — circular or elliptical — of light that are intercepted by the shadows cast by the foliage. Basically the light that slips past leaves, branches and so forth. Sometimes the shadows create crisp edges, but are more often blurred since we’re talking about light that passes though many, less defined spaces that diffuse and distort the light as it casts shadows from a further distance than, say, your own stark shadow on a nearby wall from direct sunlight.

Here’s the difference in the appearance of a white wall with and without lit by dappled light:

A side-by-side comparison of the same white brick surface, the left showing the CSS dappled light effect compared to no shadows.
The effect creates splashes of light and shadow.

I’m going to recreate the dappled light effect with both plain text and fun emojis, applying CSS shadows and blends to mimic nature. I’ll cover alternative methods too.

Setting the scene

We’ll use text — letters from the alphabet, special characters, emojis, etc. — to create the shapes of light. And by light, I mean pale, translucent colors. Again, we’re for a dappled light effect rather than something that’s sharp, crisp, or stark.

It’s best to choose characters that are elliptical or oblong in some way — the spots produced by dappled light comes in a variety of shapes. You’ll have to go with your best judgement here to get exactly what you’re going for. Me? I’m using 🍃, 🍂, \ because they are elliptical, oblong, and slanted — a bit of chaos and unpredictability for an otherwise serene effect.

I’m wrapping those in paragraphs that are contained in a .backdrop parent element:

<div class="backdrop">
  <p class="shapes">🍃</p>
  <p class="shapes">🍂</p>
  <p class="shapes">\</p>
</div>

I’m using the parent element as the surface where the dappled light and shadows are cast, applying a background image for its texture. And not only am I giving the surface an explicit width and height, but also setting hidden overflow on it so I’m able to cast shadows that go beyond the surface without revealing them. The objects that cast the dappled light effect are aligned in the middle of the backdrop’s surface, thanks to CSS grid:

.backdrop {
  background: center / cover no-repeat url('image.jpeg');
  width: 400px; height: 240px;
  overflow: hidden;
  display: grid;
}
.backdrop > * {
  grid-area: 1/1;
}

I find that it’s OK if the shapes aren’t aligned exactly on top of one another as long as they overlap in a way that gets the dappled light effect you want. So no pressure to do exactly what I’m doing here to position things in CSS. In fact, I encourage you to try playing with the values to get different patterns of dappled light!

Styling the dappled light in CSS

These are the key properties the emojis should have — transparent color, black semi-transparent background (using the alpha channel in rgba()), blurry white text-shadow with a nice large font-size, and finally, a mix-blend-mode to smooth things out.

.shapes {
  color:  transparent;
  background-color: rgba(0, 0, 0, 0.3); // Use alpha transparency
  text-shadow: 0 0 40px #fff; // Blurry white shadow
  font: bolder 320pt/320pt monospace;
  mix-blend-mode: multiply;
}

mix-blend-mode sets how an element’s colors blend with that of its container element’s content. The multiply value causes the backdrop of an element to show through the element’s light colors and keeps dark colors the same, making for a nicer and more natural dappled light effect.

Refining colors and contrast

I wanted the background-image on the backdrop to be a bit brighter, so I also added filter: brightness(1.6). Another way to do this is with background-blend-mode instead, where all the different backgrounds of an element are blended and, instead of adding the emojis as separate elements, we add them as background images.

Notice that I used a different emoji in that last example as well as floralwhite for some color that’s less intense than pure white for the light. Here’s one of the emoji background images unwrapped:

<svg xmlns='http://www.w3.org/2000/svg'> 
  <foreignObject width='400px' height='240px'> 
    <div xmlns='http://www.w3.org/1999/xhtml' style=
      'font: bolder 720pt/220pt monospace;
       color: transparent;
       text-shadow: 0 0 40px floralwhite;
       background: rgba(0, 0, 0, 0.3);'
    >
      🌾
    </div> 
  </foreignObject> 
</svg>

If you want to use your own images for the shapes, ensure the borders are blurred to create a soft light. The CSS blur() filter can be handy for the same sort of thing. I also used CSS @supports to adjust the shadow blur value for certain browsers as a fallback.

Now let’s circle back to the first example and add a few things:

<div class="backdrop">
  <p class="shapes">🍃</p>
  <p class="shapes">🍂</p>
  <p class="shapes">\</p>
</div>

<p class="content">
  <img width="70px" style="float: left; margin-right: 10px;" src="image.jpeg" alt="">
  Top ten tourists spots for the summer vacation <br><br><i style="font-weight: normal;">Here are the most popular places...</i>
</p>

.backdrop and .shapes are basically the same styles as before. As for the .content, which also sits on top of the .backdrop, I added isolation: isolate to form a new stacking context, excluding the element from the blending as a refining touch.

Animating the light source

I also decided to add a simple CSS animation with @keyframes that get applied to the .backdrop on :hover:

.backdrop:hover > .shapes:nth-of-type(1){
  animation: 2s ease-in-out infinite alternate move;
}
.backdrop:hover > .shapes:nth-of-type(2):hover{
  animation: 4s ease-in-out infinite alternate move-1;
}

@keyframes move {
  from {
    text-indent: -20px;
  }
  to {
    text-indent: 20px;
  }
}
@keyframes move-1 {
  from {
    text-indent: -60px;
  }
  to {
    text-indent: 40px;
  }
}

Animating the text-indent property on the emojis products a super subtle bit of movement — the kind you might expect from clouds moving overhead that change the direction of the light. Just a touch of class, you know.

Wrapping up

There we have it! We drew some inspiration from nature and art to mimic one of those partly cloudy days where the sun shines through trees and bushes, projecting dappled light and shadow spots against a surface. And we did all of it with a small handful of CSS and a few emoji.

The key was how we applied color on the emoji. Using an extra blurry text-shadow in a light color sets the light, and a semi-transparent background-color defines the shadow spots. From there, all we had to do was ensure the backdrop for the light and shadows used a realistic texture with enough contrast to see the dappled light effect in action.


A Serene CSS Dappled Light Effect originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-dappled-light-effect/feed/ 8 360899
Fun Times Styling Checkbox States https://css-tricks.com/fun-times-styling-checkbox-states/ https://css-tricks.com/fun-times-styling-checkbox-states/#comments Fri, 10 Sep 2021 14:53:24 +0000 https://css-tricks.com/?p=351034 We might leave a text input unstyled. We might leave a link unstyled. Even a button. But checkboxes… we don’t leave them alone. That’s why styling checkboxes never gets old.

Although designing checkboxes is not that complicated, we also don’t …


Fun Times Styling Checkbox States originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
We might leave a text input unstyled. We might leave a link unstyled. Even a button. But checkboxes… we don’t leave them alone. That’s why styling checkboxes never gets old.

Although designing checkboxes is not that complicated, we also don’t have to settle for simple background color changes, or adding and removing borders, to indicate state changes. We also don’t have to pull out any fancy design skills — that we don’t possess — to make this work. I’ll show you how.

Basics

In the following demos, the checkboxes pretty much have the same three-stack layout — at the bottom is a checkbox, and on top of it are two stacked elements, or pseudo-elements. The checkbox is indicated as checked or unchecked depending on which of the two is visible.

If you look at the CSS code in the pens you’ll notice all the layouts — including the one for the checkboxes — are grids. You can use other layouts that feel right for your use case (and learn more in the CSS-Tricks Grid Guide). Additional notes on code and design alternatives are at the end of the source code inside the pens.

In addition, any elements stacked on top of the checkbox have pointer-events: none so they don’t prevent users from clicking or tapping the checkbox.

Let’s now get to the first method.

Idea 1: Blended backgrounds as a state

Blending in CSS is a versatile technique. Manipulating colors relative to two or more elements or backgrounds can be handy in contexts you might not have thought of.

One such instance is the checkbox.

<input id="un" type="checkbox"> <label for="un">un</label>
<!-- more checkboxes --> 
input[type=checkbox]::before,
input[type=checkbox]::after {
  mix-blend-mode: hard-light;
  pointer-events: none;
  /* more style */
}
input[type=checkbox]::before {
  background: green;
  content: '✓';
  color: white;
  /* more style */
}
input[type=checkbox]::after {
  background: blue;
  content: '⨯';
  /* more style */
}
input[type=checkbox]:checked::after {
  mix-blend-mode: unset;
  color: transparent;
}

In this demo, I’ve styled the checkbox’s pseudo-elements green and blue, stacked them up, and gave them each a mix-blend-mode value. This means the background of each element blends with its backdrop.

I used the hard-light value, which emulates the result of either multiply or screen depending on if the top color is darker or lighter. You can learn in depth about different blend modes over at MDN.

When the box is checked, the ::after pseudo-element’s mix blend mode value is unset, resulting in a different visual.

Idea 2: Make a 3D animation

Animating a block of color is fun. Make them seem 3D and it’s even better. CSS has the means to render elements along an emulated 3D space. So using that, we make a 3D box and rotate it to indicate the checkbox state change.

<div class="c-checkbox">
  <input type="checkbox" id="un">
  <!-- cube design -->
  <div><i></i><i></i><i></i><i></i></div>
</div>
<label for="un">un</label>
<!-- more checkboxes -->
.c-checkbox > div {
  transition: transform .6s cubic-bezier(.8, .5, .2, 1.4);
  transform-style: preserve-3d;
  pointer-events: none;
  /* more style */
}
/* front face */
.c-checkbox > div > i:first-child {
  background: #ddd;
  transform:  translateZ( -10px );
}
/* back face */
.c-checkbox > div > i:last-child {
  background: blue;
  transform:  translateZ( 10px );
}
/* side faces */
.c-checkbox > div > i:nth-of-type(2),
.c-checkbox > div > i:nth-of-type(3) {
  transform: rotateX(90deg)rotateY(90deg);
  position: relative;
  height: 20px;
  top: 10px;
}
.c-checkbox > div > i:nth-of-type(2) {
  background: navy;
  right: 20px;
}
.c-checkbox > div > i:nth-of-type(3) {
  background: darkslategray;
  left: 20px;
}

The <div> after the checkbox becomes a container of a 3D space — its child elements can be placed along the x, y and z axes — after it’s given transform-style: preserve-3d;.

Using the transform property, we place two <i> elements (grey and blue colored) with some distance between them across the z-axis. Two more are wedged between them, covering their left and right sides. It’s like a cardboard box that’s covered except at the top and bottom.

When the checkbox is checked, this grey and blue box is rotated sideways to face the other side. Since I’ve already added a transition to the <div>, its rotation is animated.

input:checked + div { 
  transform: rotateY( 180deg ); 
}

Idea 3: Playing with border radius

Changing a checked box’s border radius? Not that fun. Changing also the border radius of other boxes near it? Now we have something.

<input type="checkbox" id="un"> <label for="un">un</label>
<!-- more rows of checkboxes -->
input {
  background: #ddd;
  border-radius: 20px;
  /* more style */
}
input:not(:first-of-type)::before {
  content: '';    
  transform: translateY(-60px); /* move up a row */
  pointer-events: none;
}
input:checked + * + input::before,
input:last-of-type:checked {
  border-radius: 20px;
  background: blue;
}
input:checked + * + input:checked + * + input::before {
  border-top-left-radius: unset !important;
  border-top-right-radius: unset !important;
}
input:checked::before {
  border-bottom-left-radius: unset !important;
  border-bottom-right-radius: unset !important;
}
/* between the second-last and last boxes */ 
input:nth-of-type(4):checked + * + input:checked {
  border-top-left-radius: unset;
  border-top-right-radius: unset;
}

If you’d just interacted with the demo before, you’ll notice that when you click or tap a checkbox, it not only can change its own borders but also the borders of the boxes after and before it.

Now, we don’t have selectors that can select elements prior, only the ones after. So what we did to control the appearance of a preceding box is use the pseudo-element of a checkbox to style the box before it. With exception of the first box, every other box gets a pseudo-element that’s moved to the top of the box before it.

Let’s say boxes A, B and C are one after another. If I click B, I can change the appearance of A by styling B’s pseudo-element, B by styling C’s pseudo-element, and C by styling D’s pseudo-element.

From B, the pseudo-elements of B, C and D are accessible — as long as the next element selector can be used between them in the layout.

The four corners of each checkbox are initially rounded when checked and unchecked. But if a box is checked, the following box’s top corners and preceding box’s bottom corners are straightened (by overriding and removing their border radii).

Idea 4: Using a CSS mask

Toggles, switches… they are also checkboxes as far as the code goes. So we can style the boxes as toggles for this one, and it’s done with a CSS mask, which Chris has written about before. But in a nutshell, it’s a technique where we use an image to filter out portions of its backdrop.

<input type="checkbox">
<div class="skin one"></div>
<div class="skin two"></div>
.one.skin {
  background: no-repeat center -40px url('photo-1584107662774-8d575e8f3550?w=350&q=100');
}
.two.skin {
  background: no-repeat center -110px url('photo-1531430550463-9658d67c492d?w=350&q=100');
  --mask: radial-gradient(circle at 45px 45px , rgba(0,0,0,0) 40px, rgba(0,0,0,1) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

Two skins (displaying landscape photos) are on top of a checkbox. The topmost one gets a mask-image that’s in the shape of a typical toggle switch — a transparent circle at the left, and the rest is a fully opaque color. Through the transparent circle we see the photo below while the rest of the mask image shows the photo at the top.

When a checkbox is clicked, the transparent circle is moved to the right, so we see the image at the top through the circle while the rest shows the photo at the bottom.

input:checked ~ .two.skin {
  --mask: radial-gradient(circle at 305px 45px, rgba(0,0,0,1) 40px, rgba(0,0,0,0) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

Idea 5: Using box shadow

Let’s end with the simplest — but what I consider to be the most effective — method of them all: an animated inset box-shadow.

<input id="un" type="checkbox"> <label for="un">un</label>
input {
  transition: box-shadow .3s;
  background: lightgrey;
  /* more style */
}
input:checked { 
  box-shadow: inset 0 0 0 20px blue;
}

There are some CSS properties that can be animated by default and one of them is box-shadow. This type of subtle animation goes well with a minimalist theme.


That’s it! I hope this sparks some inspiration the next time you find yourself working with checkboxes. CSS gives us so many possibilities to indicate state changes, so have a little fun and please share if you have any interesting ideas.


Fun Times Styling Checkbox States originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/fun-times-styling-checkbox-states/feed/ 3 351034
Using CSS Shapes for Interesting User Controls and Navigation https://css-tricks.com/using-css-shapes-for-interesting-user-controls-and-navigation/ https://css-tricks.com/using-css-shapes-for-interesting-user-controls-and-navigation/#comments Wed, 04 Aug 2021 14:13:45 +0000 https://css-tricks.com/?p=345274 Straight across or down, that’s the proverbial order for user controls on a screen. Like a list of menu items. But what if we change that to a more fluid layout with bends, curves, and nooks? We can pull it …


Using CSS Shapes for Interesting User Controls and Navigation originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Straight across or down, that’s the proverbial order for user controls on a screen. Like a list of menu items. But what if we change that to a more fluid layout with bends, curves, and nooks? We can pull it off with just a few lines of code. In the age of modern minimalistic designs, curved layouts for the user controls add just the right amount of pep to a web design.

And coding them couldn’t be more easier, thanks to CSS Shapes.

CSS Shapes (notably, the shape-outside property) is a standard that assigns geometric shapes to float elements. The content then wraps around the floated element along the boundaries of those shapes.

The use cases for this standard are usually showcased as designs for textual, editorial content — where plain text flow along the shapes floating at their sides. However, in this post, in place of just plain text, we use user controls to see how these shapes can breathe some fluid silhouettes into their layouts.

For the first demo, here’s a design that can be used in product pages, where any product-related action controls can be aligned along the shape of the product itself.

<form>
  <img src="./img/bottle.png" alt="A tall refreshing and unopened bottle of Coca-Cola, complete with red bottle cap and the classic Coke logo in white.">
    <div>
      <input type="radio" id="one" name="coke" checked>
      <label for="one">One Bottle</label>
    </div>
    <div>
      <input type="radio" id="six" name="coke">
      <label for="six">Six Pack</label>
    </div>
    <div>
      <input type="radio" id="twelve" name="coke">
      <label for="twelve">Twelve Pack</label>
    </div>
    <div>
      <input type="radio" id="crate" name="coke">
      <label for="crate">Entire Crate</label>
    </div>
  </form>
img {
  height: 600px;
  float: left;
  shape-outside: url("bottle.png");
  filter: brightness(1.5);
}
input {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  margin-left: 20px;
  box-sizing: content-box;
  border: 10px solid #231714;
  border-radius: 50%;
  background: linear-gradient(45deg, pink, beige);
  cursor: pointer;
}

The image of the bottle is floated left and given a shape boundary using the shape-outside property. The image itself is referenced for the shape.

Note: Only images with transparent backgrounds can produce shapes according to the silhouettes of the images.

The default style of the radio buttons is replaced with a custom style. Once the browser applies the shape to the floated image, the radio buttons automatically align themselves along the shape of the bottle.

Like this, we don’t have to bother with individually assigning positions for each radio button to create such a design. Any buttons later added will automatically be aligned with the buttons before them according to the shape of the bottle.

Here’s another example, inspired by the Wikipedia homepage. This is a perfect example of the sort of unconventional main menu layouts we’re looking at.

Screenshot of the Wikipedia home page, displaying the site logo above a world globe made out of puzzle pieces. Links to various languages float around the globe's edge, like English, Spanish, German, in blue. Each link has a light grey count of how many articles are available in each language.

It’s not too crazy to make with shape-outside:

<div>
  <img src="earth.png">
  <div class="left">
    <a href="#">Formation</a><br>
    <a href="#">Atmosphere</a><br>
    <a href="#">Heat</a><br>
    <a href="#">Gravitation</a>
  </div>
</div>
<div>
  <img src="earth.png">
  <div class="right">
    <a href="#">Moon</a><br>
    <a href="#">Climate</a><br>
    <a href="#">Rotation</a><br>
    <a href="#">Orbit</a>
  </div>
</div>
img {
  height: 250px;
  float: left;
  shape-outside: circle(40%);
}

/* stack both sets of menus on the same grid cell */
main > div { grid-area: 1/1; } 

/* one set of menus is flipped and moved sideways over the other */
.right { transform: rotatey(180deg) translatex(250px); }

/* links inside the flipped set of menus are rotated back */
.right > a { 
  display: inline-block; 
  transform: rotateY(180deg) translateX(-40px); 
}

/* hide one of the images */
main > div:nth-of-type(2) img { visibility: hidden; }

An element only ever floats left or right. There’s no center floating element where content wraps around both the sides. In order to achieve the design where links wrap on both the sides of the image, I made two sets of links and flipped one of the sets horizontally. I used the same image with a circle() CSS shape value in both the sets so the shapes match even after the rotation. The text of the links of the flipped set will appear upside down sideways, so it’s rotated back.

Although both the images can sit on top of each other with no visible overflow, it’s best to hide one of them with either opacity or visibility property.

The third example is a bit lively thanks to the use of one of the dynamic HTML elements, <details>. This demo is a good example for designs to show extra information on products and such which by default are hidden to the users.

<img src="diamond.png">
<details>
  <summary>Click to know more!</summary>
  <ul>
    <li>The diamond is now known as the Sancy
    <li>It comprises two back-to-back crowns
    <li>It's likely of Indian origin
  </ul>
</details>
img {
  height: 200px;
  float: left;
  shape-outside: url("diamond.png");
  shape-margin: 20px;
}
summary {
  background: red;
  color: white;
  cursor: pointer;
  font-weight: bold;
  width: 80%; 
  height: 30px;
  line-height: 30px;
}

The image is floated left and is given a CSS shape that’s same as the image. The shape-margin property adds margin space around the shape assigned to the floated element. When the <summary> element is clicked, the parent <details> element reveals its content that automatically wraps along the shape of the floated diamond image.

The content of the <details> element doesn’t necessarily have to be a list, like in the demo. Any inline content would wrap along the floated image’s shape.

The final example works with a polygon shape instead of images or simple shapes like circle and ellipse. Polygons give us more angular geometric shapes that can easily be bent by adding just another coordinate in the shape.

<img src="nasa.png">
<div><!-- triangle --></div>
<ul>
  <li><a href="#">Home</a>
  <li><a href="#">Projects</a>
  <li><a href="#">Shop</a>
  <li><a href="#">Contact</a>
  <li><a href="#">Media</a>
</ul>
div {
  width: 0;
  height: 0;
  --d:  200px;
  /* red triangle */
  border-right: var(--d) solid transparent;
  border-bottom: var(--d) solid transparent;
  border-left: var(--d) solid red;
  float: left;
  /* triangle CSS shape */
  shape-outside: polygon(0 0, var(--d) 0, 0 var(--d));
}
ul {
  list-style: none;
  padding-top: 25px;
}

A left-floated red triangle is created using border properties. To create a triangular CSS shape that matches the red triangle, we’re using the polygon function as a value for the shape-outside property. The value for the polygon() function is the three coordinates of the triangle, separated by commas. The links automatically align around the floated triangle, forming a slanted menu layout down the triangle’s hypotenuse.

As you can see, even for a simple diagonal layout of user controls, CSS Shapes do a nice job adding a little pizzazz to a design. Using CSS Shapes is a much better option than rotating a line of user controls — the alignment of the individual controls and text also rotate, creating layout weirdness. By contrast, a CSS Shape simply lays out the individual controls along the provided shape’s boundary.


Using CSS Shapes for Interesting User Controls and Navigation originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/using-css-shapes-for-interesting-user-controls-and-navigation/feed/ 2 345274
How to Create CSS Charts With Interesting Shapes, Glyphs and Emoji https://css-tricks.com/how-to-create-css-charts-with-interesting-shapes-glyphs-and-emoji/ https://css-tricks.com/how-to-create-css-charts-with-interesting-shapes-glyphs-and-emoji/#comments Mon, 21 Jun 2021 14:32:45 +0000 https://css-tricks.com/?p=342448 Let’s forego the usual circles and bars we typically see used in charts for more eccentric shapes. With online presentations more and more common today, a quick way to spruce up your web slides and make them stand out is …


How to Create CSS Charts With Interesting Shapes, Glyphs and Emoji originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Let’s forego the usual circles and bars we typically see used in charts for more eccentric shapes. With online presentations more and more common today, a quick way to spruce up your web slides and make them stand out is to give the charts a shapely makeover 🪄

I’ll show you how to create charts with interesting shapes using glyphs, CSS shapes, and emojis with minimal effort.

Let’s start with a simple example.

Using glyphs

<div id="chart">
  <div id="chart-shape">⬠</div>
  <div id="chart-value"></div> 
</div>
#chart {
  width: 300px; 
  height: 300px;
  display: grid;
  background: white;
}
#chart * {
  height: inherit;
  grid-area: 1 / 1;
}

We first give the chart some dimensions and stack the two div inside it by assigning them to the same grid cell. They can be stacked up using any other way, too — with position property, for instance.

Look at the HTML above one more time. One of the divs has a pentagon symbol — the chart shape we want. I added that symbol using the “Emoji and Symbols” keyboard, though it can also be done with the HTML entity value for pentagon, &#x2B20;, inside the div.

The div with the symbol is then styled with CSS font properties as well as a desired chart color. It’s large enough and centered.

#chart-shape {
  font: 300px/300px serif;
  text-align: center; 
  color: limegreen;
}

To the second div in the HTML contains a conic gradient background image. The percentage of the gradient represents the visual value of the chart. The same div also has mix-blend-mode: screen;.

#chart-value {
  background: conic-gradient(transparent 75%, darkseagreen 75%);
  mix-blend-mode: screen;
}

The mix-blend-mode property blends colors inside an element with its backdrop. The screen blend mode value causes a lighter blend to come through. A lighter green shows through the portion where the darkseagreen colored part of the conic gradient overlaps with the limegreen colored pentagram, while the rest of the darskseagreen gradient disappears against the white backdrop of the chart.

An alternative to adding the chart shape in the HTML is to add it as another background layer in CSS and use background-blend-mode instead of mix-blend-mode. However, the code for a chart shape inside the CSS can be less legible for a quick glance. So it’s up to you to see where it’ll be easier for you to add the chart shape in: HTML or CSS. You’ve both options.

#chart {
  width: 300px; 
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'>⬠</div></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

The pentagon symbol is added as a background image in addition to the conic gradient. Then, finally, the property-value pair background-blend-mode: screen; kicks in and the result looks same as the previous demo.

The pentagon background image is created by embedding the HTML with the pentagon symbol () into an SVG that is embedded into a data URL.

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
    <div xmlns='http://www.w3.org/1999/xhtml' 
         style='
          font:300px/300px serif;
          color:limegreen;
          text-align: center;
          background:white;'>
          ⬠
    </div>
  </foreignObject>
</svg>

Which becomes this in CSS:

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'>⬠</div></foreignObject></svg>");

Using CSS shapes

Next, let’s use CSS shapes in place of symbols. CSS shapes are primarily created with the use of border properties. We have a collection of CSS shapes in our archive for your reference.

Here’s a set of properties that can create a simple triangle shape in an element we’ll later add to the SVG, replacing the symbol:

border: 150px solid white; 
border-bottom: 300px solid lime; 
border-top: unset;

When combined with the conic gradient and the background blend, the result is:

<div id="chart"></div>
#chart {
  width: 300px;
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

To restrict the design to the border, a smaller white triangle was added to the design.

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
   <html xmlns='http://www.w3.org/1999/xhtml'>
    /* green triangle */
    <div style='
         border: 150px solid white; 
         border-bottom: 300px solid lime; 
         border-top: unset'></div>
    /* smaller white triangle */
    <div style='
         border: 150px solid transparent; 
         border-bottom: 300px solid white; 
         border-top: unset; 
         transform: scale(0.8) translateY(-360px);'></div>
   </html>
  </foreignObject>
</svg>

Which, again, becomes this in CSS:

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>");

Using emojis

Will emojis work with this approach to charts? You bet it will! 🥳

A block-colored emoji is fed into the SVG image the same way the HTML symbols are. The block color of the emoji is created by giving it a transparent color value, followed by adding a desired color as text-shadow. I covered this technique in another post.

<div id="chart"></div>
#chart {
  width: 300px; 
  height: 300px;
  background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
  conic-gradient(transparent 64%, darkseagreen 64%);
  background-blend-mode: screen;
}

Just as with the last demo, a smaller white apple shape is added at the center to create the border design.

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='300px'>
    <body xmlns='http://www.w3.org/1999/xhtml' style='
          margin: 0;
          text-align: center;
          color:transparent;'>
       /* green apple shape */
       <div style='
            text-shadow: 0 0 limegreen; 
            font-size: 200px; 
            background: white;'>🍏</div>
       /* smaller white apple shape */
       <div style='
            text-shadow:0 0 white; 
            font-size: 170px; 
            position: relative; 
            top: -300px;'>🍏</div>
    </body>
  </foreignObject>
</svg>

I added the two divs inside the <body> element so the repeating style properties of the divs are declared only once in the body element. The divs will then automatically inherit those properties.

Chris had the idea to animate the conic gradient — its percent value to be specific — using the CSS @property (supported in Chrome at the time of writing this article), and it just has the most beautiful effect on the design. @property is a CSS at-rule that explicitly defines a custom CSS property. In supported browsers, when a custom property is defined using @property it can be animated.

@property --n {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 30%;
}
#chart {
  width: 300px; 
  height: 300px;
  --n: 30%;  /*declaration for browsers with no @property support */
  background: 
    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
    conic-gradient(transparent var(--n), darkseagreen var(--n));
  background-blend-mode: screen;
  transition: --n 2s ease-in-out	
}
#chart:hover { --n: 70%; }

The chart above will change its value on hover. In Chrome, the change will look animated.

And although it won’t be as smooth as CSS animation, you can also try animating the gradient using JavaScript. The following JavaScript will cause a somewhat similar animating effect as the above when the cursor moves over the chart.

const chart = document.querySelector('#chart')
chart.onpointerover = ()=>{
  var i = 30,
      timer = setInterval(()=> {
        if (i < 70)
          chart.style.setProperty('--n', i++ + '%')
        else clearInterval(timer)
      }, 10)
}
chart.onpointerout = ()=>{
  var i = 70,
      timer = setInterval(()=> {
        if (i >= 30) 
          chart.style.setProperty('--n', i-- + '%')
        else clearInterval(timer)
      }, 10)
}

When trying your own designs, keep in mind how the different blend modes work. I used the screen blend mode in all my demos just to keep things simple. But with different blend modes, and different backdrop colors, you’ll get varying results. So, I recommend going deeper into blend modes if you haven’t already.

Also, if you want to exclude an element’s color from the final result, try isolation: isolate; on the element — the browser will ignore that backdrop color when applying the blend.

And even though there are all kinds of unusual and quirky shapes we can use in any wild colors we want, always be mindful of the legibility by making the chart value large and clear enough to read.


How to Create CSS Charts With Interesting Shapes, Glyphs and Emoji originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-create-css-charts-with-interesting-shapes-glyphs-and-emoji/feed/ 1 342448
How to Create Actions for Selected Text With the Selection API https://css-tricks.com/how-to-create-actions-for-selected-text-with-the-selection-api/ https://css-tricks.com/how-to-create-actions-for-selected-text-with-the-selection-api/#comments Wed, 28 Apr 2021 14:19:54 +0000 https://css-tricks.com/?p=338189 Click, drag, release: you’ve just selected some text on a webpage — probably to copy and paste it somewhere or to share it. Wouldn’t it be cool if selecting that text revealed some options that make those tasks easier? That’s …


How to Create Actions for Selected Text With the Selection API originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Click, drag, release: you’ve just selected some text on a webpage — probably to copy and paste it somewhere or to share it. Wouldn’t it be cool if selecting that text revealed some options that make those tasks easier? That’s what a selection menu does.

You may already be familiar with selection menus if you’ve ever used an online editor. When you select text, options to format the selection might float above it. In fact, I’m writing this draft in an editor that does exactly this.

Let’s see how we can create a selection menu like this using JavaScript’s Selection API. The API gives us access to the space and content of the selected area on a webpage. This way we can place the selection menu exactly above the selected text and get access to the selected text itself.

Here’s an HTML snippet with some sample text:

<article>
  <h1>Select over the text below</h1> 
  <p>Cascading Style Sheets (CSS) is a style sheet language used for describing the presentation of a document written in a markup language such as HTML. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript. CSS is designed to enable the separation of presentation and content, including layout, colors, and fonts. This separation can improve content accessibility, provide more flexibility and control in the specification of presentation characteristics. </p>
</article>
<template><span id="control"></span></template>

There’s a <template> tag at the end there. The <span> inside it is our selection menu control. Anything inside a <template> tag is not rendered on the page until it’s later added to the page with JavaScript. We’ll add the selection menu control to the page when user selects text. And when the user selects that text, our selection menu will prompt the user to tweet it.

Here’s the CSS to style it:

#control {
    background-image: url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 width='40px' height='40px'><foreignObject width='40px' height='40px'><div xmlns='http://www.w3.org/1999/xhtml' style='width:40px;height:40px;line-height:40px;text-align:center;color:transparent;text-shadow: 0 0 yellow, 2px 4px black, -1px -1px black;font-size:35px;'>💬</div></foreignObject></svg>");
  cursor: pointer;
  position: absolute;
  width: 40px;
  height: 40px;
}
#control::before{
  background-color: black;
  color: white;
  content: " tweet this! ";
  display: block;
  font-weight: bold;
  margin-left: 37px;
  margin-top: 6px;
  padding: 2px;
  width: max-content;
  height: 20px;
}

Check out this article to learn how I used an emoji (💬) for the background image.

So far, the sample text is ready, and the selection menu control has been styled. Let’s move on to the JavaScript. When a selection is made, we’ll get the size and position of the selected area on the page. We then use those measurements to assign the position of the selection menu control at the top-middle of the selected area.

var control = document.importNode(document.querySelector('template').content, true).childNodes[0];
document.querySelector('p').onpointerup = () => {
  let selection = document.getSelection(), text = selection.toString();
  if (text !== "") {
    let rect = selection.getRangeAt(0).getBoundingClientRect();
    control.style.top = `calc(${rect.top}px - 48px)`;
    control.style.left = `calc(${rect.left}px + calc(${rect.width}px / 2) - 40px)`;
    control['text']= text; 
    document.body.appendChild(control);
  }
}

In this code, we first get a copy of the selection menu control inside <template>, then assign it to the control variable.

Next, we write the handler function for the onpointerup event of the element carrying the sample text. Inside the function, we get the selection and the selected string using document.getSelection(). If the selected string is not empty, then we get the selected area’s size and position, via getBoundingClientRect(), and place it in the rect variable.

Using rect, we calculate and assign the top and left positions of the control. This way, the selection menu control is placed a little above the selected area and centered horizontally. We’re also assigning the selected string to a user-defined property of control. This will later be used to share the text.

And, finally, we add control to the webpage using appendChild(). At this point, if we select some of the sample text on the page, the selection menu control will appear on the screen.

Now we get to code what happens when the selection menu control is clicked. In other words, we’re going to make it so that the text is tweeted when the prompt is clicked.

control.addEventListener('pointerdown', oncontroldown, true);

function oncontroldown(event) {
  window.open(`https://twitter.com/intent/tweet?text=${this.text}`)
  this.remove();
  document.getSelection().removeAllRanges();
  event.stopPropagation();
}

When the control is clicked, a tab opens with Twitter’s “New Tweet” page, complete with the selected text ready to go.

After the tweet prompt, the selection menu control is no longer needed and is removed, along with any selection made on the page. The way that the pointerdown event cascades further down the DOM tree is also stopped at this point.

We also need an event handler for the onpointerdown event of the page:

document.onpointerdown = ()=> {    
  let control = document.querySelector('#control');
  if (control !== null) {control.remove();document.getSelection().removeAllRanges();}
}

Now the control and any selection made on the page are removed when clicking anywhere on the page but the selection menu control.

Demo

Here’s a more prettified version that Chris put together:

And here’s an example showing more than one control in the selection menu:

About that <template>

It’s not totally necessary that we use it. Instead, you can also try simply hiding and showing the control some other way, like the hidden HTML attribute or the CSS display. You can also build a selection menu control in the JavaScript itself. The coding choices will depend on how efficiently you execute them, and their fallbacks, if needed, as well as how they fit in with your application.

Some UI/UX advice

While this is a nice effect, there are a couple of things to consider when using it to ensure a good user experience. For example, avoid injecting your own text into the text selection — you know, like appending a link back to your site in the auto-generated tweet. It’s intrusive and annoying. If there’s any reason to do that, like adding the source citation, let the user see a preview of the final text before posting it. Otherwise, the user might be confused or surprised by the addition.

One more thing: It’s best if the menu control is out of the way. We don’t want it covering up too much of the surrounding content. That sort of thing adds up to CSS “data loss” and we want to avoid that.

Bottom line: Understand why your users need to select text on your website and add the controls in a way that gets out of the way of what they’re trying to do.


How to Create Actions for Selected Text With the Selection API originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-create-actions-for-selected-text-with-the-selection-api/feed/ 6 338189
How to Add Text in Borders Using Basic HTML Elements https://css-tricks.com/how-to-add-text-in-borders-using-basic-html-elements/ https://css-tricks.com/how-to-add-text-in-borders-using-basic-html-elements/#comments Tue, 01 Dec 2020 15:56:23 +0000 https://css-tricks.com/?p=326412 Some HTML elements come with preset designs, like the inconveniently small squares of <input type="checkbox"> elements, the limited-color bars of <meter> elements, and the “something about them bothers me” arrows of the <details> elements. We can style them to match …


How to Add Text in Borders Using Basic HTML Elements originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Some HTML elements come with preset designs, like the inconveniently small squares of <input type="checkbox"> elements, the limited-color bars of <meter> elements, and the “something about them bothers me” arrows of the <details> elements. We can style them to match the modern aesthetics of our websites while making use of their functionalities. There are also many elements that rarely get used as both their default appearance and functionality are less needed in modern web designs.

One such HTML element is <fieldset>, along with its child element <legend>.

A <fieldset> element is traditionally used to group and access form controls. We can visually notice the grouping by the presence of a border around the grouped content on the screen. The caption for this group is given inside the <legend> element that’s added as the first child of the <fieldset>.

This combination of <fieldset> and <legend> creates a unique ready-made “text in border” design where the caption is placed right where the border is and the line of the border doesn’t go through the text. The border line “breaks” when it encounters the beginning of the caption text and resumes after the text ends.

In this post, we’ll make use of the <fieldset> and <legend> combo to create a more modern border text design that’s quick and easy to code and update.

For the four borders, we need four <fieldset> elements, each containing a <legend> element inside. We add the text that will appear at the borders inside the <legend> elements.

<fieldset><legend>Wash Your Hands</legend></fieldset>
<fieldset><legend>Stay Apart</legend></fieldset>
<fieldset><legend>Wear A Mask</legend></fieldset>
<fieldset><legend>Stay Home</legend></fieldset>

To begin, we stack the <fieldset> elements on top of each other in a grid cell and give them borders. You can stack them using any way you want — it doesn’t necessarily have to be a grid.

Only the top border of each <fieldset> element is kept visible while the remaining edges are transparent since the text of the <legend> element appears at the top border of the <fieldset> by default.

Also, we give all the <fieldset> elements a box-sizing property with a value of border-box so the width and height of the <fieldset> elements include their border and padding sizes too. Doing this later creates a leveled design, when we style the <legend> elements.

body {
  display: grid; 
  margin: auto; /* to center */
  margin-top: calc(50vh - 170px); /* to center */
  width: 300px; height: 300px; 
}

fieldset {
  border: 10px solid transparent; 
  border-top-color: black; 
  box-sizing: border-box; 
  grid-area: 1 / 1; /* first row, first column */
  padding: 20px; 
  width: inherit; 
}

After this, we rotate the last three <fieldset> elements in order to use their top borders as the side and bottom borders of our design.

/* rotate to right */
fieldset:nth-of-type(2){ transform: rotate(90deg); }
/* rotate to bottom */
fieldset:nth-of-type(3){ transform: rotate(180deg); }
/* rotate to left */
fieldset:nth-of-type(4){ transform: rotate(-90deg); }

Next up is styling the <legend> elements. The key to create smooth border text using a <legend> element is to give it a zero (or small enough) line-height. If it has a large line height, that will displace the position of the border it’s in, pushing the border down. And when the border moves with the line height, we won’t be able to connect all the four sides of our design and will need to readjust the borders.

legend {
  font: 15pt/0 'Averia Serif Libre'; 
  margin: auto; /* to center */
  padding: 0 4px; 
}

fieldset:nth-of-type(3) > legend { 
  transform: rotate(180deg);
}

I used the font shorthand property to give the values for the font-size, line-height and font-family properties of the <legend> elements.

The <legend> element that adds the text at the bottom border of our design, fieldset:nth-of-type(3)>legend, is upside-down because of its rotated <fieldset> parent element. Flip that <legend> element vertically to show its text right-side-up.

Add an image to the first <fieldset> element and you get something like this:

Lateral margins can move the text along the border. Left and right margins with auto values will center the text, as seen in the above Pen. Only the left margin with an auto value will flush the text to the right, and vice versa, for the right margin.

Bonus: After a brief geometrical detour, here’s an octagonal design I made using the same technique:


How to Add Text in Borders Using Basic HTML Elements originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-add-text-in-borders-using-basic-html-elements/feed/ 7 326412
Creating CSS Shapes with Emoji https://css-tricks.com/creating-css-shapes-with-emoji/ https://css-tricks.com/creating-css-shapes-with-emoji/#comments Fri, 23 Oct 2020 22:36:16 +0000 https://css-tricks.com/?p=323780 CSS Shapes is a standard that lets us create geometric shapes over floated elements that cause the inline contents — usually text — around those elements to wrap along the specified shapes.

Such a shaped flow of text looks good …


Creating CSS Shapes with Emoji originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
CSS Shapes is a standard that lets us create geometric shapes over floated elements that cause the inline contents — usually text — around those elements to wrap along the specified shapes.

Such a shaped flow of text looks good in editorial designs or designs that work with text-heavy contents to add some visual relief from the chunks of text.

Here’s an example of CSS Shape in use:

The shape-outside property specifies the shape of a float area using either one of the basic shape functions — circle(), ellipse(), polygon() or inset() — or an image, like this:

Inline content wraps along the right side of a left-floated element, and the left side of a right-floated element.

In this post, we’ll use the concept of CSS Shapes with emoji to create interesting text-wrapping effects. Images are rectangles. Many of the shapes we draw in CSS are also boxy or at least limited to standard shapes. Emoji, on the other hand, offers neat opportunities to break out of the box!

Here’s how we’ll do it: We’ll first create an image out of an emoji, and then float it and apply a CSS Shape to it.

I’ve already covered multiple ways to convert emojis to images in this post on creative background patterns. In that I said I wasn’t able to figure out how to use SVG <text> to do the conversion, but I’ve figured it out now and will show you how in this post.  You don’t need to have read that article for this one to make sense, but it’s there if you want to see it.

Let’s make an emoji image

The three steps we’re using to create an emoji image are:

  • Create an emoji-shaped cutout in SVG
  • Convert the SVG code to a DataURL by URL encoding and prefixing it with data:image/svg+xml
  • Use the DataURL as the url() value of an element’s background-image.

Here’s the SVG code that creates the emoji shaped cutout:

<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> 
  <clipPath id='emojiClipPath'> 
    <text x='0' y='130px' font-size='130px'>🦕</text> 
  </clipPath> 
  <text x='0' y='130px' font-size='130px' clip-path='url(#emojiClipPath)'>🦕</text>
</svg>

What’s happening here is we’re providing a <text> element with an emoji character for a <clipPath>. A clip path is an outline of a region to be kept visible when that clip path is applied to an element. In our code, that outline is the shape of the emoji character.

Then the emoji’s clip path is referenced by a <text> element carrying the same emoji character, using its clip-path property, creating a cutout in the shape of the emoji.

Now, we convert the SVG code to a DataURL. You can URL encode it by hand or use online tools (like this one!) that can do it for you.

Here’s the resulted DataURL, used as the url() value for the background image of an .emoji element in CSS:

.emoji {
  background: url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px'  font-size='130px'>🦕</text> </clipPath> <text x='0' y='130px' font-size='130px' clip-path='url(%23emojiClipPath)'>🦕</text></svg>");
}

If we were to stop here and give the .emoji element dimensions, we’d see our character displayed as a background image:

Now let’s turn this into a CSS Shape

We can do this in two steps:

  • Float the element with the emoji background
  • Use the DataURL as the url() value for the element’s shape-outside property
.emoji {
  --image-url: url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px'  font-size='130px'>🦕</text> </clipPath> <text x='0' y='130px'  font-size='130px' clip-path='url(#emojiClipPath)'>🦕</text></svg>");
  background: var(--image-url);
  float: left;
  height: 150px;
  shape-outside: var(--image-url);
  width: 150px;
  margin-left: -6px; 
}

We placed the DataURL in a custom property, --image-url, so we can easily refer it in both the background and the shape-outside properties without repeating that big ol’ string of encoded SVG multiple times.

Now, any inline content near the floated .emoji element will flow in the shape of the emoji. We can adjust things even further with margin or shape-margin to add space around the shape.

If you want a color-blocked emoji shape, you can do that by applying the clip path to a <rect> element in the SVG:

<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> 
    <clipPath id='emojiClipPath'> 
        <text x='0' y='130px' font-size='130px'>🦕</text> 
    </clipPath> 
    <rect x='0' y='0' fill='green' width='150px' height='150px' clip-path='url(#emojiClipPath)'/> 
</svg>

The same technique will work with letters!

Just note that Firefox doesn’t always render the emoji shape. We can work around that by updating the SVG code.

<svg xmlns='http://www.w3.org/2000/svg' width='150px' height='150px'>
  <foreignObject width='150px' height='150px'>
    <div xmlns='http://www.w3.org/1999/xhtml' style='width:150px;height:150px;line-height:150px;text-align:center;color:transparent;text-shadow: 0 0 black;font-size:130px;'>🧗</div>
  </foreignObject>
</svg>

This creates a block-colored emoji shape by making the emoji transparent and giving it text-shadow with inline CSS. The <div> containing the emoji and inline CSS style is then inserted into a <foreignObject> element of SVG so the HTML <div> code can be used inside the SVG namespace. The rest of the code in this technique is same as the last one.

Now we need to center the shape

Since CSS Shapes can only be applied to floated elements, the text flows either to the right or left of the element depending on which side it’s floated. To center the element and the shape, we’ll do the following:

  • Split the emoji in half
  • Float the left-half of the emoji to the right, and the right-half to the left
  • Put both sides together!

One caveat to this strategy: if you’re using running sentences in the design, you’ll need to manually align the letters on both sides.

Here’s what we’re aiming to make:

First, we see the HTML for the left and right sides of the design. They are identical.

<div id="design">
  <p id="leftSide">A C G T A <!-- more characters --> C G T A C G T A C G T <span class="emoji"></span>A C G <!-- more characters --> C G T </p>
  <p id="rightSide">A C G T A <!-- more characters --> C G T A C G T A C G T <span class="emoji"></span>A C G <!-- more characters --> C G T </p>
</div>

p#leftSide and p#rightSide inside #design are arranged side-by-side in a grid.

#design {
  border-radius: 50%; /* A circle */
  box-shadow: 6px 6px 20px silver;
  display: grid; 
  grid: "1fr 1fr"; /* A grid with two columns */
  overflow: hidden;
  width: 400px; height: 400px;
}

Here’s the CSS for the emoji:

span.emoji {
  filter: drop-shadow(15px 15px 5px green);
  shape-margin: 10px;
  width: 75px; 
  height: 150px;
}

/* Left half of the emoji */
p#leftSide>span.emoji {
  --image-url:url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='0' y='130px'  font-size='130px'>🦎</text> </clipPath> <rect x='0' y='0' width='150px' height='150px' clip-path='url(%23emojiClipPath)'/></svg>");
  background-image: var(--image-url);
  float: right;
  shape-outside: var(--image-url);
}

/* Right half of the emoji */
p#rightSide>span.emoji {
  --image-url:url("data:image/svg+xml,<svg width='150px' height='150px' xmlns='http://www.w3.org/2000/svg'> <clipPath id='emojiClipPath'> <text x='-75px' y='130px'  font-size='130px'>🦎</text> </clipPath> <rect x='0' y='0' width='150px' height='150px' clip-path='url(%23emojiClipPath)'/></svg>");
  background-image: var(--image-url);
  float: left;
  shape-outside: var(--image-url);
}

The width of the <span> elements that hold the emoji images (span.emoji) is 75px whereas the width of the SVG emoji images is 150px. This automatically crops the image in half when displayed inside the spans.

On the right side of the design, with the left-floated emoji (p#rightSide>span.emoji), we need to move the emoji halfway to the left to show the right-half, so the x value in the <text> in the DataURL is changed to 75px. That’s the only difference in the DataURLs from the left and right sides of the design.

Here’s that result once again:


That’s it! You can try the above method to center any CSS Shape as long as you can split the element up into two and put the halves back together with CSS.


Creating CSS Shapes with Emoji originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creating-css-shapes-with-emoji/feed/ 3 323780
Menu Reveal By Page Rotate Animation https://css-tricks.com/menu-reveal-by-page-rotate-animation/ https://css-tricks.com/menu-reveal-by-page-rotate-animation/#comments Tue, 08 Sep 2020 15:08:12 +0000 https://css-tricks.com/?p=320113 There are many different approaches to menus on websites. Some menus are persistent, always in view and display all the options. Other menus are hidden by design and need to be opened to view the options. And there are even …


Menu Reveal By Page Rotate Animation originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There are many different approaches to menus on websites. Some menus are persistent, always in view and display all the options. Other menus are hidden by design and need to be opened to view the options. And there are even additional approaches on how hidden menus reveal their menu items. Some fly out and overlap the content, some push the content away, and others will do some sort of full-screen deal.

Whatever the approach, they all have their pros and cons and the right one depends on the situation where it’s being used. Frankly, I tend to like fly-out menus in general. Not for all cases, of course. But when I’m looking for a menu that is stingy on real estate and easy to access, they’re hard to beat.

What I don’t like about them is how often they conflict with the content of the page. A fly-out menu, at best, obscures the content and, at worst, removes it completely from the UI.

I tried taking another approach. It has the persistence and availability of a fixed position as well as the space-saving attributes of a hidden menu that flies out, only without removing the user from the current content of the page.

Here’s how I made it.

The toggle

We’re building a menu that has two states — open and closed — and it toggles between the two. This is where the Checkbox Hack comes into play. It’s perfect because a checkbox has two common interactive states — checked and unchecked (there’s also the indeterminate) — that can be used to trigger those states.

The checkbox is hidden and placed under the menu icon with CSS, so the user never sees it even though they interact with it. Checking the box (or, ahem, the menu icon) reveals the menu. Unchecking it hides it. Simple as that. We don’t even need JavaScript to do the lifting!

Of course, the Checkbox Hack isn’t the only way to do this, and if you want to toggle a class to open and close the menu with JavaScript, that’s absolutely fine.

It’s important the checkbox precedes the main content in the source code, because the :checked selector we’re going to ultimately write to make this work needs to use a sibling selector. If that’ll cause layout concerns for you, use Grid or Flexbox for your layouts as they are source order independent, like how I used its advantage for counting in CSS.

 The checkbox’s default style (added by the browser) is stripped out, using the appearance CSS property, before adding its pseudo element with the menu icon so that the user doesn’t see the square of the checkbox.

First, the basic markup:

<input type="checkbox"> 
<div id="menu">
  <!--menu options-->
</div>
<div id="page">
  <!--main content-->
</div>

…and the baseline CSS for the Checkbox Hack and menu icon:

/* Hide checkbox and reset styles */
input[type="checkbox"] {
  appearance: initial; /* removes the square box */
  border: 0; margin: 0; outline: none; /* removes default margin, border and outline */
  width: 30px; height: 30px; /* sets the menu icon dimensions */
  z-index: 1;  /* makes sure it stacks on top */
} 


/* Menu icon */
input::after {
  content: "\2255";
  display: block; 
  font: 25pt/30px "georgia"; 
  text-indent: 10px;
  width: 100%; height: 100%;
} 


/* Page content container */
#page {
  background: url("earbuds.jpg") #ebebeb center/cover;
  width: 100%; height: 100%;
}

I threw in the styles for the #page content as well, which is going to be a full size background image.

The transition

Two things happen when the menu control is clicked. First, the menu icon changes to an × mark, symbolizing that it can be clicked to close the menu. So, we select the ::after pseudo element of checkbox input when the input is in a :checked state:

input:checked::after {
  content: "\00d7"; /* changes to × mark */
  color: #ebebeb;
}

Second, the main content (our “earbuds” image) transforms, revealing the menu underneath. It moves to the right, rotates and scales down, and its left side corners get angular. This is to give the appearance of the content getting pushed back, like a door that swings open. 

input:checked ~ #page { 
  clip-path: polygon(0 8%, 100% 0, 100% 100%, 0 92%);
  transform: translateX(40%) rotateY(10deg) scale(0.8); 
  transform-origin: right center; 
  transition: all .3s linear;
} 

I used clip-path to change the corners of the image.

Since we’re applying a transition on the transformations, we need an initial clip-path value on the #page so there’s something to transition from. We’ll also drop a transition on #page while we’re at it because that will allow it to close as smoothly as it opens.

#page {
  background: url("earbuds.jpeg") #ebebeb center/cover; 
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: all .3s linear;
  width: 100%; height: 100%;
}

We’re basically done with the core design and code. When the checkbox is unchecked (by clicking the × mark) the transformation on the earbud image will automatically be undone and it’ll be brought back to the front and centre. 

A sprinkle of JavaScript

Even though we have what we’re looking for, there’s still one more thing that would give this a nice boost in the UX department: close the menu when clicking (or tapping) the #page element. That way, the user doesn’t need to look for or even use the × mark to get back to the content.

Since this is merely an additional way to hide the menu, we can use JavaScript. And if JavaScript is disabled for some reason? No big deal. It’s just an enhancement that doesn’t prevent the menu from working without it.

document.querySelector("#page").addEventListener('click', (e, checkbox = document.querySelector('input')) => { 
  if (checkbox.checked) { checkbox.checked = false; e.stopPropagation(); }
});

What this three-liner does is add a click event handler over the #page element that un-checks the checkbox if the checkbox is in a :checked state, which closes the menu.

We’ve been looking at a demo made for a vertical/portrait design, but works just as well at larger landscape screen sizes, depending on the content we’re working with.


This is just one approach or take on the typical fly-out menu. Animation opens up lots of possibilities and there are probably dozens of other ideas you might have in mind. In fact, I’d love to hear (or better yet, see) them, so please share!


Menu Reveal By Page Rotate Animation originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/menu-reveal-by-page-rotate-animation/feed/ 6 320113
Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/ https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/#comments Wed, 10 Jun 2020 14:45:25 +0000 https://css-tricks.com/?p=312443 You can create stripes in CSS. That’s all I thought about in terms of CSS background patterns for a long time. There’s nothing wrong with stripes; stripes are cool. They can be customized into wide and narrow bands, criss-crossed …


Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You can create stripes in CSS. That’s all I thought about in terms of CSS background patterns for a long time. There’s nothing wrong with stripes; stripes are cool. They can be customized into wide and narrow bands, criss-crossed into a checked pattern, and played with in other ways using the idea of hard stops. But stripes can be boring, too. Too conventional, out of fashion, and sometimes even unpleasant.

Thankfully, we can conjure up far more background patterns than you can even imagine with CSS, with code that is similar in spirit to stripes.

Background patterns are images repeated across a background. They can be done by referencing an external image, like a PNG file, or can be drawn with CSS, which is traditionally done using CSS gradients. 

Linear gradients (and repeating linear gradients) for instance, are typically used for stripes. But there are other ways to create cool background patterns. Let’s see how we can use gradients in other ways and toss in other things, like CSS shapes and emoji, to spice things up.

Gradient patterns

There are three types of CSS gradients.

Linear (left), radial (center) and conic (right) gradients
  1. linear-gradient(): Colors flow from left-to-right, top-to-bottom, or at any angle you choose in a single direction.
  2. radial-gradient(): Colors start at a single point and emanate outward
  3. conic-gradient(): Similar in concept to radial gradients, but the color stops are placed around the circle rather than emanating from the center point.

I recommend checking out the syntax for all the gradients to thoroughly understand how to start and end a color in a gradient.

Radial gradient patterns

Let’s look at radial gradients first because they give us very useful things: circles and ellipses. Both can be used for patterns that are very interesting and might unlock some ideas for you!

background: radial-gradient(<gradient values>)

Here’s a pattern of repeating watermelons using this technique:

background: 
	radial-gradient(circle at 25px 9px, black 2px, transparent 2px), 
	radial-gradient(circle at 49px 28px, black 2px, transparent 2px), 
	radial-gradient(circle at 38px 1px, black 2px, transparent 2px), 
	radial-gradient(circle at 20px 4px, black 2px, transparent 2px), 
	radial-gradient(circle at 80px 4px, black 2px, transparent 2px), 
	radial-gradient(circle at 50px 10px, black 2px, transparent 2px), 
	radial-gradient(circle at 60px 16px, black 2px, transparent 2px), 
	radial-gradient(circle at 70px 16px, black 2px, transparent 2px), 
	radial-gradient(ellipse at 50px 0, red 33px, lime 33px, lime 38px, transparent 38px) 
	white;
background-size: 100px 50px;

We start by providing a background size on the element then stack up the gradients inside it. An ellipse forms the green and red parts. Black circles are scattered across to represent the watermelon seeds. 

The first two parameters for a radial gradient function determine whether the gradient shape is a circle or an ellipse and the starting position of the gradient. That’s followed by the gradient color values along with the start and ending positions within the gradient.

Conic gradient patterns

Conic gradients create ray-like shapes. Like linear and radial gradients, conic gradients can be used to create geometric patterns.

background: conic-gradient(<gradient values>)
background: 
  conic-gradient(yellow 40deg, blue 40deg, blue 45deg, transparent 45deg), 
  conic-gradient(transparent 135deg, blue 135deg, blue 140deg, transparent 140deg) ;
background-size: 60px 60px;
background-color: white;

The rub with conic gradient is that it’s not supported in Firefox, at least at the time of writing. It’s always worth keeping an eye out for deeper support.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
6983No7912.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
11511511512.2-12.5

Emoji icon patterns

This is where things begin to get interesting. Rather than just using geometric patterns (as in gradients), we now use the organic shapes of emojis to create background patterns. 🎉 

It starts with emoji icons. 

Solid-color emoji patterns

We can create emoji icons by giving emojis a transparent color and text shadow.

color: transparent;
text-shadow: 0 0 black;

Those icons can then be turned into an image that can be used as a background, using SVG.

<svg>
  <foreignObject>
    <!-- The HTML code with emoji -->
  </foreignObject>
</svg>

The SVG can then be referred by the background property using data URL

background: url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><!-- SVG code --></svg>");

And, voilá! We get something like this:

background: 
    url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><foreignObject width=%22100px%22 height=%22100px%22><div xmlns=%22http://www.w3.org/1999/xhtml%22 style=%22color:transparent;text-shadow: 0 0 %23e42100, -2px 2px 0 black;font-size:70px%22>🏄‍♀️</div></foreignObject></svg>"), 
    white; 
background-size: 60px 60px; 

Other than emojis, it’s also possible to draw CSS shapes and use them as patterns. Emojis are less work, though. Just saying. 

Gradient-colored emoji patterns

Instead of using plain emoji icons, we can use gradient emoji icons. To do that, skip the text shadow on the emojis. Add a gradient background behind them and use background-clip to trim the gradient background to the shape of the emojis. 

color: transparent;
background: linear-gradient(45deg, blue 20%, fuchsia);
background-clip: text; /* Safari requires -webkit prefix */

Then, just as before, use the combination of SVG and data URL to create the background pattern.

Translucent-colored emoji patterns

This is same as using block colored emoji icons. This time, however, we take away the opaqueness of the colors by using rgba() or hsla() values for the text shadow. 

color: transparent;
text-shadow: 20px 10px rgba(0, 255, 0, .3), 
             0 0 red;

SVG-text emoji patterns

We’ve already looked at all the working methods I could think of to create background patterns, but I feel like I should also mention this other technique I tried, which is not as widely supported as I’d hoped.

 I tried placing the emoji in an SVG <text> element instead of the HTML added using <foreignObject>. But I wasn’t able to create a solid shadow behind it in all the browsers.

background: 
  url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%221em%22 font-size=%2270%22 fill=%22transparent%22 style=%22text-shadow: 0 0 %23e42100, -2px 2px 5px black, 0 0 6px white; ;%22>🏄‍♀️</text></svg>")

Just in case, I tried using CSS and SVG filters for the shadow as well, thinking that might work. It didn’t. I also tried using the stroke attribute, to at least create an outline for the emoji, but that didn’t work, either. 

CSS element() patterns

I didn’t think of SVG when I first thought of converting emoji icons or CSS shapes into background images. I tried CSS element(). It’s a function that directly converts an HTML element into an image that can be referenced and used. I really like this approach, but browser support is a huge caveat, which is why I’m mentioning it here at the end.

Basically, we can drop an element in the HTML like this:

<div id=snake >🐍</div>

…then pass it into the element() function to use like an image on other elements, like this:

background: 
  -moz-element(#snake), /* Firefox only */
  linear-gradient(45deg, transparent 20px, blue 20px, blue 30px, transparent 30px) 
  white;
background-size: 60px 60px;
background-color: white;

Now that snake emoji is technically an image that we get to include in the pattern.

Again, browser support is spotty, making this approach super experimental.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
No4*NoNoNo

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
No115*NoNo

In this method, the original emoji (or any CSS shape for that matter) used for the background pattern needs to render on screen for it to appear in the background pattern as well. To hide that original emoji, I used mix-blend-mode — it sort of masks out the original emoji in the HTML so it doesn’t show up on the page.


I hope you find the methods in this post useful in one way or another and learned something new in the process! Give them a try. Experiment with different emojis and CSS shapes because gradients, while cool and all, aren’t the only way to make patterns.. The background property takes multiple values, allowing us to think of creative ways to stack things.


Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/feed/ 1 312443