About

Wednesday, October 6, 2021

Scroll Shadows With JavaScript

Scroll shadows are when you can see a little inset shadow on elements if (and only if) you can scroll in that direction. It’s just good UX. You can actually pull it off in CSS, which I think is amazing and one of the great CSS tricks. Except… it just doesn’t work on iOS Safari. It used to work, and then it broke in iOS 13, along with some other useful CSS things, with no explanation why and has never been fixed.

So, now, if you really want scroll shadows (I think they are extra useful on mobile browsers anyway), it’s probably best to reach for JavaScript.

Here’s a pure CSS example so you can see it work in all browsers except iOS Safari. Screenshots:

I’m bringing this up now because I see Jonnie Hallman is blogging about tit again. He mentioned it as an awesome little detail back in May. There are certain interfaces where scroll shadows really extra make sense.

Taking a step back, I thought about the solution that currently worked, using scroll events. If the scroll area has scrolled, show the top and left shadows. If the scroll area isn’t all the way scrolled, show the bottom and right shadows. With this in mind, I tried the simplest, most straight-forward, and least clever approach by putting empty divs at the top, right, bottom, and left of the scroll areas. I called these “edges”, and I observed them using the Intersection Observer API. If any of the edges were not intersecting with the scroll area, I could assume that the edge in question had been scrolled, and I could show the shadow for that edge. Then, once the edge is intersecting, I could assume that the scroll area has reached the edge of the scroll, so I could hide that shadow.

Clever clever. No live demo, unfortunately, but read the post for a few extra details on the implementation.

Other JavaScript-powered examples

I do think if you’re going to do this you should go the IntersectionObserver route though. Would love to see someone port the best of these ideas all together (wink wink).


The post Scroll Shadows With JavaScript appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



source https://css-tricks.com/scroll-shadows-with-javascript/

Conditional Border Radius In CSS

Ahmad Shadeed documents a bonafide CSS trick from the Facebook CSS codebase. The idea is that when an element is the full width of the viewport, it doesn’t have any border-radius. But otherwise, it has 8px of border-radius. Here’s the code:

.card {
  border-radius: max(0px, min(8px, calc((100vw - 4px - 100%) * 9999)));
}

One line! Super neat. The guts of it is the comparison between 100vw and 100%. Essentially, the border-radius comes out to 8px most of the time. But if the component becomes the same width as the viewport (within 4px, but I’d say that part is optional), then the value of the border-radius becomes 0px, because the equation yields a negative (invalid) number.

The 9999 multiplication means that you’ll never get low-positive numbers. It’s a toggle. You’ll either get 8px or 0px and nothing in between. Try removing that part, resizing the screen, and seeing it sorta morph as the viewport becomes close to the component size:

Why do it like this rather than at a @media query? Frank, the developer behind the Facebook choice, says:

It’s not a media query, which compares the viewport to a fixed width. It’s effectively a kind of container query that compares the viewport to its own variable width.

Frank Yan

And:

This is a more general purpose solution as it doesn’t need to know the size of the card. A media query would be dependent on the width of the card.

Naman Goel

The technique is apparently called the “Fab Four” Technique which is useful in emails.

Direct Link to Article — Permalink


The post Conditional Border Radius In CSS appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



source https://ishadeed.com/article/conditional-border-radius/

Tuesday, October 5, 2021

Branching Strategies in Git

This article is part of our “Advanced Git” series. Be sure to follow us on Twitter or sign up for our newsletter to hear about the next articles!

Almost all version control systems (VCS) have some kind of support for branching. In a nutshell, branching means that you leave the main development line by creating a new, separate container for your work and continue to work there. This way you can experiment and try out new things without messing up the production code base. Git users know that Git’s branching model is special and incredibly powerful; it’s one of the coolest features of this VCS. It’s fast and lightweight, and switching back and forth between the branches is just as fast as creating or deleting them. You could say that Git encourages workflows that use a lot of branching and merging.

Git totally leaves it up to you how many branches you create and how often you merge them. Now, if you’re coding on your own, you can choose when to create a new branch and how many branches you want to keep. This changes when you’re working in a team, though. Git provides the tool, but you and your team are responsible for using it in the optimal way!

In this article, I’m going to talk about branching strategies and different types of Git branches. I’m also going to introduce you to two common branching workflows: Git Flow and GitHub Flow.

Advanced Git series:

  • Part 1: Creating the Perfect Commit in Git
  • Part 2: Branching Strategies in Git
    You are here!
  • Part 3: Better Collaboration With Pull Requests
    Coming soon!
  • Part 4: Merge Conflicts
  • Part 5: Rebase vs. Merge
  • Part 6: Interactive Rebase
  • Part 7: Cherry-Picking Commits in Git
  • Part 8: Using the Reflog to Restore Lost Commits

