Ads
Saturday, August 31, 2024
Clear today!
With a high of F and a low of 54F. Currently, it's 68F and Clear outside.
Current wind speeds: 8 from the Southeast
Pollen: 0
Sunrise: August 31, 2024 at 06:19PM
Sunset: September 1, 2024 at 07:23AM
UV index: 0
Humidity: 39%
via https://ift.tt/BPk3qmN
September 1, 2024 at 10:02AM
Friday, August 30, 2024
Clear today!
With a high of F and a low of 54F. Currently, it's 64F and Clear outside.
Current wind speeds: 9 from the Southeast
Pollen: 0
Sunrise: August 30, 2024 at 06:18PM
Sunset: August 31, 2024 at 07:24AM
UV index: 0
Humidity: 49%
via https://ift.tt/UF7tKZ6
August 31, 2024 at 10:02AM
CSSWG Minutes Telecon (2024-08-21)
View Transitions are one of the most awesome features CSS has shipped in recent times. Its title is self-explanatory: transitions between views are possible with just CSS, even across pages of the same origin! What’s more interesting is its subtext, since there is no need to create complex SPA with routing just to get those eye-catching transitions between pages.
What also makes View Transitions amazing is how quickly it has gone from its first public draft back in October 2022 to shipping in browsers and even in some production contexts like Airbnb — something that doesn’t happen to every feature coming to CSS, so it shows how rightfully hyped it is.
That said, the API is still new, so it’s bound to have some edge cases or bugs being solved as they come. An interesting way to keep up with the latest developments about CSS features like View Transitions is directly from the CSS Telecom Minutes (you can subscribe to them at W3C.org).
View Transitions were the primary focus at the August 21 meeting, which had a long agenda to address. It started with a light bug in Chrome regarding the navigation
descriptor, used in every cross-document view transition to opt-in to a view transition.
@view-transition {
navigation: auto | none;
}
Currently, the specs define navigation as an enum type (a set of predefined types), but Blink takes it as a CSSOMString (any string). While this initially was passed as a bug, it’s interesting to see the conversation it sparked on the GitHub Issue:
Actually I think this is debatable, we don’t currently have at rules that use enums in that way, and usually CSSOM doesn’t try to be fully type-safe in this way. e.g. if we add new navigation types and some browsers don’t support them, this would interpret them as invalid rules rather than rules with empty navigation.
The last statement may not look exciting, but it opens the possibility of new navigation
types beyond auto
and none
, so think about what a different type of view transition could do.
And then onto the CSSWG Minutes:
emilio: Is it useful to differentiate between missing auto or none?
noamr: Yes, very important for forward compat. If one browser adds another type that others don’t have yet, then we want to see that there’s a difference between none or invalid
emilio: But then you get auto behavior?
noamr: No, the unknown value is not read for purpose of nav. It’s a vt role without navigation descriptor and no initial value Similar to having invalid rule
So in future implementations, an invalid navigation
descriptor will be ignored, but exactly how is still under debate:
ntim: How is it different from navigation none?
noamr: Auto vs invalid and then auto vs none. None would supersede auto; it has a meaning to not do a nav while invalid is a no-op.
ntim: So none cancels the nav from the prev doc?
noamr: Yes
The none
has the intent to cancel any view transitions from a previous document, while an invalid or empty string will be ignored. In the end, it resolved to return an empty string if it’s missing or invalid.
RESOLVED: navigation is a CSSOMString, it returns an empty string when navigation descriptor is missing or invalid
Onto the next item on the agenda. The discussion went into the view-transition-group
property and whether it should have an order of precedence. Not to confuse with the pseudo-element of the same name (::view-transition-group
) the view-transition-group
property was resolved to be added somewhere in the future. As of right now, the tree of pseudo-elements created by view transitions is flattened:
::view-transition
├─ ::view-transition-group(name-1)
│ └─ ::view-transition-image-pair(name-1)
│ ├─ ::view-transition-old(name-1)
│ └─ ::view-transition-new(name-1)
├─ ::view-transition-group(name-2)
│ └─ ::view-transition-image-pair(name-2)
│ ├─ ::view-transition-old(name-2)
│ └─ ::view-transition-new(name-2)
│ /* and so one... */
However, we may want to nest transition groups into each other for more complex transitions, resulting in a tree with ::view-transition-group
inside others ::view-transition-group
, like the following:
::view-transition
├─ ::view-transition-group(container-a)
│ ├─ ::view-transition-group(name-1)
│ └─ ::view-transition-group(name-2)
└─ ::view-transition-group(container-b)
├─ ::view-transition-group(name-1)
└─ ::view-transition-group(name-2)
So the view-transition-group
property was born, or to be precise, it will be at some point in timer. It might look something close to the following syntax if I’m following along correctly:
view-transition-group: normal | <ident> | nearest | contain;
normal
is contained by the root::view-transition
(current behavior).<ident>
will be contained by an element with a matchingview-transition-name
nearest
will be contained by its nearest ancestor withview-transition-name
.contain
will contain all its descendants without changing the element’s position in the tree
The values seem simple, but they can conflict with each other. Imagine the following nested structure:
A /* view-transition-name: foo */
└─ B /* view-transition-group: contain */
└─ C /* view-transition-group: foo */
Here, B
wants to contain C
, but C
explicitly says it wants to be contained by A
. So, which wins?
vmpstr: Regarding nesting with view-transition-group, it takes keywords or ident. Contain says that all of the view-transition descendants are nested. Ident says same thing but also element itself will nest on the thing with that ident. Question is what happens if an element has a view-transition-group with a custom ident and also has an ancestor set to contain – where do we nest this? the contain one or the one with the ident? noam and I agree that ident should probably win, seems more specific.
<khush>: +1
The conversations continued if there should be a contain
keyword that wins over <ident>
emilio: Agree that this seems desirable. Is there any use case for actually enforcing the containment? Do we need a strong contain? I don’t think so?
astearns: Somewhere along the line of adding a new keyword such as contain-idents?
<fantasai>: “contain-all”
emilio: Yeah, like sth to contain everything but needs a use case
But for now, it was set for <ident>
to have more specificity than contain
PROPOSED RESOLUTION: idents take precedence over contain in view-transition-group
astearns: objections or concerns or questions?
<fantasai>: just as they do for
<ident>
values. (which also apply containment, but only to ‘normal’ elements)RESOLVED: idents take precedence over contain in view-transition-group
Lastly, the main course of the discussion: whether or not some properties should be captured as styles instead of as a snapshot. Right now, view transitions work by taking a snapshot of the “old” view and transitioning to the “new” page. However, not everything is baked into the snapshot; some relevant properties are saved so they can be animated more carefully.
From the spec:
However, properties like
mix-blend-mode
which define how the element draws when it is embedded can’t be applied to its image. Such properties are applied to the element’s corresponding ::view-transition-group() pseudo-element, which is meant to generate a box equivalent to the element.
In short, some properties that depend on the element’s container are applied to the ::view-transition-group
rather than ::view-transition-image-pair()
. Since, in the future, we could nest groups inside groups, how we capture those properties has a lot more nuance.
noamr: Biggest issue we want to discuss today, how we capture and display nested components but also applies to non-nested view transition elements derived from the nested conversation. When we nest groups, some CSS properties that were previously not that important to capture are now very important because otherwise it looks broken. Two groups: tree effects like opacity, mask, clip-path, filters, perspective, these apply to entire tree; borders and border-radius because once you have a hierarchy of groups, and you have overflow then the overflow affects the origin where you draw the borders and shadows these also paint after backgrounds
noamr: We see three options.
- Change everything by default and don’t just capture snapshot but add more things that get captured as ?? instead of a flat snapshot (opacity, filter, transform, bg borders). Will change things because these styles are part of the group but have changed things before (but this is different as it changes observable computed style)
- Add new property
view-transition-style
orview-transition-capture-mode
. Fan of the first as it reminds me oftransform-style
.- To have this new property but give it auto value. If group contains other groups when you get the new mode so users using nesting get the new mode but can have a property to change the behavior If people want the old crossfade behavior they can always do so by regular DOM nesting
Regarding the first option about changing how all view transitions capture properties by default:
bramus: Yes, this would be breaking, but it would break in a good way. Regarding the name of the property, one of the values proposed is cross-fade, which is a value I wouldn’t recommend because authors can change the animation, e.g. to scale-up/ scale-down, etc. I would suggest a different name for the property,
view-transition-capture-mode: flat | layered
Of course, changing how view transitions work is a dilemma to really think about:
noamr: There is some sentiment to 1 but I feel people need to think about this more?
astearns: Could resolve on option 1 and have blink try it out to see how much breakage there is and if its manageable then we’re good and come back to this. Would be resolving one 1 unless it’s not possible. I’d rather not define a new capture mode without a switch
…so the best course of action was to gather more data and decide:
khush: When we prototype we’ll find edge cases. We will take those back to the WG in that case. Want to get this right
noamr: It involves a lot of CSS props. Some of them are captured and not painted, while others are painted. The ones specifically would all be specified
After some more discussion, it was resolved to come back with compat data from browsers, you can read the full minutes at W3C.org. I bet there are a lot of interesting things I missed, so I encourage you to read it.
RESOLVED: Change the capture mode for all view-transitions and specify how each property is affected by this capture mode change
RESOLVED: Describe categorization of properties in the Module Interactions sections of each spec
RESOLVED: Blink will experiment and come back with changes needed if there are compat concerns
CSSWG Minutes Telecon (2024-08-21) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/6vbpX4T
via IFTTT
Paragraphs
I sure do love little reminders about HTML semantics, particularly semantics that are tougher to commit to memory. Scott has a great one, beginning with this markup:
<p>I am a paragraph.</p>
<span>I am also a paragraph.</span>
<div>You might hate it, but I'm a paragraph too.</div>
<ul>
<li>Even I am a paragraph.</li>
<li>Though I'm a list item as well.</li>
</ul>
<p>I might trick you</p>
<address>Guess who? A paragraph!</address>
You may look at that markup and say “Hey! You can’t fool me, only the
<p>
elements are “real” paragraphs!You might even call out such elements as
div
s orspan
s being used as “paragraphs” a WCAG failure.But, if you’re thinking those sorts of things, then maybe you’re not aware that those are actually all “paragraphs”.
It’s easy to forget this since many of those non-paragraph elements are not allowed in between paragraph tags and it usually gets all sorted out anyway when HTML is parsed.
The accessibility bits are what I always come to Scott’s writing for:
Those examples I provided at the start of this post? macOS VoiceOver, NVDA and JAWS treat them all as paragraphs ([asterisks] for NVDA, read on…). […] The point being that screen readers are in step with HTML, and understand that “paragraphs” are more than just the
p
element.
Paragraphs originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/pNj4lKX
via IFTTT
Thursday, August 29, 2024
Mostly Clear today!
With a high of F and a low of 52F. Currently, it's 60F and Clear outside.
Current wind speeds: 6 from the Northeast
Pollen: 0
Sunrise: August 29, 2024 at 06:17PM
Sunset: August 30, 2024 at 07:26AM
UV index: 0
Humidity: 78%
via https://ift.tt/sz2TIXU
August 30, 2024 at 10:02AM
Shipping Tumblr and WordPress
Didya see that Tumblr is getting a WordPress makeover? And it’s not a trivial move:
This won’t be easy. Tumblr hosts over half a billion blogs. We’re talking about one of the largest technical migrations in internet history. Some people think it’s impossible. But we say, “challenge accepted.”
Half a billion blogs. Considering that WordPress already powers somewhere around 40% of all websites (which is much, much higher than 500m) this’ll certainly push that figure even further.
I’m sure there’s at least one suspicious nose out there catching whiffs of marketing smoke though I’m amicable to the possibility that this is a genuine move to enhance a beloved platform that’s largely seen as a past relic of the Flickr era. I loved Tumblr back then. It really embraced the whole idea that a blog can help facilitate better writing with a variety of post formats. (Post formats, fwiw, are something I always wished would be a WordPress first-class citizen but they never made it out of being an opt-in theme feature). Tumblr was the first time I was able to see blogging as more than a linear chain of content organized in reverse chronological order. Blog posts are more about what you write and how you write it than they are when they’re written.
Anyway, I know jobs are a scarce commodity in tech these days and Auttomatic is looking for folks to help with the migration.
I was about to say this “could” be a neat opportunity, but nay, it’s a super interesting and exciting opportunity, one where your work is touching two of the most influential blogging platforms on the planet. I remember interviewing Alex Hollender and Jon Robson after they shipped a design update to Wikipedia and thinking how much fun and learning would come out of a project like that. This has that same vibe to me. Buuuut, make no illusions about it: it’ll be tough.
Shipping Tumblr and WordPress originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/KbGfFqJ
via IFTTT
Wednesday, August 28, 2024
Mostly Cloudy today!
With a high of F and a low of 64F. Currently, it's 77F and Clear outside.
Current wind speeds: 16 from the Southeast
Pollen: 0
Sunrise: August 28, 2024 at 06:16PM
Sunset: August 29, 2024 at 07:27AM
UV index: 0
Humidity: 42%
via https://ift.tt/iowlrfj
August 29, 2024 at 10:02AM
Introducing
I created a little library at work to make those “skeleton screens” that I’m not sure anyone likes. […] We named it
skellyCSS
because… skeletons and CSS, I guess. We still aren’t even really using it very much, but it was fun to do and it was the first node package I made myself (for the most part).
Regardless of whether or not anyone “likes” skeleton screens, they do come up and have their use cases. And they’re probably not something you want to rebuild time and again. Great use for a web component, I’d say! Maybe Ryan can get Uncle Dave to add it to his Awesome Standalones list. 😉
The other reason I’m sharing this link is that Ryan draws attention to the Web Components De-Mystified course that Scott Jehl recently published, something worth checking out of course, but that I needed a reminder for myself.
Introducing <shelly-wc> originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/mseGb0O
via IFTTT
Useful Tools for Creating AVIF Images
AVIF (AV1 Image File Format) is a modern image file format specification for storing images that offer a much more significant file reduction when compared to other formats like JPG, JPEG, PNG, and WebP. Version 1.0.0 of the AVIF specification was finalized in February 2019 and released by Alliance for Open Media to the public.
You save 50% of your file size when compared to JPG and 20% compared to WebP while still maintaining the image quality.
In this article, you will learn about some browser-based tools and command-line tools for creating AVIF images.
Why use AVIF over JPGs, PNGS, WebP, and GIF?
- Lossless compression and lossy compression
- JPEG suffers from awful banding
- WebP is much better, but there’s still noticeable blockiness compared to the AVIF
- Multiple color space
- 8, 10, 12-bit color depth
Caveats
Jake Archibald, wrote an article a few years back on this new image format and also helped us to identify some disadvantages to compressing images, normally you should look out for these two when compressing to AVIF:
- If a user looks at the image in the context of the page, and it strikes them as ugly due to compression, then that level of compression is not acceptable. But, one tiny notch above that boundary is fine.
- It’s okay for the image to lose noticeable detail compared to the original unless that detail is significant to the context of the image.
See also: Addy Osmani at Smashing Magazine goes in-depth on using AVIF and WebP.
Browser Solutions
Squoosh
Squoosh is a popular image compression web app that allows you to convert images in numerous formats to other widely used compressed formats, including AVIF.
Features
- File-size limit: 4MB
- Image optimization settings (located on the right side)
- Download controls – this includes seeing the size of the resulting file and the percentage reduction from the original image
- Free to use
Cloudinary
Cloudinary’s free image-to-AVIF converter is another image tool that doesn’t require any form of code. All you need to do is upload your selected images (PNG, JPG, GIF, etc.) and it returns compressed versions of them. Its API even has more features besides creating AVIF images like its image enhancement and artificially generating filling for images.
I’m pretty sure you’re here because you’re looking for a free and fast converter. So, the browser solution should do.
Features
- No stated file size limit
- Free to use
You can find answers to common questions in the Cloudinary AVIF converter FAQ.
Command Line Solutions
avif-cli
avif-cli
by lovell lets you take your images (PNG, JPEG, etc.) stored in a folder and converts them to AVIF images of your specified reduction size.
Here are the requirements and what you need to do:
- Node.js 12.13.0+
Install the package:
npm install avif
Run the command in your terminal:
npx avif --input="./imgs/*" --output="./output/" --verbose
./imgs/*
– represents the location of all your image files./output/
– represents the location of your output folder
Features
- Free to use
- Speed of conversion can be set
You can find out about more commands via the avif-cli GitHub page.
sharp
sharp is another useful tool for converting large images in common formats to smaller, web-friendly AVIF images.
Here are the requirements and what you need to do:
- Node.js 12.13.0+
Install the package:
npm install sharp
Create a JavaScript file named sharp-example.js
and copy this code:
const sharp = require('sharp')
const convertToAVIF = () => {
sharp('path_to_image')
.toFormat('avif', {palette: true})
.toFile(__dirname + 'path_to_output_image')
}
convertToAVIF()
Where path_to_image
represents the path to your image with its name and extension, i.e.:
./imgs/example.jpg
And path_to_output_image
represents the path you want your image to be stored with its name and new extension, i.e.:
/sharp-compressed/compressed-example.avif
Run the command in your terminal:
node sharp-example.js
And there! You should have a compressed AVIF file in your output location!
Features
- Free to use
- Images can be rotated, blurred, resized, cropped, scaled, and more using
sharp
See also: Stanley Ulili’s article on How To Process Images in Node.js With Sharp.
Conclusion
AVIF is a technology that front-end developers should consider for their projects. These tools allow you to convert your existing JPEG and PNG images to AVIF format. But as with adopting any new tool in your workflow, the benefits and downsides will need to be properly evaluated in accordance with your particular use case.
I hope you enjoyed reading this article as much as I enjoyed writing it. Thank you so much for your time and I hope you have a great day ahead!
Useful Tools for Creating AVIF Images originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/EWj0BSU
via IFTTT
Tuesday, August 27, 2024
Clear today!
With a high of F and a low of 59F. Currently, it's 71F and Clear outside.
Current wind speeds: 8 from the Southeast
Pollen: 0
Sunrise: August 27, 2024 at 06:16PM
Sunset: August 28, 2024 at 07:29AM
UV index: 0
Humidity: 60%
via https://ift.tt/sWyicnL
August 28, 2024 at 10:02AM
Monday, August 26, 2024
Partly Cloudy today!
With a high of F and a low of 58F. Currently, it's 70F and Clear outside.
Current wind speeds: 7 from the South
Pollen: 0
Sunrise: August 26, 2024 at 06:15PM
Sunset: August 27, 2024 at 07:30AM
UV index: 0
Humidity: 60%
via https://ift.tt/LMoIiVN
August 27, 2024 at 10:02AM
Understanding Gutenberg Blocks, Patterns, and Templates
Developers suffer in the great multitudes whom their sacred block-based websites cannot reach.
Johannes Gutenberg (probably)
Long time WordPresser, first time Gutenberger here. I’m a fan even though I’m still anchored to a classic/block hybrid setup. I believe Johanes himself would be, too, trading feather pens for blocks. He was a forward-thinking 15th-century inventor, after all.
My enthusiasm for Gutenberg-ness is curbed at the theming level. I’ll sling blocks all day long in the Block Editor, but please, oh please, let me keep my classic PHP templates and the Template Hierarchy that comes with it. The separation between theming and editing is one I cherish. It’s not that the Site Editor and its full-site editing capabilities scare me. It’s more that I fail to see the architectural connection between the Site and Block Editors. There’s a connection for sure, so the failure of not understanding it is more on me than WordPress.
The WP Minute published a guide that clearly — and succinctly — describes the relationships between WordPress blocks, patterns, and templates. There are plenty of other places that do the same, but this guide is organized nicely in that it starts with the blocks as the lowest-level common denominator, then builds on top of it to show how patterns are comprised of blocks used for content layout, synced patterns are the same but are one of many that are edited together, and templates are full page layouts cobbled from different patterns and a sprinkle of other “theme blocks” that are the equivalent of global components in a design system, say a main nav or a post loop.
The guide outlines it much better, of course:
- Gutenberg Blocks: The smallest unit of content
- Patterns: Collections of blocks for reuse across your site
- Synced Patterns: Creating “master patterns” for site-wide updates
- Synced Pattern Overrides: Locking patterns while allowing specific edits
- Templates: The structural framework of your WordPress site
That “synced pattern overrides” is new to me. I’m familiar with synced patterns (with a giant nod to Ganesh Dahal) but must’ve missed that in the WordPress 6.6 release earlier this summer.
I’m not sure when or if I’ll ever go with a truly modern WordPress full-site editing setup wholesale, out-of-the-box. I don’t feel pressured to, and I believe WordPress doesn’t care one way or another. WordPress’s ultimate selling point has always been its flexibility (driven, of course, by the massive and supportive open-source community behind it). It’s still the “right” tool for many types of projects and likely will remain so as long as it maintains its support for classic, block, and hybrid architectures.
Understanding Gutenberg Blocks, Patterns, and Templates originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/IfoNdka
via IFTTT
Quick Hit #13
Happy birthday, Chris Coyier — and thank you for CSS-Tricks as well as everything you do at CodePen, ShopTalk, Boost, and even your personal blog!
Quick Hit #13 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/o7yTz3V
via IFTTT
Sunday, August 25, 2024
Partly Cloudy today!
With a high of F and a low of 65F. Currently, it's 78F and Partly Cloudy outside.
Current wind speeds: 11 from the South
Pollen: 0
Sunrise: August 25, 2024 at 06:14PM
Sunset: August 26, 2024 at 07:32AM
UV index: 0
Humidity: 41%
via https://ift.tt/HDST73b
August 26, 2024 at 10:02AM
Saturday, August 24, 2024
Showers Early today!
With a high of F and a low of 65F. Currently, it's 77F and Clear outside.
Current wind speeds: 9 from the Southwest
Pollen: 0
Sunrise: August 24, 2024 at 06:13PM
Sunset: August 25, 2024 at 07:33AM
UV index: 0
Humidity: 43%
via https://ift.tt/yf1iEAk
August 25, 2024 at 10:02AM
Friday, August 23, 2024
Partly Cloudy today!
With a high of F and a low of 62F. Currently, it's 71F and Clear outside.
Current wind speeds: 10 from the East
Pollen: 0
Sunrise: August 23, 2024 at 06:12PM
Sunset: August 24, 2024 at 07:35AM
UV index: 0
Humidity: 76%
via https://ift.tt/v7I9LPM
August 24, 2024 at 10:02AM
Quick Hit #12
Giant kudos to Scott Jehl on releasing his new Web Components De-Mystified online course! Eight full hours of training from one of the best in the business.
Quick Hit #12 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/V8oa9J6
via IFTTT
Basic keyboard shortcut support for focused links
Eric gifting us with his research on all the various things that anchors (not links) do when they are in :focus
.
Turns out, there’s a lot!
That’s an understatement! This is an incredible amount of work, even if Eric calls it “dry as a toast sandwich.” Boring ain’t always a bad thing. Let me simply drop in a pen that Dave put together pulling all of Eric’s findings into a table organized to compare the different behaviors between operating systems — and additional tables for each specific platform — because I think it helps frame Eric’s points.
That really is a lot! But why on Earth go through the trouble of documenting all of this?
All of the previously documented behavior needs to be built in JavaScript, since we need to go the synthetic link route. It also means that it is code we need to set aside time and resources to maintain.
That also assumes that is even possible to recreate every expected feature in JavaScript, which is not true. It also leaves out the mental gymnastics required to make a business case for prioritizing engineering efforts to re-make each feature.
There’s the rub! These are the behaviors you’re gonna need to mimic and maintain if veering away from semantic, native web elements. So what Eric is generously providing is perhaps an ultimate argument against adopting frameworks — or rolling some custom system — that purposely abstract the accessible parts of the web, often in favor of DX.
As with anything, there’s more than meets the eye to all this. Eric’s got an exhaustive list at the end there that calls out all the various limitations of his research. Most of those notes sound to me like there are many, many other platforms, edge cases, user agent variations, assistive technologies, and considerations that could also be taken into account, meaning we could be responsible for a much longer list of behaviors than what’s already there.
And yes, this sweatshirt is incredible. Indeed.
Basic keyboard shortcut support for focused links originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/iLaEoC7
via IFTTT
Thursday, August 22, 2024
Thunderstorms Early today!
With a high of F and a low of 60F. Currently, it's 65F and Mostly Cloudy outside.
Current wind speeds: 8 from the Northeast
Pollen: 0
Sunrise: August 22, 2024 at 06:11PM
Sunset: August 23, 2024 at 07:36AM
UV index: 0
Humidity: 94%
via https://ift.tt/HDZJh2V
August 23, 2024 at 10:02AM
Callbacks on Web Components?
A gem from Chris Ferdinandi that details how to use custom events to hook into Web Components. More importantly, Chris dutifully explains why custom events are a better fit than, say, callback functions.
With a typical JavaScript library, you pass callbacks in as part of the instantiate process. […] Because Web Components self-instantiate, though, there’s no easy way to do that.
There’s a way to use callback functions, just not an “easy” way to go about it.
JavaScript provides developers with a way to emit custom events that developers can listen for with the
Element.addEventListener()
method.We can use custom events to let developers hook into the code that we write and run more code in response to when things happen. They provide a really flexible way to extend the functionality of a library or code base.
Don’t miss the nugget about canceling custom events!
Callbacks on Web Components? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/t4ukp0y
via IFTTT
Wednesday, August 21, 2024
Partly Cloudy today!
With a high of F and a low of 63F. Currently, it's 75F and Partly Cloudy outside.
Current wind speeds: 10 from the Southeast
Pollen: 0
Sunrise: August 21, 2024 at 06:10PM
Sunset: August 22, 2024 at 07:38AM
UV index: 0
Humidity: 63%
via https://ift.tt/HC9eUWG
August 22, 2024 at 10:02AM
Quick Hit #11
Hey look at that, the State of CSS Survey for 2024 is open and taking submissions.
Quick Hit #11 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/TbJQEsG
via IFTTT
The Intersection of Speed and Proximity
You ever find yourself in bumper-to-bumper traffic? I did this morning on the way to work (read: whatever cafe I fancy). There’s a pattern to it, right? Stop, go, stop, go, stop… it’s almost rhythmic and harmonious in the most annoying of ways. Everyone in line follows the dance, led by some car upfront, each subsequent vehicle pressed right up to the rear of the next for the luxury of moving a few feet further before the next step.
Have you tried breaking the pattern? Instead of playing shadow to the car in front of me this morning, I allowed space between us. I’d gradually raise my right foot off the brake pedal and depress the gas pedal only once my neighboring car gained a little momentum. At that point, my car begins to crawl. And continue crawling. I rarely had to tap the brakes at all once I got going. In effect, I had sacrificed proximity for a smoother ride. I may not be traveling the “fastest” in line, but I was certainly gliding along with a lot less friction.
I find that many things in life are like that. Getting closest to anything comes with a cost, be it financial or consequence. Want the VIP ticket to a concert you’re stoked as heck about? Pony up some extra cash. Want the full story rather than a headline? Just enter your email address. Want up-to-the-second information in your stock ticker? Hand over some account information. Want access to all of today’s televised baseball games? Pick up an ESPN+ subscription.
Proximity and speed are the commodities, the products so to speak. Closer and faster are what’s being sold.
You may have run into the “law of diminishing returns” in some intro-level economics class you took in high school or college. It’s the basis for a large swath of economic theory but in essence, is the “too much of a good thing” principle. It’s what AMPM commercials have been preaching this whole time.
I’m embedding the clip instead of linking it up because it clearly illustrates the “problem” of having too many of what you want (or need). Dude resorted to asking two teens to reach into his front pocket for his wallet because his hands were full, creeper. But buy on, the commercial says, because the implication is that there’s never too much of a good thing, even if it ends in a not-so-great situation chockfull of friction.
The only and only thing I took away from physics in college — besides gravity force being 9.8 m/s2 — is that there’s no way to have bigger, cheaper, and faster at the same time. You can take two, but all three cannot play together. For example, you can have a spaceship that’s faster and cheaper, but chances are that it ain’t gonna be bigger than a typical spaceship. If you were to aim for bigger, it’d be a lot less cheap, not only for the extra size but also to make the dang heavy thing go as fast as possible. It’s a good rule in life. I don’t have proof of it, but I’d wager Mick Jagger lives by it, or at least did at one time.
Speed. Proximity. Faster and slower. Closer and further. I’m not going to draw any parallels to web development, UX design, or any other front-end thing. They’re already there.
The Intersection of Speed and Proximity originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/EHlNB1S
via IFTTT
Elastic Overflow Scrolling
A client asked if we could mimic the “rubber band” scrolling behavior on many mobile devices. I’m sure you know what I’m talking about. It’s a behavior that already exists and happens automatically in most browsers. In iOS Safari, for example, you’re allowed to scroll beyond the top or bottom edge of the viewport by a few hundred pixels, and letting go snaps the page back in place.
I had heard of some instances where someone might want to prevent the bounce from happening but no one had asked me to implement it, especially in a way that supports devices without a touch interface. I was actually a bit surprised there isn’t an existing CSS property for this. There’s the non-standard -webkit-overflow-scrolling
property but that’s for a different type of “momentum” scrolling. Nor would I want to rely on a non-standard property that’s not on track to become part of the specifications.
OK, so what if we want to force this sort of rubber banding in our work? For starters, we’d need some sort of element acting as a container for content that requires scrolling. From there, we could reach for JavaScript, of course, but that involves adding scroll listeners or a combination of pointerDown
, pointerUp
, and pointerMove
events, not to mention keeping track of positions, inertial movement, etc.
A CSS-only solution would be much more ideal.
Here is a container with a few child elements:
<div class="carousel">
<div class="slides">
<div class="slide">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
<div class="slide">5</div>
</div>
</div>
Let’s get some baseline styles in place, specifically to create a situation where we’re guaranteed to overflow a parent container.
/* Parent container with fixed dimensions for overflow */
.carousel {
width: 200px;
height: 400px;
overflow-x: hidden;
overflow-y: auto;
}
/* Wrapper for slides, stacked in a column */
.slides {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100%;
height: fit-content;
}
/* Each slide is the full width of the carousel */
.slide {
width: 100%;
aspect-ratio: 1;
}
Let’s start by adding some vertical margins. If your container has only one long item, add it to the top and bottom of the child element. If the container has multiple children, you’ll want to add margin
to the top of the first child element and the bottom of the last child element.
.carousel > .slides > .slide:first-child {
margin-top: 100px;
}
.carousel > .slides > .slide:last-child {
margin-bottom: 100px;
}
Great! We can now scroll past the edges, but we need something to snap it back after the user lifts their finger or pointer. For this, we’ll need the scroll-snap-type
and scroll-snap-align
properties
.carousel {
scroll-snap-type: y mandatory;
}
.carousel > .slides > .slide {
scroll-snap-align: start;
}
.carousel > .slides > .slide:first-child {
margin-top: 100px;
}
.carousel > .slides > .slide:last-child {
scroll-snap-align: end;
margin-bottom: 100px;
}
Note that the same applies to a horizontally scrolling element. For that, you’d change things up so that margin
is applied to the element’s left and right edges instead of its top and bottom edges. You’ll also want to change the scroll-snap-type
property’s value from y mandatory
to x mandatory
while you’re at it.
That’s really it! Here’s the final demo:
I know, I know. This isn’t some Earth-shattering or mind-blowing effect, but it does solve a very specific situation. And if you find yourself in that situation, now you have something in your back pocket to use.
Additional resources
- “The inside story of the iconic ‘rubber band’ effect that launched the iPhone” (Cult of Mac)
- “Six things I learnt about iOS Safari’s rubber band scrolling” (Special Agent Squeaky)
- “Scroll Bouncing On Your Websites” (Smashing Magazine)
Elastic Overflow Scrolling originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/Il6KQ5E
via IFTTT
Tuesday, August 20, 2024
Partly Cloudy today!
With a high of F and a low of 64F. Currently, it's 77F and Fair outside.
Current wind speeds: 10 from the South
Pollen: 0
Sunrise: August 20, 2024 at 06:09PM
Sunset: August 21, 2024 at 07:39AM
UV index: 0
Humidity: 57%
via https://ift.tt/1RkKJoN
August 21, 2024 at 10:02AM
RTL Styling 101
A couple of weeks ago I was super excited about publishing my first CSS-Tricks post: “Letter Spacing is Broken. Forget about that though, what’s important is the post’s topic: letter spacing is broken and doesn’t work as the CSS Specification says it should. In a nutshell, instead of spacing the characters evenly, it leaves an unpleasant space at the end of the element.
While this inconsistency between the web and the spec is just a quirk for a Spanish/English speaker like me, for speakers of right-to-left (RTL) languages like Arabic or Hebrew, an annoying space is left at the start or end of a word. Firefox (Gecko) kinda fixes it and rearranges the unnecessary space at the end (in the reading order), but Google and Safari (Blink and Webkit) leave it at the start.
Of course, I wanted to demo this major pain point, but styling RTL content was beyond my CSS power. That’s when I found this life-saver guide by Ahmad Shadeed that covers every major aspect of styling RTL content on the web and best practices to easily internationalize an LTR webpage. A resource that, I think, is a must-read if you are interested in i18n and accessibility in the web.
I may have discovered warm water since this guide goes back to 2018, but I hope those like me who didn’t know about it have fun learning something new!
RTL Styling 101 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/Hu90exN
via IFTTT
Monday, August 19, 2024
Thunderstorms Early today!
With a high of F and a low of 62F. Currently, it's 69F and Rain outside.
Current wind speeds: 11 from the Southeast
Pollen: 0
Sunrise: August 19, 2024 at 06:08PM
Sunset: August 20, 2024 at 07:40AM
UV index: 0
Humidity: 85%
via https://ift.tt/LH1bP2p
August 20, 2024 at 10:02AM
On the Ground at Frostapalooza
I can’t say I would have ever expected to see Jeremy Keith performing the Yeah Yeah Yeahs song “Maps”, but then again, I don’t know what I expected to happen at Frostapalooza.
The Event
Brad Frost, web designer, author of Atomic Design, and an absolute maniac on the bass, celebrated his birthday by putting together a one-night-only benefit concert featuring musical performances by himself and his talented family and friends.
Frostapalooza, held at Mr. Smalls Theatre in Pittsburgh, PA, was an all-ages event where 100% of the proceeds are headed towards two great causes:
- NextStep Pittsburgh: Helping provide accessible rehabilitation for folks with spinal cord injuries and paralysis in Pittsburgh.
- Project Healthy Minds: Providing research and resources to help tackle mental health.
Performances
The variation of musical performances sprawled across the night, covering tracks by Fleetwood Mac, Radiohead, David Bowie and so much more, check out this setlist of all 31 tracks on Spotify.
I loved the performance of Pink Floyd’s classic song, “Money.” As a Floyd fan who will never get to see them live, this was easily the best rendition I could ask for, which included the full lineup of instrumental sections.
Brad was joined on stage by none other than CSS-Tricks founder, Chris Coyier. Chris picked banjo on a few songs, such as Johnny Cash’s “Folsom Prison Blues” and The Band’s “The Weight,” both fantastic.
The stage background prominently displayed visuals out of CodePen demos made by CodePen community members during the set. Check out the Frostapalooza tag on CodePen to see everything that was projected.
Another favorite moment was Brad’s version of “Wake Up” by Arcade Fire, which felt like a perfectly matched song for the evening.
Musicians
If you haven’t caught on yet, many of the folks lending their musical talents to Frostapalooza also happen to be web designers and developers Brad has met and worked with during his career. At times it felt like the Wu-Tang Clan of CSS on stage.
Brad’s family and musicians from his other bands pitched in, such as Elby Brass. Ridiculously impressive! I had never seen a tuba-playing lead vocalist until this night.
You can see the full lineup on the event’s website. But I’ll drop a screenshot in here just for posterity.
Photos! Videos!
Mike Aparicio captured a great video of a group jam on Queen’s “Bohemian Rhapsody” that you’ve got to watch on YouTube. Brian Kardell nabbed this gem of Chris pickin’ on “The Weight”:
The end
Plain and simple, this was a super fun night celebrating music and friends. Happy birthday, Brad, and thanks for putting on an awesome show!
On the Ground at Frostapalooza originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/AquVHW8
via IFTTT
All About JavaScript Loops
Every programming language has loops. Loops perform an operation (i.e., a chunk of work) a number of times, usually once for every item in an array or list, or to simply repeat an operation until a certain condition is met.
JavaScript in particular has quite a few different types of loops. I haven’t even used all of them, so for my own curiosity, I thought I’d do a high-level overview of them. And as it turns out, there are pretty good reasons I haven’t used at least a couple of the different types.
So, for
now let’s spend a while
exploring the different types of loops, what we can do
with each
of one, and why you might use one over another. (You’ll think that little play on words is absolutely hilarious by the end.)
The while
and do...while
loops
First up is the while
loop. It’s the most basic type of loop and has the potential to be the easiest to read and the fastest in many cases. It’s usually used for doing something until a certain condition is met. It’s also the easiest way to make an infinite loop or a loop that never stops. There is also the do...while
statement. Really, the only difference is that the condition is checked at the end versus the beginning of each iteration.
// remove the first item from an array and log it until the array is empty
let queue1 = ["a", "b", "c"];
while (queue1.length) {
let item = queue1.shift();
console.log(item);
}
// same as above but also log when the array is empty
let queue2 = [];
do {
let item = queue2.shift() ?? "empty";
console.log(item);
} while (queue2.length);
The for
loop
Next is the for
loop. It should be the go to way to do something a certain number of times. If you need to repeat an operation, say, 10 times, then use a for
loop instead. This particular loop may be intimidating to those new to programming, but rewriting the same loop in the while
-style loop can help illustrate the syntax make it easier to stick in your mind.
// log the numbers 1 to 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// same thing but as a while loop
let i = 1; // the first part of a for loop
// the second
while (i <= 5) {
console.log(i);
i++; // the third
}
("end");
The for...of
and for await...of
loops
A for...of
loop is the easiest way to loop through an array.
let myList = ["a", "b", "c"];
for (let item of myList) {
console.log(item);
}
They aren’t limited to arrays though. Technically they can iterate through anything that implements what is called an iterable protocol. There are a few built-in types that implement the protocol: arrays, maps, set, and string, to mention the most common ones, but you can implement the protocol in your own code. What you’d do is add a [Symbol.iterator]
method to any object and that method should return an iterator. It’s a bit confusing, but the gist is that iterables are things with a special method that returns iterators; a factory method for iterators if you will. A special type of function called a generator is a function that returns both a iterable and iterator.
let myList = {
*[Symbol.iterator]() {
yield "a";
yield "b";
yield "c";
},
};
for (let item of myList) {
console.log(item);
}
There is the async
version of all the things I just mentioned: async
iterables, async
iterators, and async
generators. You’d use an async
iterable with for await...of
.
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
// this time we're not making an iterable, but a generator
async function* aNumberAMinute() {
let i = 0;
while (true) {
// an infinite loop
yield i++;
// pause a minute
await delay(60_000);
}
}
// it's a generator, so we need to call it ourselves
for await (let i of aNumberAMinute()) {
console.log(i);
// stop after one hour
if (i >= 59) {
break;
}
}
One unobvious thing about for await...of
statement is that you can use it with non-async iterables and it will work just fine. The reverse, however, is not true; you can’t use async
iterables with the for...of
statement.
The forEach
and map
loops
While these are not technically loops per se, you can use them to iterate over a list.
Here is the thing about the forEach
method. Historically it was much slower than using a for
loop. I think in some cases that may not be true anymore, but if performance is a concern, then I would avoid using it. And now that we have for...of
I’m not sure there is much reason to use it. I guess the only reason that it still may come up is if you have a function ready to use as the callback, but you could easily just call that same function from inside the body of for...of
.
forEach
also receives the index for each item though, so that may be a thing you need too. Ultimately, the decision to use it will probably come down to whether any other code you’re working with uses it, but I personally would avoid using it if I’m writing something new.
let myList = ["a", "b", "c"];
for (let item of myList) {
console.log(item);
}
// but maybe if I need the index use forEach
["a", "b", "c"].forEach((item, index) => {
console.log(`${index}: ${item}`);
});
Meanwhile, map
essentially converts one array into another. It still has the same performance impact that forEach
has, but it is a bit nicer to read than the alternative. It’s certainly subjective though, and just like with forEach
you’ll want to do what the rest of your other code is doing. You see it a ton in React and React-inspired libraries as the primary way to loop through an array and output a list of items within JSX.
function MyList({items}) {
return (
<ul>
{items.map((item) => {
return <li>{item}</li>;
})}
</ul>
);
}
The for...in
loop
This list of loops in JavaScript wouldn’t be complete without mentioning the for...in
statement because it can loop through the fields of an object. It visits fields that are inherited through the object’s prototype chain too, though, and I’ve honestly always avoided it for that reason.
That said, if you have an object literal, then for...in
might be a viable way to iterate through the keys of that object. Also it’s worth noting that if you’ve been programming JavaScript for a long time, you may remember that the order of keys use to be inconsistent between browsers, but now the order is consistent. Any key that could be an array index (i.e., positive integers) will be first in ascending order, and then everything else in the order as authored.
let myObject = {
a: 1,
b: 2,
c: 3,
};
for (let k in myObject) {
console.log(myObject[k]);
}
Wrapping up
Loops are something that many programmers use every day, though we may take them for granted and not think about them too much.
But when you step back and look at all of the ways we have to loop through things in JavaScript, it turns out there are several ways to do it. Not only that, but there are significant — if not nuanced — differences between them that can and will influence your approach to scripts.
All About JavaScript Loops originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/p8EwP7o
via IFTTT
Sunday, August 18, 2024
Cloudy today!
With a high of F and a low of 63F. Currently, it's 74F and Partly Cloudy outside.
Current wind speeds: 9 from the Northeast
Pollen: 0
Sunrise: August 18, 2024 at 06:07PM
Sunset: August 19, 2024 at 07:42AM
UV index: 0
Humidity: 73%
via https://ift.tt/W18ekHu
August 19, 2024 at 10:02AM
Saturday, August 17, 2024
Mostly Clear today!
With a high of F and a low of 65F. Currently, it's 79F and Clear outside.
Current wind speeds: 12 from the Southeast
Pollen: 0
Sunrise: August 17, 2024 at 06:06PM
Sunset: August 18, 2024 at 07:43AM
UV index: 0
Humidity: 49%
via https://ift.tt/C159aQs
August 18, 2024 at 10:02AM
Friday, August 16, 2024
Clear today!
With a high of F and a low of 61F. Currently, it's 74F and Clear outside.
Current wind speeds: 9 from the Southeast
Pollen: 0
Sunrise: August 16, 2024 at 06:06PM
Sunset: August 17, 2024 at 07:45AM
UV index: 0
Humidity: 57%
via https://ift.tt/O2p16e7
August 17, 2024 at 10:02AM
CSSWG Minutes Telecon (2024-08-14)
I was just going over the latest CSSWG minutes (you can subscribe to them at W3C.org) and came across a few interesting nuggets I wanted to jot down for another time. The group discussed the CSS Values, CSS Easing, and Selectors modules, but what really caught my eye was adding triggered delays to CSS for things like hover, long taps, and focus states.
The idea stems from an OpenUI proposal, the same group we can thank for raising things like the Popover API and customizable select element. The concept, if I understand it right, is that anytime someone hovers, taps, or focuses on, say, a <button>
for a certain amount of time, we can invoke some sort of thing. A tooltip is the perfect illustration. Hovering over the trigger element, the reasoning goes, is an expression of interest and as web authors, we can do something with that interest, like displaying a tooltip.
Whoa, right?! There’s long been chatter about CSS encroaching on JavaScript territory (isn’t it ironic, don’t you think?). Firing events in response to interaction is quite literally the only thing I use JavaScript for. There’s no mistake about that in the CSSWG, as documented in the minutes:
So. Does this belong in CSS? Or should it be elsewhere? Does the approach make sense? Are there better ideas? Most interested in the last.
[…]
Other question; does this belong in CSS or HTML… maybe this is just a javascript feature? In JS you can determine MQ state and change things so it wouldn’t necessarily be in CSS.
And shortly later:
As you were talking; one thing that I kept thinking of; should developers be customizing the delay at all? Original use case for delay is that hover shouldn’t be instant. But if we don’t allow for customizing we can align to platform delay lengths.
But there’s an excellent point to be made about the way many of us are already doing this with CSS animations (animation-delay
) and transitions (transition-delay
). Sometimes even applying those globally with the Universal Selector or a prefers-*
query.
Things get even hairier when considering how values are defined for this. Are they explicit delays (800ms
), generic keywords (none
/short
/medium
/long
), a custom property, a pseudo-class… something else? I’m glad there’re incredibly smart folks noodling on this stuff.
I think here it would be good to go with time values. CSS is a good place to put it. We have all the ergonomics. The right declarative place to put it.
Whatever the eventual case may be:
I think this sounds reasonable and I’d like to explore it. Unsure if this is the exact shape, but this space seems useful to me.
CSSWG Minutes Telecon (2024-08-14) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/FfCojMu
via IFTTT
Thursday, August 15, 2024
Partly Cloudy today!
With a high of F and a low of 59F. Currently, it's 71F and Clear outside.
Current wind speeds: 8 from the East
Pollen: 0
Sunrise: August 15, 2024 at 06:05PM
Sunset: August 16, 2024 at 07:46AM
UV index: 0
Humidity: 49%
via https://ift.tt/p59aLz6
August 16, 2024 at 10:02AM
How are the `colspan` and `rowspan` attributes different?
Yes, yes. Functionally, they are different. But heck if I didn’t know about the wacky thresholds until Jens Oliver Meiert tooted a pair of quick polls.
According to the HTML Standard:
- If the current cell has a
colspan
attribute, then parse that attribute’s value, and let colspan be the result.
If parsing that value failed, or returned zero, or if the attribute is absent, then let colspan be 1, instead.
If colspan is greater than 1000, let it be 1000 instead.- If the current cell has a
rowspan
attribute, then parse that attribute’s value, and let rowspan be the result.
If parsing that value failed or if the attribute is absent, then let rowspan be 1, instead.
If rowspan is greater than 65534, let it be 65534 instead.
I saw the answers in advance and know I’d have flubbed rowspan
. Apparently, 1000
table columns are plenty of columns to span at once, while 65534
is the magic number for clamping how many rows we can span at a time. Why is the sweet spot for rowspan
6,4543 spans greater than colspan
? There are usually good reasons for these things.
What that reason is, darned if I know, but now I have a little nugget for cocktail chatter in my back pocket.
How are the `colspan` and `rowspan` attributes different? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/h0DYJwv
via IFTTT
Mostly Clear today!
With a high of F and a low of 15F. Currently, it's 14F and Clear outside. Current wind speeds: 13 from the Southwest Pollen: 0 S...
-
So you want an auto-playing looping video without sound? In popular vernacular this is the very meaning of the word GIF . The word has stuck...
-
With a high of F and a low of 31F. Currently, it's 37F and Cloudy outside. Current wind speeds: 7 from the Northeast Pollen: 0 S...
-
Last year , we kicked out a roundup of published surveys, research, and other findings from around the web. There were some nice nuggets in ...