Ads
Friday, March 31, 2023
Clear/Wind today!
With a high of F and a low of 25F. Currently, it's 36F and Clear outside.
Current wind speeds: 13 from the Northwest
Pollen: 0
Sunrise: March 31, 2023 at 06:37PM
Sunset: April 1, 2023 at 07:14AM
UV index: 0
Humidity: 51%
via https://ift.tt/yfBX2kQ
April 1, 2023 at 10:03AM
Thursday, March 30, 2023
Clear/Wind today!
With a high of F and a low of 30F. Currently, it's 50F and Clear outside.
Current wind speeds: 19 from the West
Pollen: 0
Sunrise: March 30, 2023 at 06:39PM
Sunset: March 31, 2023 at 07:13AM
UV index: 0
Humidity: 28%
via https://ift.tt/KkpumEo
March 31, 2023 at 10:03AM
Wednesday, March 29, 2023
Mostly Clear today!
With a high of F and a low of 26F. Currently, it's 32F and Clear outside.
Current wind speeds: 5 from the East
Pollen: 0
Sunrise: March 29, 2023 at 06:40PM
Sunset: March 30, 2023 at 07:12AM
UV index: 0
Humidity: 72%
via https://ift.tt/Uqzj94i
March 30, 2023 at 10:03AM
Tuesday, March 28, 2023
Mostly Clear today!
With a high of F and a low of 25F. Currently, it's 37F and Clear outside.
Current wind speeds: 15 from the Southeast
Pollen: 0
Sunrise: March 28, 2023 at 06:42PM
Sunset: March 29, 2023 at 07:11AM
UV index: 0
Humidity: 34%
via https://ift.tt/TNRat9O
March 29, 2023 at 10:03AM
Monday, March 27, 2023
Mostly Clear today!
With a high of F and a low of 15F. Currently, it's 22F and Clear outside.
Current wind speeds: 9 from the Northwest
Pollen: 0
Sunrise: March 27, 2023 at 06:43PM
Sunset: March 28, 2023 at 07:10AM
UV index: 0
Humidity: 79%
via https://ift.tt/TNRat9O
March 28, 2023 at 10:03AM
Sunday, March 26, 2023
Snow today!
With a high of F and a low of 21F. Currently, it's 29F and Partly Cloudy outside.
Current wind speeds: 11 from the East
Pollen: 0
Sunrise: March 26, 2023 at 06:45PM
Sunset: March 27, 2023 at 07:09AM
UV index: 0
Humidity: 67%
via https://ift.tt/2ErBNXC
March 27, 2023 at 10:03AM
Saturday, March 25, 2023
Clear today!
With a high of F and a low of 16F. Currently, it's 26F and Clear outside.
Current wind speeds: 11 from the Northwest
Pollen: 0
Sunrise: March 25, 2023 at 06:47PM
Sunset: March 26, 2023 at 07:08AM
UV index: 0
Humidity: 66%
via https://ift.tt/2ErBNXC
March 26, 2023 at 10:03AM
Friday, March 24, 2023
Rain to Snow today!
With a high of F and a low of 24F. Currently, it's 33F and Fair outside.
Current wind speeds: 6 from the Southeast
Pollen: 0
Sunrise: March 24, 2023 at 06:48PM
Sunset: March 25, 2023 at 07:07AM
UV index: 0
Humidity: 77%
via https://ift.tt/PtsCELi
March 25, 2023 at 10:03AM
Thursday, March 23, 2023
Rain/Snow today!
With a high of F and a low of 29F. Currently, it's 38F and Mostly Cloudy outside.
Current wind speeds: 9 from the Southeast
Pollen: 0
Sunrise: March 23, 2023 at 06:50PM
Sunset: March 24, 2023 at 07:06AM
UV index: 0
Humidity: 71%
via https://ift.tt/PtsCELi
March 24, 2023 at 10:03AM
Wednesday, March 22, 2023
Mostly Clear today!
With a high of F and a low of 23F. Currently, it's 41F and Fair outside.
Current wind speeds: 14 from the Northwest
Pollen: 0
Sunrise: March 22, 2023 at 06:52PM
Sunset: March 23, 2023 at 07:05AM
UV index: 0
Humidity: 57%
via https://ift.tt/5ToGsyD
March 23, 2023 at 10:03AM
Some Cross-Browser DevTools Features You Might Not Know
I spend a lot of time in DevTools, and I’m sure you do too. Sometimes I even bounce between them, especially when I’m debugging cross-browser issues. DevTools is a lot like browsers themselves — not all of the features in one browser’s DevTools will be the same or supported in another browser’s DevTools.
But there are quite a few DevTools features that are interoperable, even some lesser-known ones that I’m about to share with you.
For the sake of brevity, I use “Chromium” to refer to all Chromium-based browsers, like Chrome, Edge, and Opera, in the article. Many of the DevTools in them offer the exact same features and capabilities as one another, so this is just my shorthand for referring to all of them at once.
Search nodes in the DOM tree
Sometimes the DOM tree is full of nodes nested in nodes that are nested in other nodes, and so on. That makes it pretty tough to find the exact one you’re looking for, but you can quickly search the DOM tree using Cmd
+ F
(macOS) or Ctrl
+ F
(Windows).
Additionally, you can also search using a valid CSS selector, like .red
, or using an XPath, like //div/h1
.
In Chromium browsers, the focus automatically jumps to the node that matches the search criteria as you type, which could be annoying if you are working with longer search queries or a large DOM tree. Fortunately, you can disable this behavior by heading to Settings (F1
) → Preferences → Global → Search as you type → Disable.
After you have located the node in the DOM tree, you can scroll the page to bring the node within the viewport by right-clicking on the nod, and selecting “Scroll into view”.
Access nodes from the console
DevTools provides many different ways to access a DOM node directly from the console.
For example, you can use $0
to access the currently selected node in the DOM tree. Chromium browsers take this one step further by allowing you to access nodes selected in the reverse chronological order of historic selection using, $1
, $2
, $3
, etc.
Another thing that Chromium browsers allow you to do is copy the node path as a JavaScript expression in the form of document.querySelector
by right-clicking on the node, and selecting Copy → Copy JS path, which can then be used to access the node in the console.
Here’s another way to access a DOM node directly from the console: as a temporary variable. This option is available by right-clicking on the node and selecting an option. That option is labeled differently in each browser’s DevTools:
- Chromium: Right click → “Store as global variable”
- Firefox: Right click → “Use in Console”
- Safari: Right click → “Log Element”
Visualize elements with badges
DevTools can help visualize elements that match certain properties by displaying a badge next to the node. Badges are clickable, and different browsers offer a variety of different badges.
In Safari, there is a badge button in the Elements panel toolbar which can be used to toggle the visibility of specific badges. For example, if a node has a display: grid
or display: inline-grid
CSS declaration applied to it, a grid
badge is displayed next to it. Clicking on the badge will highlight grid areas, track sizes, line numbers, and more, on the page.
The badges that are currently supported in Firefox’s DevTools are listed in the Firefox source docs. For example, a scroll
badge indicates a scrollable element. Clicking on the badge highlights the element causing the overflow with an overflow
badge next to it.
In Chromium browsers, you can right-click on any node and select “Badge settings…” to open a container that lists all of the available badges. For example, elements with scroll-snap-type
will have a scroll-snap
badge next to it, which on click, will toggle the scroll-snap
overlay on that element.
Taking screenshots
We’ve been able to take screenshots from some DevTools for a while now, but it’s now available in all of them and includes new ways to take full-page shots.
The process starts by right-clicking on the DOM node you want to capture. Then select the option to capture the node, which is labeled differently depending on which DevTools you’re using.
Repeat the same steps on the html
node to take a full-page screenshot. When you do, though, it’s worth noting that Safari retains the transparency of the element’s background color — Chromium and Firefox will capture it as a white background.
There’s another option! You can take a “responsive” screenshot of the page, which allows you to capture the page at a specific viewport width. As you might expect, each browser has different ways to get there.
- Chromium:
Cmd
+Shift
+M
(macOS) orCtrl
+Shift
+M
(Windows). Or click the “Devices” icon next to the “Inspect” icon. - Firefox: Tools → Browser Tools → “Responsive Design Mode”
- Safari: Develop → “Enter Responsive Design Mode”
Chrome tip: Inspect the top layer
Chrome lets you visualize and inspect top-layer elements, like a dialog, alert, or modal. When an element is added to the #top-layer
, it gets a top-layer
badge next to it, which on click, jumps you to the top-layer container located just after the </html>
tag.
The order of the elements in the top-layer
container follows the stacking order, which means the last one is on the top. Click the reveal
badge to jump back to the node.
Firefox tip: Jump to ID
Firefox links the element referencing the ID attribute to its target element in the same DOM and highlights it with an underline. Use CMD
+ Click
(macOS) or CTRL
+ Click
(Windows) )to jump to the target element with the identifier.
Wrapping up
Quite a few things, right? It’s awesome that there are some incredibly useful DevTools features that are supported in Chromium, Firefox, and Safari alike. Are there any other lesser-known features supported by all three that you like?
There are a few resources I keep close by to stay on top of what’s new. I thought I’d share them with here:
- DevTools Tips (Patrick Brosset): A curated collection of helpful cross-browser DevTools tips and tricks.
- Dev Tips (Umar Hansa): DevTools tips sent to your inbox!
- Can I DevTools?: The Caniuse for DevTools.
Some Cross-Browser DevTools Features You Might Not Know originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/9hlsywQ
via IFTTT
Tuesday, March 21, 2023
Showers Early today!
With a high of F and a low of 27F. Currently, it's 42F and Partly Cloudy outside.
Current wind speeds: 10 from the East
Pollen: 0
Sunrise: March 21, 2023 at 06:53PM
Sunset: March 22, 2023 at 07:04AM
UV index: 0
Humidity: 31%
via https://ift.tt/HiuZRLr
March 22, 2023 at 10:03AM
Monday, March 20, 2023
Clouds Early/Clearing Late today!
With a high of F and a low of 27F. Currently, it's 40F and Partly Cloudy outside.
Current wind speeds: 8 from the East
Pollen: 0
Sunrise: March 20, 2023 at 06:55PM
Sunset: March 21, 2023 at 07:03AM
UV index: 0
Humidity: 36%
via https://ift.tt/HiuZRLr
March 21, 2023 at 10:03AM
Sunday, March 19, 2023
Partly Cloudy today!
With a high of F and a low of 24F. Currently, it's 34F and Clear outside.
Current wind speeds: 8 from the South
Pollen: 0
Sunrise: March 19, 2023 at 06:56PM
Sunset: March 20, 2023 at 07:02AM
UV index: 0
Humidity: 25%
via https://ift.tt/074CdWY
March 20, 2023 at 10:03AM
Saturday, March 18, 2023
Clear today!
With a high of F and a low of 16F. Currently, it's 21F and Clear outside.
Current wind speeds: 5 from the Southeast
Pollen: 0
Sunrise: March 18, 2023 at 06:58PM
Sunset: March 19, 2023 at 07:01AM
UV index: 0
Humidity: 41%
via https://ift.tt/OAfdbhC
March 19, 2023 at 10:03AM
Friday, March 17, 2023
Clear today!
With a high of F and a low of 16F. Currently, it's 25F and Clear outside.
Current wind speeds: 9 from the North
Pollen: 0
Sunrise: March 17, 2023 at 06:59PM
Sunset: March 18, 2023 at 07:00AM
UV index: 0
Humidity: 42%
via https://ift.tt/2NMDAuG
March 18, 2023 at 10:03AM
Thursday, March 16, 2023
Partly Cloudy/Wind today!
With a high of F and a low of 17F. Currently, it's 25F and Fair outside.
Current wind speeds: 8 from the North
Pollen: 0
Sunrise: March 16, 2023 at 07:01PM
Sunset: March 17, 2023 at 06:59AM
UV index: 0
Humidity: 68%
via https://ift.tt/2NMDAuG
March 17, 2023 at 10:03AM
Wednesday, March 15, 2023
Showers/Wind Early today!
With a high of F and a low of 26F. Currently, it's 55F and Mostly Cloudy outside.
Current wind speeds: 12 from the Northwest
Pollen: 0
Sunrise: March 15, 2023 at 07:03PM
Sunset: March 16, 2023 at 06:58AM
UV index: 0
Humidity: 42%
via https://ift.tt/2hoIAXm
March 16, 2023 at 10:03AM
Tuesday, March 14, 2023
Partly Cloudy today!
With a high of F and a low of 37F. Currently, it's 43F and Clear outside.
Current wind speeds: 14 from the Southeast
Pollen: 0
Sunrise: March 14, 2023 at 07:04PM
Sunset: March 15, 2023 at 06:57AM
UV index: 0
Humidity: 45%
via https://ift.tt/2hoIAXm
March 15, 2023 at 10:03AM
Monday, March 13, 2023
Clear today!
With a high of F and a low of 27F. Currently, it's 32F and Clear outside.
Current wind speeds: 14 from the Southeast
Pollen: 0
Sunrise: March 13, 2023 at 07:06PM
Sunset: March 14, 2023 at 06:56AM
UV index: 0
Humidity: 69%
via https://ift.tt/qdLEesv
March 14, 2023 at 10:03AM
Making Calendars With Accessibility and Internationalization in Mind
Doing a quick search here on CSS-Tricks shows just how many different ways there are to approach calendars. Some show how CSS Grid can create the layout efficiently. Some attempt to bring actual data into the mix. Some rely on a framework to help with state management.
There are many considerations when building a calendar component — far more than what is covered in the articles I linked up. If you think about it, calendars are fraught with nuance, from handling timezones and date formats to localization and even making sure dates flow from one month to the next… and that’s before we even get into accessibility and additional layout considerations depending on where the calendar is displayed and whatnot.
Many developers fear the Date()
object and stick with older libraries like moment.js
. But while there are many “gotchas” when it comes to dates and formatting, JavaScript has a lot of cool APIs and stuff to help out!
I don’t want to re-create the wheel here, but I will show you how we can get a dang good calendar with vanilla JavaScript. We’ll look into accessibility, using semantic markup and screenreader-friendly <time>
-tags — as well as internationalization and formatting, using the Intl.Locale
, Intl.DateTimeFormat
and Intl.NumberFormat
-APIs.
In other words, we’re making a calendar… only without the extra dependencies you might typically see used in a tutorial like this, and with some of the nuances you might not typically see. And, in the process, I hope you’ll gain a new appreciation for newer things that JavaScript can do while getting an idea of the sorts of things that cross my mind when I’m putting something like this together.
First off, naming
What should we call our calendar component? In my native language, it would be called “kalender element”, so let’s use that and shorten that to “Kal-El” — also known as Superman’s name on the planet Krypton.
Let’s create a function to get things going:
function kalEl(settings = {}) { ... }
This method will render a single month. Later we’ll call this method from [...Array(12).keys()]
to render an entire year.
Initial data and internationalization
One of the common things a typical online calendar does is highlight the current date. So let’s create a reference for that:
const today = new Date();
Next, we’ll create a “configuration object” that we’ll merge with the optional settings
object of the primary method:
const config = Object.assign(
{
locale: (document.documentElement.getAttribute('lang') || 'en-US'),
today: {
day: today.getDate(),
month: today.getMonth(),
year: today.getFullYear()
}
}, settings
);
We check, if the root element (<html>
) contains a lang
-attribute with locale info; otherwise, we’ll fallback to using en-US
. This is the first step toward internationalizing the calendar.
We also need to determine which month to initially display when the calendar is rendered. That’s why we extended the config
object with the primary date
. This way, if no date is provided in the settings
object, we’ll use the today
reference instead:
const date = config.date ? new Date(config.date) : today;
We need a little more info to properly format the calendar based on locale. For example, we might not know whether the first day of the week is Sunday or Monday, depending on the locale. If we have the info, great! But if not, we’ll update it using the Intl.Locale
API. The API has a weekInfo
object that returns a firstDay
property that gives us exactly what we’re looking for without any hassle. We can also get which days of the week are assigned to the weekend
:
if (!config.info) config.info = new Intl.Locale(config.locale).weekInfo || {
firstDay: 7,
weekend: [6, 7]
};
Again, we create fallbacks. The “first day” of the week for en-US
is Sunday, so it defaults to a value of 7
. This is a little confusing, as the getDay
method in JavaScript returns the days as [0-6]
, where 0
is Sunday… don’t ask me why. The weekends are Saturday and Sunday, hence [6, 7]
.
Before we had the Intl.Locale
API and its weekInfo
method, it was pretty hard to create an international calendar without many **objects and arrays with information about each locale or region. Nowadays, it’s easy-peasy. If we pass in en-GB
, the method returns:
// en-GB
{
firstDay: 1,
weekend: [6, 7],
minimalDays: 4
}
In a country like Brunei (ms-BN
), the weekend is Friday and Sunday:
// ms-BN
{
firstDay: 7,
weekend: [5, 7],
minimalDays: 1
}
You might wonder what that minimalDays
property is. That’s the fewest days required in the first week of a month to be counted as a full week. In some regions, it might be just one day. For others, it might be a full seven days.
Next, we’ll create a render
method within our kalEl
-method:
const render = (date, locale) => { ... }
We still need some more data to work with before we render anything:
const month = date.getMonth();
const year = date.getFullYear();
const numOfDays = new Date(year, month + 1, 0).getDate();
const renderToday = (year === config.today.year) && (month === config.today.month);
The last one is a Boolean
that checks whether today
exists in the month we’re about to render.
Semantic markup
We’re going to get deeper in rendering in just a moment. But first, I want to make sure that the details we set up have semantic HTML tags associated with them. Setting that up right out of the box gives us accessibility benefits from the start.
Calendar wrapper
First, we have the non-semantic wrapper: <kal-el>
. That’s fine because there isn’t a semantic <calendar>
tag or anything like that. If we weren’t making a custom element, <article>
might be the most appropriate element since the calendar could stand on its own page.
Month names
The <time>
element is going to be a big one for us because it helps translate dates into a format that screenreaders and search engines can parse more accurately and consistently. For example, here’s how we can convey “January 2023” in our markup:
<time datetime="2023-01">January <i>2023</i></time>
Day names
The row above the calendar’s dates containing the names of the days of the week can be tricky. It’s ideal if we can write out the full names for each day — e.g. Sunday, Monday, Tuesday, etc. — but that can take up a lot of space. So, let’s abbreviate the names for now inside of an <ol>
where each day is a <li>
:
<ol>
<li><abbr title="Sunday">Sun</abbr></li>
<li><abbr title="Monday">Mon</abbr></li>
<!-- etc. -->
</ol>
We could get tricky with CSS to get the best of both worlds. For example, if we modified the markup a bit like this:
<ol>
<li>
<abbr title="S">Sunday</abbr>
</li>
</ol>
…we get the full names by default. We can then “hide” the full name when space runs out and display the title
attribute instead:
@media all and (max-width: 800px) {
li abbr::after {
content: attr(title);
}
}
But, we’re not going that way because the Intl.DateTimeFormat
API can help here as well. We’ll get to that in the next section when we cover rendering.
Day numbers
Each date in the calendar grid gets a number. Each number is a list item (<li>
) in an ordered list (<ol>
), and the inline <time>
tag wraps the actual number.
<li>
<time datetime="2023-01-01">1</time>
</li>
And while I’m not planning to do any styling just yet, I know I will want some way to style the date numbers. That’s possible as-is, but I also want to be able to style weekday numbers differently than weekend numbers if I need to. So, I’m going to include data-*
attributes specifically for that: data-weekend
and data-today
.
Week numbers
There are 52 weeks in a year, sometimes 53. While it’s not super common, it can be nice to display the number for a given week in the calendar for additional context. I like having it now, even if I don’t wind up not using it. But we’ll totally use it in this tutorial.
We’ll use a data-weeknumber
attribute as a styling hook and include it in the markup for each date that is the week’s first date.
<li data-day="7" data-weeknumber="1" data-weekend="">
<time datetime="2023-01-08">8</time>
</li>
Rendering
Let’s get the calendar on a page! We already know that <kal-el>
is the name of our custom element. First thing we need to configure it is to set the firstDay
property on it, so the calendar knows whether Sunday or some other day is the first day of the week.
<kal-el data-firstday="${ config.info.firstDay }">
We’ll be using template literals to render the markup. To format the dates for an international audience, we’ll use the Intl.DateTimeFormat
API, again using the locale
we specified earlier.
The month and year
When we call the month
, we can set whether we want to use the long
name (e.g. February) or the short
name (e.g. Feb.). Let’s use the long
name since it’s the title above the calendar:
<time datetime="${year}-${(pad(month))}">
${new Intl.DateTimeFormat(
locale,
{ month:'long'}).format(date)} <i>${year}</i>
</time>
Weekday names
For weekdays displayed above the grid of dates, we need both the long
(e.g. “Sunday”) and short
(abbreviated, ie. “Sun”) names. This way, we can use the “short” name when the calendar is short on space:
Intl.DateTimeFormat([locale], { weekday: 'long' })
Intl.DateTimeFormat([locale], { weekday: 'short' })
Let’s make a small helper method that makes it a little easier to call each one:
const weekdays = (firstDay, locale) => {
const date = new Date(0);
const arr = [...Array(7).keys()].map(i => {
date.setDate(5 + i)
return {
long: new Intl.DateTimeFormat([locale], { weekday: 'long'}).format(date),
short: new Intl.DateTimeFormat([locale], { weekday: 'short'}).format(date)
}
})
for (let i = 0; i < 8 - firstDay; i++) arr.splice(0, 0, arr.pop());
return arr;
}
Here’s how we invoke that in the template:
<ol>
${weekdays(config.info.firstDay,locale).map(name => `
<li>
<abbr title="${name.long}">${name.short}</abbr>
</li>`).join('')
}
</ol>
Day numbers
And finally, the days, wrapped in an <ol>
element:
${[...Array(numOfDays).keys()].map(i => {
const cur = new Date(year, month, i + 1);
let day = cur.getDay(); if (day === 0) day = 7;
const today = renderToday && (config.today.day === i + 1) ? ' data-today':'';
return `
<li data-day="${day}"${today}${i === 0 || day === config.info.firstDay ? ` data-weeknumber="${new Intl.NumberFormat(locale).format(getWeek(cur))}"`:''}${config.info.weekend.includes(day) ? ` data-weekend`:''}>
<time datetime="${year}-${(pad(month))}-${pad(i)}" tabindex="0">
${new Intl.NumberFormat(locale).format(i + 1)}
</time>
</li>`
}).join('')}
Let’s break that down:
- We create a “dummy” array, based on the “number of days” variable, which we’ll use to iterate.
- We create a
day
variable for the current day in the iteration. - We fix the discrepancy between the
Intl.Locale
API andgetDay()
. - If the
day
is equal totoday
, we add adata-*
attribute. - Finally, we return the
<li>
element as a string with merged data. tabindex="0"
makes the element focusable, when using keyboard navigation, after any positive tabindex values (Note: you should never add positive tabindex-values)
To “pad” the numbers in the datetime
attribute, we use a little helper method:
const pad = (val) => (val + 1).toString().padStart(2, '0');
Week number
Again, the “week number” is where a week falls in a 52-week calendar. We use a little helper method for that as well:
function getWeek(cur) {
const date = new Date(cur.getTime());
date.setHours(0, 0, 0, 0);
date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
const week = new Date(date.getFullYear(), 0, 4);
return 1 + Math.round(((date.getTime() - week.getTime()) / 86400000 - 3 + (week.getDay() + 6) % 7) / 7);
}
I didn’t write this getWeek
-method. It’s a cleaned up version of this script.
And that’s it! Thanks to the Intl.Locale
, Intl.DateTimeFormat
and Intl.NumberFormat
APIs, we can now simply change the lang
-attribute of the <html>
element to change the context of the calendar based on the current region:
Styling the calendar
You might recall how all the days are just one <ol>
with list items. To style these into a readable calendar, we dive into the wonderful world of CSS Grid. In fact, we can repurpose the same grid from a starter calendar template right here on CSS-Tricks, but updated a smidge with the :is()
relational pseudo to optimize the code.
Notice that I’m defining configurable CSS variables along the way (and prefixing them with ---kalel-
to avoid conflicts).
kal-el :is(ol, ul) {
display: grid;
font-size: var(--kalel-fz, small);
grid-row-gap: var(--kalel-row-gap, .33em);
grid-template-columns: var(--kalel-gtc, repeat(7, 1fr));
list-style: none;
margin: unset;
padding: unset;
position: relative;
}
Let’s draw borders around the date numbers to help separate them visually:
kal-el :is(ol, ul) li {
border-color: var(--kalel-li-bdc, hsl(0, 0%, 80%));
border-style: var(--kalel-li-bds, solid);
border-width: var(--kalel-li-bdw, 0 0 1px 0);
grid-column: var(--kalel-li-gc, initial);
text-align: var(--kalel-li-tal, end);
}
The seven-column grid works fine when the first day of the month is also the first day of the week for the selected locale). But that’s the exception rather than the rule. Most times, we’ll need to shift the first day of the month to a different weekday.
Remember all the extra data-*
attributes we defined when writing our markup? We can hook into those to update which grid column (--kalel-li-gc
) the first date number of the month is placed on:
[data-firstday="1"] [data-day="3"]:first-child {
--kalel-li-gc: 1 / 4;
}
In this case, we’re spanning from the first grid column to the fourth grid column — which will automatically “push” the next item (Day 2) to the fifth grid column, and so forth.
Let’s add a little style to the “current” date, so it stands out. These are just my styles. You can totally do what you’d like here.
[data-today] {
--kalel-day-bdrs: 50%;
--kalel-day-bg: hsl(0, 86%, 40%);
--kalel-day-hover-bgc: hsl(0, 86%, 70%);
--kalel-day-c: #fff;
}
I like the idea of styling the date numbers for weekends differently than weekdays. I’m going to use a reddish color to style those. Note that we can reach for the :not()
pseudo-class to select them while leaving the current date alone:
[data-weekend]:not([data-today]) {
--kalel-day-c: var(--kalel-weekend-c, hsl(0, 86%, 46%));
}
Oh, and let’s not forget the week numbers that go before the first date number of each week. We used a data-weeknumber
attribute in the markup for that, but the numbers won’t actually display unless we reveal them with CSS, which we can do on the ::before
pseudo-element:
[data-weeknumber]::before {
display: var(--kalel-weeknumber-d, inline-block);
content: attr(data-weeknumber);
position: absolute;
inset-inline-start: 0;
/* additional styles */
}
We’re technically done at this point! We can render a calendar grid that shows the dates for the current month, complete with considerations for localizing the data by locale, and ensuring that the calendar uses proper semantics. And all we used was vanilla JavaScript and CSS!
But let’s take this one more step…
Rendering an entire year
Maybe you need to display a full year of dates! So, rather than render the current month, you might want to display all of the month grids for the current year.
Well, the nice thing about the approach we’re using is that we can call the render
method as many times as we want and merely change the integer that identifies the month on each instance. Let’s call it 12 times based on the current year.
as simple as calling the render
-method 12 times, and just change the integer for month
— i
:
[...Array(12).keys()].map(i =>
render(
new Date(date.getFullYear(),
i,
date.getDate()),
config.locale,
date.getMonth()
)
).join('')
It’s probably a good idea to create a new parent wrapper for the rendered year. Each calendar grid is a <kal-el>
element. Let’s call the new parent wrapper <jor-el>
, where Jor-El is the name of Kal-El’s father.
<jor-el id="app" data-year="true">
<kal-el data-firstday="7">
<!-- etc. -->
</kal-el>
<!-- other months -->
</jor-el>
We can use <jor-el>
to create a grid for our grids. So meta!
jor-el {
background: var(--jorel-bg, none);
display: var(--jorel-d, grid);
gap: var(--jorel-gap, 2.5rem);
grid-template-columns: var(--jorel-gtc, repeat(auto-fill, minmax(320px, 1fr)));
padding: var(--jorel-p, 0);
}
Final demo
Bonus: Confetti Calendar
I read an excellent book called Making and Breaking the Grid the other day and stumbled on this beautiful “New Year’s poster”:
I figured we could do something similar without changing anything in the HTML or JavaScript. I’ve taken the liberty to include full names for months, and numbers instead of day names, to make it more readable. Enjoy!
Making Calendars With Accessibility and Internationalization in Mind originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/mNL4Sfd
via IFTTT
Sunday, March 12, 2023
Partly Cloudy today!
With a high of F and a low of 21F. Currently, it's 29F and Partly Cloudy outside.
Current wind speeds: 9 from the East
Pollen: 0
Sunrise: March 12, 2023 at 07:07PM
Sunset: March 13, 2023 at 06:55AM
UV index: 0
Humidity: 54%
via https://ift.tt/qdLEesv
March 13, 2023 at 10:03AM
Saturday, March 11, 2023
Partly Cloudy today!
With a high of F and a low of 22F. Currently, it's 37F and Partly Cloudy outside.
Current wind speeds: 6 from the Northeast
Pollen: 0
Sunrise: March 11, 2023 at 07:09PM
Sunset: March 12, 2023 at 06:54AM
UV index: 0
Humidity: 43%
via https://ift.tt/AsdP64T
March 12, 2023 at 10:03AM
Friday, March 10, 2023
Partly Cloudy today!
With a high of F and a low of 36F. Currently, it's 44F and Clear outside.
Current wind speeds: 11 from the Southeast
Pollen: 0
Sunrise: March 10, 2023 at 07:11PM
Sunset: March 11, 2023 at 06:53AM
UV index: 0
Humidity: 59%
via https://ift.tt/AsdP64T
March 11, 2023 at 10:03AM
5 Mistakes I Made When Starting My First React Project
You know what it’s like to pick up a new language or framework. Sometimes there’s great documentation to help you find your way through it. But even the best documentation doesn’t cover absolutely everything. And when you work with something that’s new, you’re bound to find a problem that doesn’t have a written solution.
That’s how it was for me the first time I created a React project — and React is one of those frameworks with remarkable documentation, especially now with the beta docs. But I still struggled my way through. It’s been quite a while since that project, but the lessons I gained from it are still fresh in my mind. And even though there are a lot of React “how-to” tutorials in out there, I thought I’d share what I wish I knew when I first used it.
So, that’s what this article is — a list of the early mistakes I made. I hope they help make learning React a lot smoother for you.
Using create-react-app to start a project
TL;DR Use Vite or Parcel.
Create React App (CRA) is a tool that helps you set up a new React project. It creates a development environment with the best configuration options for most React projects. This means you don’t have to spend time configuring anything yourself.
As a beginner, this seemed like a great way to start my work! No configuration! Just start coding!
CRA uses two popular packages to achieve this, webpack and Babel. webpack is a web bundler that optimizes all of the assets in your project, such as JavaScript, CSS, and images. Babel is a tool that allows you to use newer JavaScript features, even if some browsers don’t support them.
Both are good, but there are newer tools that can do the job better, specifically Vite and Speedy Web Compiler (SWC).
These new and improved alternatives are faster and easier to configure than webpack and Babel. This makes it easier to adjust the configuration which is difficult to do in create-react-app without ejecting.
To use them both when setting up a new React project you have to make sure you have Node version 12 or higher installed, then run the following command.
npm create vite
You’ll be asked to pick a name for your project. Once you do that, select React from the list of frameworks. After that, you can select either Javascript + SWC
or Typescript + SWC
Then you’ll have to change directory cd
into your project and run the following command;
npm i && npm run dev
This should run a development server for your site with the URL localhost:5173
And it’s as simple as that.
Making a Site Work Offline Using the VitePWA Plugin
Parcel CSS: A New CSS Parser, Transformer, and Minifier
Using Parcel as a Bundler for React Applications
Using defaultProps
for default values
TL;DR Use default function parameters instead.
Data can be passed to React components through something called props
. These are added to a component just like attributes in an HTML element and can be used in a component’s definition by taking the relevant values from the prop object passed in as an argument.
// App.jsx
export default function App() {
return <Card title="Hello" description="world" />
}
// Card.jsx
function Card(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.description}</p>
</div>
);
}
export default Card;
If a default value is ever required for a prop
, the defaultProp
property can be used:
// Card.jsx
function Card(props) {
// ...
}
Card.defaultProps = {
title: 'Default title',
description: 'Desc',
};
export default Card;
With modern JavaScript, it is possible to destructure the props
object and assign a default value to it all in the function argument.
// Card.jsx
function Card({title = "Default title", description= "Desc"}) {
return (
<div>
<h1>{title}</h1>
<p>{description}</p>
</div>
)
}
export default Card;
This is more favorable as the code that can be read by modern browsers without the need for extra transformation.
Unfortunately, defaultProps
do require some transformation to be read by the browser since JSX (JavaScript XML) isn’t supported out of the box. This could potentially affect the performance of an application that is using a lot of defaultProps
.
Demonstrating Reusable React Components in a Form
I Learned How to be Productive in React in a Week and You Can, Too
Props and PropTypes in React
Don’t use propTypes
TL;DR Use TypeScript.
In React, the propTypes
property can be used to check if a component is being passed the correct data type for its props. They allow you to specify the type of data that should be used for each prop such as a string, number, object, etc. They also allow you to specify if a prop is required or not.
This way, if a component is passed the wrong data type or if a required prop is not being provided, then React will throw an error.
// Card.jsx
import { PropTypes } from "prop-types";
function Card(props) {
// ...
}
Card.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string,
};
export default Card;
TypeScript provides a level of type safety in data that’s being passed to components. So, sure, propTypes
were a good idea back when I was starting. However, now that TypeScript has become the go-to solution for type safety, I would highly recommend using it over anything else.
// Card.tsx
interface CardProps {
title: string,
description?: string,
}
export default function Card(props: CardProps) {
// ...
}
TypeScript is a programming language that builds on top of JavaScript by adding static type-checking. TypeScript provides a more powerful type system, that can catch more potential bugs and improves the development experience.
Props and PropTypes in React
Putting Things in Context With React
An Overview of Render Props in React
Using class components
TL;DR: Write components as functions
Class components in React are created using JavaScript classes. They have a more object-oriented structure and as well as a few additional features, like the ability to use the this
keyword and lifecycle methods.
// Card.jsx
class Card extends React.Component {
render() {
return (
<div>
<h1>{this.props.title}</h1>
<p>{this.props.description}</p>
</div>
)
}
}
export default Card;
I prefer writing components with classes over functions, but JavaScript classes are more difficult for beginners to understand and this
can get very confusing. Instead, I’d recommend writing components as functions:
// Card.jsx
function Card(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.description}</p>
</div>
)
}
export default Card;
Function components are simply JavaScript functions that return JSX. They are much easier to read, and do not have additional features like the this
keyword and lifecycle methods which make them more performant than class components.
Function components also have the advantage of using hooks. React Hooks allow you to use state and other React features without writing a class component, making your code more readable, maintainable and reusable.
Importing React unnecessarily
TL;DR: There’s no need to do it, unless you need hooks.
Since React 17 was released in 2020, it’s now unnecessary to import React at the top of your file whenever you create a component.
import React from 'react'; // Not needed!
export default function Card() {}
But we had to do that before React 17 because the JSX transformer (the thing that converts JSX into regular JavaScript) used a method called React.createElement
that would only work when importing React. Since then, a new transformer has been release which can transform JSX without the createElement
method.
You will still need to import React to use hooks, fragments, and any other functions or components you might need from the library:
import { useState } from 'react';
export default function Card() {
const [count, setCount] = useState(0);
// ...
}
Those were my early mistakes!
Maybe “mistake” is too harsh a word since some of the better practices came about later. Still, I see plenty of instances where the “old” way of doing something is still being actively used in projects and other tutorials.
To be honest, I probably made way more than five mistakes when getting started. Anytime you reach for a new tool it is going to be more like a learning journey to use it effectively, rather than flipping a switch. But these are the things I still carry with me years later!
If you’ve been using React for a while, what are some of the things you wish you knew before you started? It would be great to get a collection going to help others avoid the same struggles.
5 Mistakes I Made When Starting My First React Project originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/DKF3G0l
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 ...