Teamwork: Write down a convention

Before we explore different ways of structuring releases and integrating changes, let’s talk about conventions. If you work in a team, you need to agree on a common workflow and a branching strategy for your projects. It’s a good idea to put this down in writing to make it accessible to all team members.

Admittedly, not everyone likes writing documentation or guidelines, but putting best practise on record not only avoids mistakes and collisions, it also helps when onboarding new team members. A document explaining your branching strategies will help them to understand how you work and how your team handles software releases.

Here are a couple of examples from our own documentation:

  • master represents the current public release branch
  • next represents the next public release branch (this way we can commit hotfixes on master without pulling in unwanted changes)
  • feature branches are grouped under feature/
  • WIP branches are grouped under wip/ (these can be used to create “backups” of your personal WIP)

A different team might have a different opinion on these things (for example on “wip” or “feature” groups), which will certainly be reflected in their own documentation.

Integrating changes and structuring releases

When you think about how to work with branches in your Git repositories, you should probably start with thinking about how to integrate changes and how to structure releases. All those topics are tightly connected. To help you better understand your options, let’s look at two different strategies. The examples are meant to illustrate the extreme ends of the spectrum, which is why they should give you some ideas of how you can design your own branching workflow:

  • Mainline Development
  • State, Release, and Feature Branches

The first option could be described as “always be integrating” which basically comes down to: always integrate your own work with the work of the team. In the second strategy you gather your work and release a collection of it, i.e. multiple different types of branches enter the stage. Both approaches have their pros and cons, and both strategies can work for some teams, but not for others. Most development teams work somewhere in between those extremes.

Let’s start with the mainline development and explain how this strategy works.

Mainline Development

I said it earlier, but the motto of this approach is “always be integrating.” You have one single branch, and everyone contributes by committing to the mainline:

Remember that we’re simplifying for this example. I doubt that any team in the real world works with such a simple branching structure. However, it does help to understand the advantages and disadvantages of this model.

Firstly, you only have one branch which makes it easy to keep track of the changes in your project. Secondly, commits must be relatively small: you can’t risk big, bloated commits in an environment where things are constantly integrated into production code. As a result, your team’s testing and QA standards must be top notch! If you don’t have a high-quality testing environment, the mainline development approach won’t work for you. 

State, Release and Feature branches

Let’s look at the opposite now and how to work with multiple different types of branches. They all have a different job: new features and experimental code are kept in their own branches, releases can be planned and managed in their own branches, and even various states in your development flow can be represented by branches:

Remember that this all depends on your team’s needs and your project’s requirements. While this approach may look complicated at first, it’s all a matter of practise and getting used to it.

Now, let’s explore two main types of branches in more detail: long-running branches and short-lived branches.

Long-running branches

Every Git repository contains at least one long-running branch which is typically called master or main. Of course, your team may have decided to have other long-running branches in a project, for example something like develop, production or staging. All of those branches have one thing in common: they exist during the entire lifetime of a project. 

A mainline branch like master or main is one example for a long-running branch. Additionally, there are so-called integration branches, like develop or staging. These branches usually represent states in a project’s release or deployment process. If your code moves through different states in its development life cycle — e.g. from developing to staging to production — it makes sense to mirror this structure in your branches, too.

One last thing about long-running branches: most teams have a rule like “don’t commit directly to a long-running branch.” Instead, commits are usually integrated through a merge or rebase. There are two main reasons for such a convention:

  • Quality: No untested or unreviewed code should be added to a production environment.
  • Release bundling and scheduling: You might want to release new code in batches and even schedule the releases in advance.

Next up: short-lived branches, which are usually created for certain purposes and then deleted after the code has been integrated.

Short-lived branches

In contrast to long-running branches, short-lived branches are created for temporary purposes. Once they’ve fulfilled their duty and the code has been integrated into the mainline (or another long-lived branch), they are deleted. There are many different reasons for creating a short-lived branch, e.g. starting to work on a new and experimental feature, fixing a bug, refactoring your code, etc.

Typically, a short-lived branch is based on a long-running branch. Let’s say you start working on a new feature of your software. You might base the new feature on your long-running main branch. After several commits and some tests you decide the work is finished. The new feature can be integrated into the main branch, and after it has been merged or rebased, the feature branch can be deleted. 

In the last section of this article, let’s look at two popular branching strategies: Git Flow and GitHub Flow. While you and your team may decide on something completely different, you can take them as inspiration for your own branching strategy.

Git Flow

One well-known branching strategy is called Git Flow. The main branch always reflects the current production state. There is a second long-running branch, typically called develop. All feature branches start from here and will be merged into develop. Also, it’s the starting point for new releases: developers open a new release branch, work on that, test it, and commit their bug fixes on such a release branch. Once everything works and you’re confident that it’s ready for production, you merge it back into main. As the last step, you add a tag for the release commit on main and delete the release branch.

