I feel like the tech industry takes itself far too seriously sometimes. I get frustrated by all the posturing and gatekeeping – “You’re not a real developer unless you use x framework”, “CSS isn’t a real programming language”.
I think this kind of rhetoric often puts new developers off, and the ones that don’t get put off are more inclined to skip over learning things like semantic markup and accessibility in favour of learning the latest framework.
Having a deeper knowledge of HTML and CSS is often devalued.
Posturing and gatekeeping, indeed. I’ve yet to witness a conversation where discussing what is or isn’t “real” programming was fruitful for anybody.
There have been some aesthetic changes to what form elements look like as of Chrome 83. Anything with gradient colorization is gone (notably the extra-shiny <meter> stuff). The consistency across the board is nice, particularly between inputs and textareas. Not a big fan of the new <select> styling, but I hear a lot of accessibility research went into this, so it’s hard to complain there — plus you can always change it.
The Jetpack plugin for WordPress has a new comparison block and I’m going to try it out here. You can swipe between the items, just for fun (drag the slider in the middle):
This is not accompanied by new standardized ways to change the look of form elements with CSS, although browsers are well aware of that and seem to draw nearer and nearer all the time. I believe is was a step along that path.
I also see there is a new <input type="time"> as well. The old version looked like this and offered no UI controls:
Now we get this beast with controls:
There are no visual indicators or buttons, but you can scroll those columns.
Reddit notes that it uses the same pseudo element that date pickers use, so if you want it gone, you can scope it to these types of inputs (or not) and remove it.
I’d call it an improvement (I like UI controls for things), but it does continue to highlight the need to be able to style these things, particularly if the goal is to have people actually use them and not (poorly) rebuild them.
The time to use our platforms and privilege to speak out against the deep racism that plagues our society was years ago. I regret staying silent in those moments. The next best time is now. Silence is harmful because it prioritizes the comfort of those of us who benefit from racist policies at the expense of those exploited and victimized by them.
It's not enough to simply "do no harm" or "not be racist." That well-trodden path has produced the same brutal results again and again. At Moz, we’re moving to a higher standard. The creation of a more just world requires us to be loudly, unceasingly anti-racist.
We must acknowledge that human rights exist beyond politics.
We must hear and validate the lived experiences of people of color and amplify their voices.
We must show up.
We must reinforce, loudly and often, that Black lives matter.
This is an uncomfortable conversation for most of us. We’re afraid of saying the wrong thing, offending people, losing relationships, jobs, customers, and in some cases physical safety. By design, white supremacy has made it uncomfortable to speak out against white supremacy. Fearing angry backlash for speaking out against the risks and injustices people of color face every single day only serves a system designed to keep us silent — a system that has been shaped over centuries to oppress and exploit people who are not white. At Moz, we will practice the courage to speak out and show up for love and justice. Maya Angelou said wisely, “Courage is the most important of all the virtues, because without courage you can’t practice any other virtue consistently.”
Today, we express solidarity with Black people grieving the losses of David McAtee, George Floyd, Breonna Taylor, Ahmaud Arbery, and many, many others. We share and honor the outrage rippling through our country. We stand with you and we stand for justice and love.
We want to amplify the signal of inspiring people doing powerful work. Activists like Rachel Cargle and her work on The Great Unlearn project. Resources like the Intentionalist, an online directory that allows you to discover and patronize diverse local businesses in your community. Ijeoma Oluo’s So You Want to Talk About Race illuminates the harsh reality of police brutality, inequitable mass incarceration, and other lived experiences of Black people in the United States and gives us tools to talk about race and racism. EmbraceRace is an organization focused on helping parents, teachers, and community leaders raise children to think and act critically against racial injustice. Ibram X. Kendi's How to Be an Anti-Racist asks us to think about what an anti-racist society might look like, and how we can play an active role in building it. Ross Gay's poem, A Small Needful Fact, is a powerful memorial that says so much in a few beautiful words. I invite everyone to re-read or listen toMartin Luther King Jr.'s full Letter From a Birmingham Jail. His statements and questions are heartbreakingly relevant today. May you be moved beyond thought to action, as we are.
Be well and love each other.
Editor's note:We're disallowing comments on this post to make sure the focus remains on the problem at hand: the indiscriminate mistreatment and murder of Black people in the United States. In addition, we will be forgoing our typical publishing schedule to make space for the more critical conversations that need to be held.
Sign up for The Moz Top 10, a semimonthly mailer updating you on the top ten hottest pieces of SEO news, tips, and rad links uncovered by the Moz team. Think of it as your exclusive digest of stuff you don't have time to hunt down but want to read!
from The Moz Blog https://ift.tt/3cmlv7m
via IFTTT
If you’ve ever wanted to add a pause between each iteration of your CSS @keyframes animation, you’ve probably been frustrated to find there’s no built-in way to do it in CSS. Sure, we can delay the start of a set of @keyframes with animation-delay, but there’s no way to add time between the first iteration through the keyframes and each subsequent run.
This came up when I wanted to adapt this shooting stars animation for use as the background of the homepage banner in a space-themed employee portal. I wanted to use fewer stars to reduce distraction from the main content, keep CPUs from melting, and still have the shooting stars seem random.
This approach involves figuring out how long we want the delay between iterations to be, and then compressing the keyframes to a fraction of 100%. Then, we maintain the final state of the animation until it reaches 100% to achieve the pause.
@keyframes my-animation {
/* Animation happens between 0% and 50% */
0% {
width: 0;
}
15% {
width: 100px;
}
/* Animation is paused/delayed between 50% and 100% */
50%, 100% {
width: 0;
}
}
I experienced the main drawback of this approach: each keyframe has to be manually tweaked, which is mildly painful and certainly prone to error. It’s also harder to understand what the animation is doing if it requires mentally transposing all the keyframes back up to 100%.
New technique: hide during the delay
Another technique is to create a new set of @keyframes that is responsible for hiding the animation during the delay. Then, apply that with the original animation, at the same time.
.target-of-animation {
animation: my-awesome-beboop 1s, pause-between-iterations 4s;
}
@keyframes my-awesome-beboop {
...
}
@keyframes pause-between-iterations {
/* Other animation is visible for 25% of the time */
0% {
opacity: 1;
}
25% {
opacity: 1;
}
/* Other animation is hidden for 75% of the time */
25.1% {
opacity: 0;
}
100% {
opacity: 0;
}
}
A limitation of this technique is that the pause between animations must be an integer multiple of the “paused” keyframes. That’s because keyframes that repeat infinitely will immediately execute again, even if there are longer running keyframes being applied to the same element.
Interesting aside: When I started this article, I mistakenly thought that an easing function is applied at 0% and ends at 100%.. Turns out that the easing function is applied to each CSS property, starting at the first keyframe where a value is defined and ending at the next keyframe where a value is defined (e.g., an easing curve would be applied from 25% to 75%, if the keyframes were 25% { left: 0 } 75% { left: 50px}). In retrospect, this totally makes sense because it would be hard to adjust your animation if it was a subset of the total easing curve, but my mind is slightly blown.
In the my-awesome-beboop keyframes example above, my-awesome-beboop will run three times behind the scenes during the pause-between-animations keyframes before being revealed for what appears to be its second loop to the user (which is really the fifth time it’s been executed).
Here’s an example that uses this to add a delay between the shooting stars:
Can’t hide your animation during the delay?
If you need to keep your animation on screen during the delay, there is another option besides hiding. You can still use a second set of @keyframes, but animate a CSS property in a way that counteracts or nullifies the motion of the primary animation. For example, if your main animation uses translateX, you can animate left or margin-left in your set of delay @keyframes.
Here’s a couple of examples:
Pause by changing transform-origin:
Pause by counter-acting transform: translateX by animating the left property:
In the case of the pausing the translateX animation, you’ll need to get fancier with the @keyframes if you need to pause the animation for more than just a single iteration:
You may get some slight jitter during the pause. In the translateX example above, there’s some minor vibration on the ball during the slide-left-pause as the animations fight each other for dominance.
Wrap up
The best option performance-wise is to hide the element during the delay or animate transform. Animating properties like left, margin, width are much more intense on a processor than animating opacity (although the contain property appears to be changing that).
If you have any insights or comments on this idea, let me know!
Fresh from the Jetpack team at Automattic, today, comes Jetpack Scan. Jetpack Scan scans all the files on your site looking for anything suspicious or malicious and lets you know, or literally fixes it for you with your one-click approval.
This kind of security scanning is very important to me. It’s one of those sleep better at night features, where I know I’m doing all I can do for the safety of my site.
It’s not fun to admit, but I bet in my decade-and-a-half of building WordPress sites, I’ve had half a dozen of them probably have some kind of malicious thing happen. It’s been a long time because I know more, take security way more seriously, and use proper tooling like this to make sure it can’t. But an example is that a malicious actor somehow edits files on your site. One edit to your wp-config.php file could easily take down your site. One edit to your single.php file could put malicious/spammy content on every single blog post. One sketchy plugin can literally do anything to your site. I want to know when any foul play is detected like this.
The new Jetpack.com Dashboard
I’m comforted by the idea that it is Automattic themselves who are checking my site every day and making sure it is clean. Aside from the fact that this is a paid service so they have all that incentive to make sure this does its job, they have the reputation of WordPress itself to uphold here, which is the kind of alignment I like to see in products.
If you’re a user or are familiar with VaultPress, which did backups and security scans, this is an evolution of that. This brings that world into a new dashboard on Jetpack.com (for scans and backup), meaning you can manage all this right from there. Note that this dashboard is for new customers of Jetpack Scan and Backup right now and will soon be available for all existing customers also.
Our page going into the many features of Jetpack we use on this site.
This is also another step toward more à la carte offerings from Jetpack. If you only want this feature and not anything else Jetpack offers, well, you’re in luck. Just like backups, that’s how this feature is sold. Want it? Pay just for it. Don’t want it? Don’t pay for it.
The intro offer (limited time) is $7/month or $70/year. So getting Jetpack Scan right away is your best value.
Rotated <table> column headers is something that’s been covered before right here on CSS-Tricks, so shout-out to that for getting me started and helping me achieve this effect. As the article points out, if you aren’t using trigonometry to calculate your table styles, you’ll have to rely on magic numbers and your table will be brittle and any dreams of responsiveness crushed.
Fortunately, in this case, we can take the trigonometry out and replace it with some careful geometry and our magic numbers all turn into 0 (a truly magical number).
For those in a hurry, here is the CSS (it’s very similar to the styles in the other article). Below is a thorough walk-through.
table {
border-collapse: collapse;
--table-border-width: 1px;
}
th.rotate {
white-space: nowrap;
position: relative;
}
th.rotate > div {
/* place div at bottom left of the th parent */
position: absolute;
bottom: 0;
left: 0;
/* Make sure short labels still meet the corner of the parent otherwise you'll get a gap */
text-align: left;
/* Move the top left corner of the span's bottom-border to line up with the top left corner of the td's border-right border so that the border corners are matched
* Rotate 315 (-45) degrees about matched border corners */
transform:
translate(calc(100% - var(--table-border-width) / 2), var(--table-border-width))
rotate(315deg);
transform-origin: 0% calc(100% - var(--table-border-width));
width: 100%;
}
th.rotate > div > span {
/* make sure the bottom of the span is matched up with the bottom of the parent div */
position: absolute;
bottom: 0;
left: 0;
border-bottom: var(--table-border-width) solid gray;
}
td {
border-right: var(--table-border-width) solid gray;
/* make sure this is at least as wide as sqrt(2) * height of the tallest letter in your font or the headers will overlap each other*/
min-width: 30px;
padding-top: 2px;
padding-left: 5px;
text-align: right;
}
Let’s unpack this table and see what’s going on. The magic starts with that funny chain of HTML tags. We’re putting a <span> inside of a <div> inside of our <th>. Is this all really necessary? Between how borders behave, the positioning flexibility we need, and what determines the width of a table column… yes, they each have a purpose and are necessary.
Let’s see what happens if we rotate the <th> directly:
Ignoring the fact that we haven’t corrected position, there are two big issues here:
The column width is still calculated from the header length which is what we were trying to avoid.
Our border didn’t come with us in the rotation, because it is actually part of the table.
These problems aren’t so difficult to fix. We know that if the <th> has a child element with a border, the browser won’t treat that border as part of the table. Further, we know that absolutely-positioned elements are taken out of the document flow and won’t affect the parent’s width. Enter <div> tag, stage left…and right, I guess.
Now our headers don’t influence the column width and the borders are rotated. We just need to line things up.
It’s easier to tell in the image with the rotated <th> elements, but that rotation is happening around the center of the element (that’s the default behavior of transform-origin). It is only another transform in x and y to get it to the right spot, but this is where we’d need trigonometry to figure out just how much x and y to line it up with the column borders. If we instead carefully choose the point to rotate the header about, and use transform-origin to select it, then we can end up with distances that are more straightforward than magic numbers.
The animation below helps illustrate what we’re going to do to avoid complicated math. The black dot in the top left of the blue border needs to match the red dot on the right border of the table column and rotate about it. Then there won’t be any gaps between the two borders.
It’s not helpful to start going somewhere if you don’t know where you are. The absolute positioning is going to help us out with this. By specifying bottom: 0; left: 0; on the <div>, it ends up at the bottom left of the parent <th>. This means the <div> border’s bottom-left corner is sitting on top of the left column border and halfway through it. From here, it’s apparent we need to move down one border width and over one cell width, but how are we going to get that responsively? It’s at this very moment you may recall that we haven’t added the <span> yet — we’re going to need it!
We’ll use the <div> to “figure out” how big the table cells are and the <span> to actually hold the text and position it absolutely as well to overflow the parent.
th.rotate{
white-space: nowrap;
position: relative;
}
th.rotate > div {
position: absolute;
bottom: 0;
left: 0;
width: 100%; /* <- now the div parent is as wide as the columns */
}
th.rotate > div > span {
position: absolute;
bottom: 0;
left: 0;
border-bottom: 1px solid gray;
}
Great! When we set the width of the <div> to 100%, it holds the information for how big the column is regardless of what the content is in the table cells. With this in place, we can easily translate things over by the width of the <div> — but don’t forget that we need to shave off a half border width. Our translation becomes:
The <div> is now in the right spot to rotate, but we have to make sure to pick the correct transform-origin. We want it to be on the top-left corner of the border, which will be on the left and up one border’s width from the bottom of our <div> element:
Note that transformations happen after everything is placed. That means the rotated headers will overflow onto everything as best they can. You will need to wrap the whole table in something to compensate for the unexpected height. I put the title and table together in a flexbox <div> and set the flex-basis of the title to a value large enough to compensate for the tall headers.
Snook shows off a classic design with an oversized header up top, and a content area that is “pulled up” into that header area. My mind goes to the same place:
Historically, I’ve done this with negative margins. The header has a height that adds a bunch of padding to the bottom and then the body gets a margin-top: -50px or whatever the design calls for.
If you match the margin and padding with a situation like this, it’s not exactly magic numbers, but it still doesn’t feel great to me beaus they’re still numbers you need to keep in sync across totally different elements.