Most of the time you don’t really care about whether a user is actively engaged or temporarily inactive on your application. Inactive, meaning, perhaps they got up to get a drink of water, or more likely, changed tabs to do something else for a bit. There are situations, though, when tracking the user activity and detecting inactive-ness might be handy.
Let’s think about few examples when you just might need that functionality:
tracking article reading time
auto saving form or document
auto pausing game
hiding video player controls
auto logging out users for security reasons
I recently encountered a feature that involved that last example, auto logging out inactive users for security reasons.
Why should we care about auto logout?
Many applications give users access to some amount of their personal data. Depending on the purpose of the application, the amount and the value of that data may be different. It may only be user’s name, but it may also be more sensitive data, like medical records, financial records, etc.
There are chances that some users may forget to log out and leave the session open. How many times has it happened to you? Maybe your phone suddenly rang, or you needed to leave immediately, leaving the browser on. Leaving a user session open is dangerous as someone else may use that session to extract sensitive data.
One way to fight this issue involves tracking if the user has interacted with the app within a certain period of time, then trigger logout if that time is exceeded. You may want to show a popover, or perhaps a timer that warns the user that logout is about to happen. Or you may just logout immediately when inactive user is detected.
Going one level down, what we want to do is count the time that’s passed from the user’s last interaction. If that time period is longer than our threshold, we want to fire our inactivity handler. If the user performs an action before the threshold is breached, we reset the counter and start counting again.
This article will show how we can implement such an activity tracking logic based on this example.
Step 1: Implement tracking logic
Let’s implement two functions. The first will be responsible for resetting our timer each time the user interacts with the app, and the second will handle situation when the user becomes inactive:
resetUserActivityTimeout – This will be our method that’s responsible for clearing the existing timeout and starting a new one each time the user interacts with the application.
inactiveUserAction – This will be our method that is fired when the user activity timeout runs out.
let userActivityTimeout = null;
function resetUserActivityTimeout() {
clearTimeout(userActivityTimeout);
userActivityTimeout = setTimeout(() => {
inactiveUserAction();
}, INACTIVE_USER_TIME_THRESHOLD);
}
function inactiveUserAction() {
// logout logic
}
OK, so we have methods responsible for tracking the activity but we do not use them anywhere yet.
Step 2: Tracking activation
Now we need to implement methods that are responsible for activating the tracking. In those methods, we add event listeners that will call our resetUserActivityTimeout method when the event is detected. You can listen on as many events as you want, but for simplicity, we will restrict that list to a few of the most common ones.
That’s it. Our user tracking is ready. The only thing we need to do is to call the activateActivityTracker on our page load.
We can leave it like this, but if you look closer, there is a serious performance issue with the code we just committed. Each time the user interacts with the app, the whole logic runs. That’s good, but look closer. There are some types of events that are fired an enormous amount of times when the user interacts with the page, even if it isn’t necessary for our tracking. Let’s look at mousemove event. Even if you move your mouse just a touch, mousemove event will be fired dozens of times. This is a real performance killer. We can deal with that issue by introducing a throttler that will allow the user activity logic to be fired only once per specified time period.
Let’s do that now.
Step 3: Improve performance
First, we need to add one more variable that will keep reference to our throttler timeout.
let userActivityThrottlerTimeout = null
Then, we create a method that will create our throttler. In that method, we check if the throttler timeout already exists, and if it doesn’t, we create one that will fire the resetUserActivityTimeout after specific period of time. That is the period for which all user activity will not trigger the tracking logic again. After that time the throttler timeout is cleared allowing the next interaction to reset the activity tracker.
We just created a new method that should be fired on user interaction, so we need to remember to change the event handlers from resetUserActivityTimeout to userActivityThrottler in our activate logic.
Now that we have our activity tracking logic implemented let’s see how can move that logic to an application build with Vue. We will base the explanation on this example.
First we need to move all variables into our component’s data, that is the place where all reactive props live.
Since we are using Vue and it’s reactive system, we can drop all direct DOM manipulations i.(i.e. document.getElementById("app").innerHTML) and depend on our isInactive data property. We can access the data property directly in our component’s template like below.
Last thing we need to do is to find a proper place to activate the tracking logic. Vue comes with component lifecycle hooks which are exactly what we need — specifically the beforeMount hook. So let’s put it there.
There is one more thing we can do. Since we are using timeouts and register event listeners on window, it is always a good practice to clean up a little bit after ourselves. We can do that in another lifecycle hook, beforeDestroy. Let’s remove all listeners that we registered and clear all timeouts when the component’s lifecycle comes to an end.
This example concentrates purely on detecting user interaction with the application, reacting to it and firing a method when no interaction is detected within specific period of time. I wanted this example to be as universal as possible, so that’s why I leave the implementation of what should happened when an inactive user it detected to you.
I hope you will find this solution useful in your project!
Facebook actually hides 'dummy’ DOM nodes between the 'Sponsored’ text. These values are entirely random characters, with a random number of DOM nodes between them. Invisible characters. At this point our CSS ad blocker is completely broken. There is no way for us to possibly code every possible value in CSS.
We’ve covered this before when Mike Pan noted it. Looks like it’s evolved a bit since then, getting even a little tricker.
I just opened my Facebook and selected „Copy Outer HTML” on the word „Sponsored”:
I guess we shouldn’t be terribly surprised at Facebook being user-hostile. I can imagine a workplace environment where fighting against ad blockers is turned into this fun kinda cat-and-mouse technological tennis match. But what they are fighting against is people wanting to exert a little control over what they allow into their eyes, ears, and brains.
It’s worth noting that nothing else in the DOM helps identify a post as an ad. So in that sense it’s just like how Google has evolved SERPs in how ads look just like organic results aside from a tiny „AD” before the URL.
We run sponsored posts here on CSS-Tricks too, so please feel free to hold our feet to the fire of accountability if you feel sponsored posts aren’t clear enough.
We just covered The Current State of Styling Selects in 2019, but we didn’t get nearly as far and fancy as Julie Grundy gets here. There is a decent chunk of JavaScript that powers it, so I’m still very much eyeballing browsers’ recent interest in giving us more powerful selects in (presumably) just HTML and CSS.
I tossed a fork on CodePen in case you just wanna see the final result.
This is also the first article in the 2019 edition of 24 Ways, the long-running and wonderful annual advent calendar for developers that is worth reading every single year.
Have you ever looked at a site and knew exactly what CMS powers it? You might see a distinctive design aesthetic that gives it away. Or maybe it’s something even less obvious and even harder to articulate, but you know it when you see it.
That seems true with just about any platform, especially those that rely on a set of templates. If you were to jump from one site ot another on the same platform, you can see the similarities, sort of like walking down the street of a neighborhood where all the homes are designed by the same architect.
It’s not a bad thing. But like homes, we tend to want websites with personality and that feel unique. That’s one of the things that makes WordPress.com a nice hosted platform option.
Yes, it has core themes, some of which are commonly used. What it also has is hundreds of others, including 110 themes that are free. The designs range from portfolio- and business-themed sites to ones themed around traditional blogs, weddings, travel, music, and food. There’s so many to choose from, and they’re introducing more every year. Take a look through some live sites using WordPress.com. The variety is awesome and showcases the many possibilities of WordPress as a content management system.
We’ve said it before: if you can build a site with WordPress.com, you should build a site on WordPress.com. We’re proud to have WordPress as a sponsor here at CSS-Tricks and wouldn’t hesitate to recommend it to anyone who needs a quick and easy way to spin up a site. Plus, with a free plan tier, it’s even easier to get started.
It’s all too common to see the incorrect HTML used for quotes in markup. In this article, let’s dig into all this, looking at different situations and different HTML tags to handle those situations.
There are three major HTML elements involved in quotations:
<blockquote>
<q>
<cite>
Let’s take a look.
Blockquotes
Blockquote tags are used for distinguishing quoted text from the rest of the content. My tenth grade English teacher drilled it into my head that any quote of four lines or longer should be set apart this way. The HTML spec has no such requirement, but as long as the text is a quote and you want it to be set apart from the surrounding text and tags, a blockquote is the semantic choice.
By default, browsers indent blockquotes by adding margin on each side.
As a flow element (i.e. “block level” element), blockquote can contain other elements inside it. For example, we can drop paragraphs in there with no problem:
<blockquote>
<p></p>
<p></p>
</blockquote>
But it could be other elements, too, like a heading or an unordered list:
It’s important to note that blockquotes should only be used for quotations rather than as a decorative element in a design. This also aids accessibility as screen reader users can jump between blockquotes. Thus a blockquote element used solely for aesthetics could really confuse those users. If you need something more decorative that falls outside the bounds of extended quotations, then perhaps a div with a class is the way to go.
blockquote,
.callout-block {
/* These could share styling */
}
Quoting with Q
Q tags (<q>) are for inline quotes, or what my tenth grade teacher would say are those under four lines. Many modern browsers will automatically add quotation marks to the quote as pseudo elements but you may need a backup solution for older browsers.
Typical quotation marks are just as valid for inline quotes as the <q> element. The benefits of using <q>, however, are that it includes a cite attribute, automatic handling of quotation marks, and automatic handling of quote levels. <q> elements should not used for sarcasm (e.g. “you would use a <q> tag for sarcasm, wouldn’t you?”), or signifying a word with air quotes (e.g. “awesome” is an “accurate” description of the author). But if you can figure out how to mark up air quotes, please let me know. Because that would be “awesome.”
The citation attribute
Both <q> and blockquotes can use a citation (cite) attribute. This attribute holds a URL that provides context and/or a reference for the quoted material. The spec makes a point of saying that the URL can be surrounded by spaces. (I’m not sure why that’s pointed out, but if you want to anger the semantic code deities, you’ll have to do more than throw spaces around.)
<p>The officer left a note saying <q cite="https://johnrhea.com/summons">You have been summoned to appear on the 4th day of January on charges of attempted reader bribery.</q></p>
That cite attribute isn’t visible to the user by default. You could add it in with a sprinkle of CSS magic like the following demo. You could even fiddle with it further to make the citation appear on hover.
Neither of those options are particularly great. If you need to cite a source such that users can see it and go to it, you should do it in HTML and probably with the <cite> element, which we’ll cover next.
The citation element
The <cite> tag should be used for referencing creative work rather than the person who said or wrote the quote. In other words, it’s not for quotes. Here are the examples from the spec:
<p>My favorite book is <cite>The Reality Dysfunction</cite> by
Peter F. Hamilton. My favorite comic is <cite>Pearls Before
Swine</cite> by Stephan Pastis. My favorite track is <cite>Jive
Samba</cite> by the Cannonball Adderley Sextet.</p>
If the author of this article told you he’d give you a cupcake, and you <cite> him by name, that would be semantically incorrect. Thus no cupcakes would change hands. If you cited the article in which he offered you a cupcake, that would be semantically correct, but since the author wouldn’t do that, you still wouldn’t get a cupcake. Sorry.
By default, browsers italicize cite tags and there’s no requirement that a <q> or <blockquote> be present to use the cite element. If you want to cite a book or other creative work, then slap it in the cite element. The semantic deities will smile on you for not using either <i> or <em> elements.
But where to put the cite element? Inside? Outside? The upside down? If we put it inside the <blockquote> or the <q>, we’re making it part of the quote. That’s forbidden by the spec for just that reason.
<!-- This is apparently wrong -->
<blockquote>
Quote about cupcake distribution from an article
<cite>The Article</cite>
</blockquote>
Putting it outside just feels wrong and also requires you to have an enclosing element like a <div> if you wanted to style them together.
<div class="need-to-style-together">
<blockquote>
Quote about cupcake distribution from an article
</blockquote>
<cite>The Article</cite>
</div>
N.B. If you google this issue you may come across an HTML5 Doctor article from 2013 that contradicts much of what’s laid out here. That said, every time it links to the docs for support, the docs agree with the article you’re currently reading rather than the HTML5 Doctor article. Most likely the docs have changed since that article was written.
Hey, what about the figure element?
One way to mark up a quotation — and in a way that pleases the semantic code deities — is to put the blockquote within a figure element. Then, put the cite element and any other author or citation information in a figcaption.
<figure class="quote">
<blockquote>
But web browsers aren’t like web servers. If your back-end code is getting so big that it’s starting to run noticably slowly, you can throw more computing power at it by scaling up your server. That’s not an option on the front-end where you don’t really have one run-time environment—your end users have their own run-time environment with its own constraints around computing power and network connectivity.
</blockquote>
<figcaption>
— Jeremy Keith, <cite>Mental models</cite>
</figcaption>
</figure>
While this doubles the number of elements needed, there are several benefits:
It’s semantically correct for all four elements.
It allows you to both include and encapsulate author information beyond citing the name of the work.
It gives you an easy way to style the quote without resorting to divs, spans or wretchedness.
Not <dialog>! Those are for attention-grabbing modals. Dialogue, as in, conversational exchanges between people speaking or typing to each other.
Neither <blockquote> nor <q> nor <cite> are to be used for dialogue and similar exchanges between speakers. If you’re marking up dialogue, you can use whatever makes the most sense to you. There’s no semantic way to do it. That said, the spec suggests <p> tags and punctuation with <span> or <b> tags to designate the speaker and <i> tags to mark stage directions.
Accessibility of quotes
From the research I’ve done, screen readers should not have any issue with understanding semantic-deity-approved <q>, <blockquote>, or <cite> tags.
More “ways” to “quote”
You can add quotation marks to a <blockquote> using CSS pseudo elements. The <q> element comes with quotation marks baked in so they need not be added, however adding them as pseudo-elements can be a workaround for older browsers that don’t automatically add them. Since this is how modern browsers add the quotation marks there’s no danger of adding duplicate quotes. New browsers will overwrite the default pseudo elements, and older browsers that support pseudo elements will add the quotes.
But you can’t, like I did, assume that the above will always give you smart opening and closing quotes. Even if the font supports smart quotes, sometimes straight quotes will be displayed. To be safe, it’s better to use the quotes CSS property to up the intelligence on those quotation marks.
Now let’s look at quote levels. The <q> tag will automatically adjust quote levels.
Let’s say you’re in an area that uses the British convention of using single quotes. You could use the CSS quotes rule to put the opening and closing single quotes first in the list. Here’s an example of both ways:
There is no limit to nesting. Those nested <q> elements could even be within a blockquote that’s within a blockquote.
If you add quotation marks to a blockquote, know that the blockquote does not change the quote level the way a <q> tag does. If you expect to have quotes within a blockquote, you may want to add a descendant selector rule to start <q> elements within a blockquote at the single quote level (or double quotes if you follow British conventions).
blockquote q {
quotes: "‘" "’" "“" "”";
}
The last quote level you put in will continue through subsequent levels of quotation. To use the double, single, double, single… convention, add more levels to the CSS quotes property.
Many typography experts will tell you that hanging the quotation marks on blockquotes looks better (and they’re right). Hanging punctuation is, in this case, quotation marks that are pushed out from the text so that the characters of the text line up vertically.
One possibility in CSS is using a slightly negative value on the text-indent property. The exact negative indentation will vary by font, so be sure to double check the spacing with the font you end up using.
blockquote {
text-indent: -0.45em;
}
There is a nicer way to handle this by using the hanging-punctuation CSS property. It’s only supported in Safari at the time of this writing, so we’ll have to progressively enhance:
/* Fallback */
blockquote {
text-indent: -0.45em;
}
/* If there's support, erase the indent and use the property instead */
@supports ( hanging-punctuation: first) {
blockquote {
text-indent: 0;
hanging-punctuation: first;
}
}
Using hanging-punctuation is better because it’s less fiddly. It’ll just work when it can.
Why you’d need to do this, I’m not totally sure, but the quotation marks in a <q> tag are added are pseudo elements in the UA stylesheet, so we’re able to select and style them — including animation — if we need to.
Wait, maybe we just solved the air quotes thing after all.
Cassie Evans has a great intro to motion paths. That is, being able to animate an element along a path. Not just up/down/left/right, but whatever curvy/wiggly/weird path you want.
It’s an interesting subject because there are so many different technologies helping to do it over time. SMIL, JavaScript-powered animation libraries, native JavaScript APIs, and even CSS via offset-path and friends. I think offset-path is funny – it was changed to that name from motion-path as you don’t technically have to apply motion to an element you place on a path in this way.
There’s no clear winner. I’m (perhaps obviously) a fan of doing stuff like this in CSS whenever possible, but the browser support there is essentially Chrome-only. Plus seeing SVG path values in CSS always feels a smidge uncomfortable because of the unitless numbers. SMIL feels like essentially dead technology, but at least then you’re in SVG-land and the paths make good sense in that context. If browser support is vital, you have to use a library.
I do think there is untapped cool design possibility in motion paths. It’s not just for landing space ships, but can be for practical stuff like how a modal enters a page.
Cassie Evans has a great intro to motion paths. That is, being able to animate an element along a path. Not just up/down/left/right, but whatever curvy/wiggly/weird path you want.
It’s an interesting subject because there are so many different technologies helping to do it over time. SMIL, JavaScript-powered animation libraries, native JavaScript APIs, and even CSS via offset-path and friends. I think offset-path is funny – it was changed to that name from motion-path as you don’t technically have to apply motion to an element you place on a path in this way.
There’s no clear winner. I’m (perhaps obviously) a fan of doing stuff like this in CSS whenever possible, but the browser support there is essentially Chrome-only. Plus seeing SVG path values in CSS always feels a smidge uncomfortable because of the unitless numbers. SMIL feels like essentially dead technology, but at least then you’re in SVG-land and the paths make good sense in that context. If browser support is vital, you have to use a library.
I do think there is untapped cool design possibility in motion paths. It’s not just for landing space ships, but can be for practical stuff like how a modal enters a page.
Lynn Fisher walks us step-by-step through the redesign process of her latest outstanding personal website. In this design, increasing the width of the browser window will cause the illustrations on the page crack to open and reveal more within them:
This case study reminded me that Lynn also has an archive of every case study and project that she’s made over the years and that it’s most certainly worth checking out.
Lynn Fisher walks us step-by-step through the redesign process of her latest outstanding personal website. In this design, increasing the width of the browser window will cause the illustrations on the page crack to open and reveal more within them:
This case study reminded me that Lynn also has an archive of every case study and project that she’s made over the years and that it’s most certainly worth checking out.