Git Flow works pretty well for packaged software like (desktop) applications or libraries, but it seems like a bit of an overkill for website projects. Here, the difference between the main branch and the release branch is often not big enough to benefit from the distinction. 

If you’re using a Git desktop GUI like Tower, you’ll find the possible actions in the interface and won’t have to memorize any new commands:

Git Flow offers a couple of predefined actions: a desktop GUI like Tower can save you from learning these new commands by heart.

GitHub Flow

If you and your team follow the continuous delivery approach with short production cycles and frequent releases, I would suggest looking at GitHub Flow. 

It’s extremely lean and simple: there is one long-running branch, the default main branch. Anything you’re actively working on has its own separate branch. It doesn’t matter if that’s a feature, a bug fix, or a refactoring.

What’s the “best” Git branching strategy?

If you ask 10 different teams how they’re using Git branches, you’ll probably get 10 different answers. There is no such thing as the “best” branching strategy and no perfect workflow that everyone should adopt. In order to find the best model for you and your team, you should sit down together, analyze your project, talk about your release strategy, and then decide on a branching workflow that supports you in the best possible way.

If you want to dive deeper into advanced Git tools, feel free to check out my (free!) “Advanced Git Kit”: it’s a collection of short videos about topics like branching strategies, Interactive Rebase, Reflog, Submodules and much more.

Advanced Git series:

  • Part 1: Creating the Perfect Commit in Git
  • Part 2: Branching Strategies in Git
    You are here!
  • Part 3: Better Collaboration With Pull Requests
    Coming soon!
  • Part 4: Merge Conflicts
  • Part 5: Rebase vs. Merge
  • Part 6: Interactive Rebase
  • Part 7: Cherry-Picking Commits in Git
  • Part 8: Using the Reflog to Restore Lost Commits

The post Branching Strategies in Git appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



source https://css-tricks.com/branching-strategies-in-git/

ct.css — Performance Hints via Injected Stylesheet Alone

This is some bonafide CSS trickery from Harry that gives you some generic performance advice based on what it sees in your <head> element.

First, it’s possible to make a <style> block visible like any other element by changing the display away from the default of none. It’s a nice little trick. You can even do that for things in the <head>, for example…

head,
head style,
head script {
  display: block;
}

From there, Harry gets very clever with selectors, determining problematic situations from the usage and placement of certain tags. For example, say there is a <script> that comes after some styles…

<head>
  <link rel="stylesheet" href="...">
  <script src="..."></script>
  <title>Page Title</title>
  <!-- ...  -->

Well, that’s bad, because the script is blocked by CSS likely unnecessarily. Perhaps some sophisticated performance tooling software could tell you that. But you know what else can? A CSS selector!

head [rel="stylesheet"]:not([media="print"]):not(.ct) ~ script,
head style:not(:empty) ~ script {

}

That’s kinda like saying head link ~ script, but a little fancier in that it only selects actual stylesheets or style blocks that are truly blocking (and not itself). Harry then applies styling and pseudo-content to the blocks so you can use the stylesheet as a visual performance debugging tool.

That’s just darn clever, that. The stylesheet has loads of little things you can test for, like attributes you don’t need, blocking resources, and elements that are out of order.

Direct Link to Article — Permalink


The post ct.css — Performance Hints via Injected Stylesheet Alone appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



source https://csswizardry.com/ct/

Quickly Testing CSS Fallbacks

Dumb trick alert!

Not all browsers support all features. Say you want to write a fallback for browsers that doesn’t support CSS Grid. Not very common these days, but it’s just to illustrate a point.

You could write the supporting CSS in an @supports blocks:

@supports (display: grid) {
  .blocks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100px, 100%), 1fr));
    gap: 1rem;
  }
}

Then to test the fallback, you quickly change @supports (display: grid) to something nonsense, like adding an “x” so it’s @supports (display: gridx). That’s a quick toggle:

The example above doesn’t have very good fallbacks does it?! Maybe I’d attempt to write something similar in flexbox, as hey, maybe there is some small group of browsers still out there that support flexbox and not grid. More likely, I’d just write a fallback that makes things look pretty OK as a column.

If I’m fairly confident the browser supports @supports queries (oh, the irony), I could write it like:

@supports (display: grid) {
  /* grid stuff */
}

@supports not (display: grid) {
  /* at least space them out a bit */
  .block { margin: 10px }
}

That’s an assumption that will get safer and safer to make, and honestly, we’re probably already there (if you’ve dropped IE support).

This makes me want that @when syntax even more though, because then we could write:

@when supports(display: grid) {

} @else {

}

…which feels so fresh and so clean.


The post Quickly Testing CSS Fallbacks appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



source https://css-tricks.com/quickly-testing-css-fallbacks/