101 stories
·
1 follower

Intrusive Interstitials: Guidelines To Avoiding Google’s Penalty

1 Share

   

In 2015, Google announced that mobile searches surpassed desktop searches in at least 10 countries. 56% of traffic on major websites comes from mobile. In light of this, Google’s decision to improve the mobile user experience by various means, such as AMP pages and a dedicated mobile index, comes across as a sound business move.

Intrusive Interstitials: Guidelines To Avoiding Google's Penalty

More than half of the 2 trillion searches Google processes each year come from mobile devices. Mobile devices have changed the way we approach search, ushering in new types of habits such as local search, voice search and more. These consumer habits have greatly affected the way search engine providers think about user search intent.

The post Intrusive Interstitials: Guidelines To Avoiding Google’s Penalty appeared first on Smashing Magazine.

Read the whole story
grudes
17 hours ago
reply
Share this story
Delete

“UX drives all of this.”

1 Share

This little Twitter exchange has stuck in my mind quite a bit.

While I think it's generally advisable to stay away from snarky Twitter arguments, this touches on some interesting stuff that I think a lot of folks are feeling.

Thomas has a point: web development has only gotten more complicated

Listen to any Q&A session at a dev conference and you'll hear this. It's like THE prevailing talking point right now.

This complication isn't to be ignored. People are feeling it. Super smart and competent devs are understandably nervous about it. The implications of super complicated development setups and build processes probably haven't quite shaken out yet.

What does this mean for training new devs? Training old devs? What are the limits of this complication?

Colin has a point: this complication ain't for nothing

First, you don't have to use any newfangled complicated stuff to build a website if you don't want to. The web is a big place. What is necessary for the success of any given website is as diverse as the human beings who live on this planet.

The requirements of a website might be such that you can do a wonderful job with plain HTML and CSS. The web has also done a pretty great job of backwards compatibility. The websites of 1997 and 2007, if they are still around, probably work just as they did then or better, even if the hardware showing them has changed.

So what is the complication all about?

Websites in 2017, compared to 2007 and especially 1997, are being asked to do far more. Do it better. Do it faster. Work anywhere. Look good doing it.

I don't just wanna see the address of the airport, I want to book my flight, pick my seat, then change it three days later, manage my SkyMiles, print my itinerary, be alerted of any changes, and sync it all to my phone (to name 20% of what an airline website offers). And ship it in 3 months, please.

Developers, looking wide-eyed at that list of requirments, have stepped up to the plate saying "we're going to do this, but we're going to build and evolve the tools that are necessary to do it well." Yes, we're building developer convenience tools. You can think of them as complications if you want, and you aren't wrong, but that's not the whole story. These tools allow us to build what you need without making a mess that would be hard to recover from.

The users of the web want a lot. UX drives all this.


“UX drives all of this.” is a post from CSS-Tricks

Read the whole story
grudes
17 days ago
reply
Share this story
Delete

The 9 questions that uncover the most surprising insights from employees

1 Share

I’m sharing three years-worth of findings, based on data from 15,000 employees in 15+ countries through Know Your Company

When’s the last time you had a one-on-one or performance review with an employee… and you learned something completely new?

Don’t think too hard :-) If you’re like most CEOs and managers, getting new, surprising insights from employees doesn’t happen very often. Oftentimes, when we’re asking for honest feedback, we simply receive a confirmation of what we want to hear.

We learn, “Oh okay, it seems like everything is fine” or “I already knew that was an issue, so it’s all good there.

But what about the stuff you don’t know? How do you discern if an employee has an idea to improve the company that she hasn’t brought up yet? How do you figure out if an employee is frustrated with her manager? Or, how can you tell if she’s thinking about leaving?

That’s where we at Know Your Company come in. We’ve spent the past three years researching, writing and refining hundreds of questions across almost 300 companies with 15,000 employees in 15+ countries.

From our 312+Know Your Company questions, below are the best nine that we’ve found to yield the most interesting insights for companies…

#1: “Are you afraid of anything at work?”

Our findings: 67% of employees said, “Yes, I’m afraid of something at work” (753 employees answered this across 89 companies) when asked through Know Your Company. This result caught me off guard (almost 70% of employees are afraid of something at work!) but it goes to show the importance of showing vulnerability as a leader and digging deep to uncover the areas of the company (or people in the company) that employees may feel intimidated by.

#2: “Have you seen something recently and thought to yourself ‘I wish we’d done that’?”

Our findings: 75% of employees said, “Yes, I’ve seen something recently, and thought to myself, ‘I wish we’d done that’ (1,338 employees answered this across 221 companies) when asked through Know Your Company. Clearly, employees are noticing what competitors are doing and may have ideas for you to improve the business. Asking this question helps bring to light what those ideas are.

#3: “Is there something we should measure in the company that we currently don’t?”

Our findings: 78% of employees said, “Yes, there’s something we should measure in the company that we currently don’t” (286 employees answered this across 78 companies) when asked through Know Your Company. This reveals a need to more closely examine the metrics we use to run our businesses, and ask employees if there’s anything not being measured that should be.

#4: “Is there any part of the company you wish you were able to interact with more?”

Our findings: 81% of employees said, “Yes, there’s a part of the company I wish I were able to interact with more” (507 employees answered this across 72 companies) when asked through Know Your Company. An overwhelming majority of the employees we surveyed feel silo-ed. By asking this question, you’ll learn exactly which parts of the company they’d like more interaction with, be it a specific department or office.

#5: “Are there any benefits we don’t offer that you’d like to see us offer?”

Our findings: 76% said “Yes, there are benefits we don’t offer that I’d like to see us offer” (1,807 employees answered this across 179 companies) when asked through Know Your Company. You may be thinking, “Ugh, of course most of my employees want more benefits”… However, what’s most revealing with this question is which benefits your employees are looking for. Many of the companies who asked this specific question have added key benefits that have helped retain employees, or even gotten rid of benefits no one is using. You never know unless you ask.

#6: “Is there an area outside your current role where you feel you could be contributing?”

Our findings: 76% of employees said, “Yes, there’s an area outside my current role where I feel I could be contributing” (814 employees answered this across 135 companies) when asked through Know Your Company. This result is surprising, considering that most managers feel their employees are slammed and are already at capacity. Thus, this question all the more important to ask: You’ll learn very tactically where your employees want to contribute more to help push your business even further.

#7: “Is there anyone at the company you wish you could apprentice under for a few weeks?”

Our findings: 92% of employees said, “Yes, there’s someone at the company I wish I could apprentice under for a few weeks” (2,217 employees answered across 190 companies) when asked through Know Your Company. This shows how much employees crave learning and developing their skills — especially from others within the company. Asking this question will expose to you if this is similarly the case within your own company.

#8: “Have you seen someone here do great work that’s gone unnoticed?”

Our findings: 76% of employees said, “Yes, I’ve seen someone here do great work that’s gone unnoticed” (1,485 employees answered across 209 companies) when asked through Know Your Company. Based off this data, it’s highly-likely that employees in your company may feel under-appreciated. The answers to this question can help you discover which exact projects or areas of the company that employees would like more gratitude and recognition shown in.

#9: “Are there things you don’t know about the company that you feel you should know?”

Our findings: 55% of employees said “Yes, there are things I don’t know about in my company that I feel like I should know” (3,197 employees answered this across 702 companies) when asked through Know Your Company. Employees want to know more about the company —the company’s vision, people’s roles, why certain policies exist, etc. When you ask this question, you quickly get to the core of what those things are.

How many of these 9 questions are you asking in your own company? The next time you go grab coffee with an employee or have a quarterly one-on-one, consider asking one (or all!) of these questions. I guarantee you’ll learn at least one insight that is completely new and surprising.

Want even more questions? Get your hands on 303+ other questions that uncover surprising insights by signing up for Know Your Company today. Join hundreds of other business owners all over the world who now know the answers to the questions above (and more) all because of our software tool.

Lastly, if you found this post useful, please feel free to share + give it ❤️ so others can find it too! Thanks 😊 (And you can always say hi at @cjlew23!)


The 9 questions that uncover the most surprising insights from employees was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
grudes
17 days ago
reply
Share this story
Delete

Build Super Sweet Accounting Apps with Xero and Node.js

1 Share

Xero, the market leader in Cloud Accounting Software has just released support for their Node.js developer SDK.

The SDK, combined with Xero’s Platform makes it easy to get your accounting applications up and running, fast.

This guide will take you through the process of building your first Xero App in Node.js using the SDK.

Note: to jump straight to a sample application built in node.js, head to https://xero-sample-app.herokuapp.com

Register as a Xero Developer

To get started building Xero apps you must first browse to https://developer.xero.com, click ‘My Apps’ and login with your Xero credentials.

Note: If you don’t have a Xero login, you can create a free trial here then head back to http://app.xero.com.

Creating applications in developer.xero.com

Once logged in, enter the following information:

Application Type: Public
Application Name: Sample Node.js Application for NAME
URL to your product: https://yourcompany.com
OAuth callback domain: localhost

Accept the Terms and Conditions and click ‘Save’.

Saved application with Consumer Key and Consumer Secret available

You’ll now have your Consumer Key and Consumer Secret available for use.

Copy these values and save them somewhere for future reference.

Installing Node.js and NPM in your environment

To install Node.js on Mac follow this guide. On Windows go here. For other operating systems, you’re on your own.

From here on out this guide assumes you’ve got node and npm running and updated to latest versions.

Creating your Xero App

Open up your favourite terminal, make a new directory for your application and cd into it:

mkdir xero-app
cd xero-app

Now you can use the npm init script to create your project.

npm init
npm init in action..

Now you can add the Xero-Node dependency as follows:

npm install xero-node --save

You’re now ready to start building.

Creating a simple web application

We’re going to use Express.js as the basis for our web application in this example.

To install Express.js as a dependency to your project run the following command:

npm install express --save

In your favourite text editor, create a file called index.js as the entry point for this application.

index.js

const express = require('express')
let app = express()
// respond with "hello world" on the homepage
app.get('/', (req, res) => {
res.send('hello world')
})
app.listen(3000, () => {
console.log('Example app listening on port 3000!')
})

You can now run this app by executing the following command in your console:

node .

You should expect to see the following output in your console:

Example app listening on port 3000!

And then browsing to http://localhost:3000 on your browser will reveal:

Hello World!

Congratulations, you’re now running a web application in node.js!

Adding a View layer to your application

Before we can integrate Xero we need to be able to create user interfaces (views) in our application that are separate from our application logic.

To allow you to build views easily there are a number of templating languages that are supported by Express.js; my personal favourite is Handlebars.js.

To add handlebars support to your application, you need another dependency:

npm install express-handlebars --save

You then need to create a few directories that will be used by handlebars:

mkdir views
mkdir views/layouts

The layouts directory is for the main layout of the application and will include your main css, js and other front end dependencies.

All other views will exist in the views directory.

Set up your views

Create the following files that will be rendered by your application:

views/layouts/main.hbs

<!doctype html>
<html>
<head>
<title>Sample Xero App</title>
</head>
<body>
{{{body}}}
</body>
</html>

We can make this layout more feature rich later on. At this point a basic HTML layout is fine.

views/index.hbs

<p>Hello World!</p>

We’ll connect these files up in the next step.

Configure your view engine

To configure handlebars as your view engine you’ll need to modify your index.js as follows:

index.js

const express = require('express'),
exphbs = require('express-handlebars')
let app = express()
let hbs = exphbs.create({
defaultLayout: 'main',
extname: '.hbs',
layoutsDir: `${__dirname}/views/layouts`
})
//Set the view engine
app.engine('hbs', hbs.engine)
app.set('view engine', 'hbs')
// render the main.hbs layout and the index.hbs file
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('Example app listening on port 3000!')
})

Run your application again using the following command.

node .

And browse to http://localhost:3000 to see the result:

Hello World… with Handlebars!

Great, you’re now running your application using Handlebars.js as your view engine.

Add the Connect to Xero button

You now need to create a new assets directory in your project to store static assets (images, css files etc).

mkdir views/assets
mkdir views/assets/images

Download the Connect to Xero button here and save it to the assets/images directory.

Update your code in index.js to reference this new static files directory.

. . .
app.set('view engine', 'hbs')
//Set the static files directory
app.use(express.static(`${__dirname}/views/assets`))
. . .

Update your code in views/index.hbs to use the new button:

<a href="connect">
<img src="images/connect_xero_button_blue_2x.png">
</a>

Browse to http://localhost:3000 and your page should now display the ‘Connect’ button as follows:

Sample ‘Connect to Xero’ button

Configuring your connection to Xero

In order to connect your application to the Xero API you first need to set up a configuration file. This configuration file tells the Node.js client how to connect to Xero.

Create a new file in the root directory of your project called config.json.

Note: don’t forget to add config.json to your .gitignore to make sure it doesn’t go into source control.

config.json should look as follows:

{
"userAgent" : "Xero Sample App - Your Name",
"consumerKey" : "...from developer.xero.com",
"consumerSecret" : "...from developer.xero.com",
"authorizeCallbackUrl" : "http://localhost:3000/callback"
}

Remember the values you saved when you set up your Xero app in developer.xero.com? These values now need to be saved in this config file so they can be used by the client.

Once you’ve saved your config.json file it needs to be included in your application.

index.js

const express = require('express'),
exphbs = require('express-handlebars'),
config = require('./config.json')
//. . .

With this config object, you can now create a Xero client as follows:

const express = require('express'),
exphbs = require('express-handlebars'),
config = require('./config.json'),
xero = require('xero-node')
let xeroClient = new xero.PublicApplication(config)
//. . .

Configuring your connect and callback routes

Now that you’ve got your xeroClient you can use this to easily perform the Xero authorisation and token retrieval processes.

You’ve already set your image to browse to the /connect route when clicked, so let’s modify the index.js file to add this function.

let oauthToken = '', oauthSecret = ''
//Redirect to xero and perform the authorisation
app.get('/connect', (req, res) => {
xeroClient.getRequestToken((err, token, secret) => {
if (!err) {
//these variables will be used in the callback
oauthToken = token
oauthSecret = secret

let url = xeroClient.buildAuthorizeUrl(token)
res.redirect(url)
} else {
console.log(err)
}
})
})

This automatically creates a redirect URL for your application and redirects the user to Xero for them to enter their credentials:

Xero App Authorisation
User Access Approval

This will now redirect you back to the authorizeCallbackUrl specified in your config.json file. In our case it’s http://localhost:3000/callback. This doesn’t yet exist, so let’s create it.

index.js

//Set up the callback
app.get('/callback', (req, res) => {
let verifier = req.query.oauth_verifier
xeroClient.setAccessToken(oauthToken, oauthSecret, verifier)
.then(() => {
//We're connected to Xero so get something useful!
xeroClient.core.organisations.getOrganisation()
.then((organisation) => {
res.render('index', {
org: organisation
})
})
})
.catch((err) => {
console.log(err);
res.render('index', { err: err.data })
})
})

This has now completed the OAuth flow and set the token locally so this function now goes to the Organisations endpoint in the API and retrieves the data for the connected org, and sends it to the view.

Updating the View to show the data

The last step is to update the index.hbs view to show the newly retrieved information.

For this example, we’ll just show the name of the Organisation, and if an error occurred we’ll show that too.

index.hbs

{{#if err}}
<p>Error occurred: {{err}}</p>
{{/if}}
{{#if org.Name }}
<p>Successfully connected to {{org.Name}}</p>
{{else}}
<a href="connect">
<img src="images/connect_xero_button_blue_2x.png">
</a>
{{/if}}

Browse to http://localhost:3000 and click ‘Connect’ to see the end to end flow in action.

Successfully connected!

Congratulations! You’ve now built your web application, connected it to the Xero API using Node.js, retrieved some data and displayed it to the user.

Next Steps

  • All of the SDK functions are documented in Github so head over there to see what data you can access.
  • The UI for this obviously needs some improvement, so go ahead and integrate your favourite front end framework.
  • The tokens that are retrieved aren’t stored so each time the page is refreshed the user will need to authenticate again, try saving these in a session instead.
  • Add some more routes, user persistence, a navigation, and some graphs for a fully fledged app!
  • Deploy to your favourite cloud hosting provider.
  • Head over to https://developer.xero.com/partner/ and register as an Add On Partner to upgrade your Public App to a Partner App and become a Xero Partner!

Issues? Tweet @jordwalsh or @xeroapi or contact api@xero.com.


Build Super Sweet Accounting Apps with Xero and Node.js was originally published in Xero Developer on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
grudes
17 days ago
reply
Share this story
Delete

Don’t Promise

1 Share

We’ve all been there.

A customer’s upset. They make a demand. Maybe it’s reasonable, quick, easy, and no big deal. Fine. But sometimes it’s unreasonable given the context and situation. And we give in.

Promises to placate rarely end up well. Sometimes you’ll do anything to avoid the immediate pain of saying no. And since in the near-term there’s little cost to saying “yes”, promises feel like a bargain. But while promises are cheap and easy to make, actual work is hard and expensive to do. If it wasn’t, you’d just have done it now rather than promised it later!

Promises are like debt — they accrue interest. The longer you wait to fulfill them, the more they cost to pay off.

One of the biggest costs is regret. Past promises are often met with current regret. Once it’s time to get to work, you realize just how expensive that “yes” really was.

You promised someone you’d release that new feature or product by the end of the year. Sounded totally reasonable in April — “sure, we’ll have plenty of time to get to that!” — but now that it’s November, you have to scramble.

Things that were slated get pushed off. People have to get reshuffled. Teams reassembled. Priorities put on hold. Other things delayed. New ideas take a backseat to old ones. All because of a simple “yes” to dodge the pain of saying “no” months ago.

Many companies are weighed down by prior obligations of placation. Promises salespeople made to land a deal. Promises the project manager made to the client. Promises the owner made to the employees. Promises one department made to another.

The further away the promise, the easier it is to make. And the more painful it is to ultimately deliver. That’s because when the time comes to fulfill the promise, Employees would rather be working on new ideas rather than old promises. You have to put aside progress to make up for the past. Tomorrow waits for yesterday.

Morale takes a hit when the past continually snaps you backwards. Energy and will is sapped. Undesirable past obligations are a constant source of stress and frustration. People leave when they feel like the work they’re doing today is last year’s work.

It might feel difficult in the moment, but you’re far better off saying no in the first place. Take the short term pain that goes away quick vs. the long term pain that sneaks up on you and intensifies as obligations come due.


Don’t Promise was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
grudes
25 days ago
reply
Share this story
Delete

Focusing a `background-image` on a Precise Location with Percentages

1 Share

Let's say you have an element with a background-image, where only part of the image is visible, because the image is bigger than the element itself. The rest is cropped away, outside the element.

Now you want to move that background-image such that you're focusing the center of the element on a specific point in it. You also want to do that with percentage values rather than pixels. We're going to have to get clever.

This is going to involve some math.

Let's use this as our image, which has markers for sizing:

And here's our element, with that background-image applied. Notice we can only see the (top) left of the image:

See the Pen Background Focus: no position by Jay (@jsit) on CodePen.

Now let's say we want to align a specific point on the image with the center of that element. Say, the point at 300px in from the left.

Since we're asking for this position in pixels, it's straightforward. With no position defined, the background-image "starts" with the point at 100 pixels at the center, so you need to move it to the left by 200 pixels:

See the Pen Background Focus: pixel position by Jay (@jsit) on CodePen.

Let's formalize it.

The x value you're using for background-position is calculated like so:

(0.5 × [bounding box width]) - [x-coordinate]
             0.5 × 200px -              300px
                   100px -              300px = -200px

It takes a second to figure out, but it's nothing too taxing. You could have probably figured that out intuitively without needing to use a formula.

But what if you wanted to (or had to) express background-position as a percentage? Shouldn't be too hard, right? Let's try using a percentage to get ourselves centered at 300px again. We had a background-position-x of -200px, so let's convert that to percent: -200 / 800 = -25%, so:

See the Pen Background Focus: percentage (1st attempt) by Jay (@jsit) on CodePen.

Hm. That didn't work at all. Maybe we need to use a positive value?

See the Pen Background Focus: percentage (2nd attempt) by Jay (@jsit) on CodePen.

That's better, but it's centered at, like... 250px? How about as a percentage of the bounding box width: 300 / 200 = 150%. That can't be right...

See the Pen Background Focus: percentage (3rd attempt) by Jay (@jsit) on CodePen.

Yeah, that's not right.

Let's back up. What happens if we do this?

See the Pen Background Focus: percentage (4th attempt) by Jay (@jsit) on CodePen.

That feels like it kind of makes sense; background-position: 100% 0; makes the background-image flush-right and centered at 700px, or 7/8 the width of the image. But what if we wanted to center it at 100%? I guess we'd have to do... 9/8?

See the Pen Background Focus: percentage (5th attempt) by Jay (@jsit) on CodePen.

At this point, I'm not surprised that didn't work.

This doesn't feel like the right path. Let's back up.

What does the spec say?

For example, with a value pair of '0% 0%', the upper left corner of the image is aligned with the upper left corner of, usually, the box's padding edge. A value pair of ‘100% 100%’ places the lower right corner of the image in the lower right corner of the area. With a value pair of '75% 50%', the point 75% across and 50% down the image is to be placed at the point 75% across and 50% down the area.

Maybe we can reverse-engineer this.

On that last one, 112.5%, it was aligning the point at 112.5% across the background-image with the point at 112.5% across the bounding box. That kind makes sense. The spec seems written to make it easy for only three values: 0%, 50%, and 100%. Any other value isn't so intuitive.

With background-position: 0;, we were focused on 100px, or 12.5%. With background-position: 100% 0;, we were focused on 700px, or 87.5%. How does background-position: 50% 0; look, exactly?

See the Pen Background Focus: percentage (6th attempt) by Jay (@jsit) on CodePen.

50% is kind of like our "anchor" here; it's the point at which our desired focal point and the corresponding background-position values are equal.

Let's pretend we want to focus on 700px or 87.5%. We go 100% of the way from the center: 50% + 50%.

See the Pen Background Focus: percentage (4th attempt) by Jay (@jsit) on CodePen.

With background-position set to 100%, the center of our bonding box has "panned" from the center of the image, 3/4 of the way to the rightmost edge (from 400px to 700px). If we want to "pan" to the rightmost edge, we need to go that extra 1/4, or 200px. 1/4 is 1/3 of 3/4, so we need to go a third more than we did a moment ago, or a total of 66.667% from the center:

See the Pen Background Focus: percentage (7th attempt) by Jay (@jsit) on CodePen.

Whew! So to focus on the rightmost edge of a background-image that is 4 times the size of our bounding box, we need to set background-position: 116.667% 0;.

How the heck are we supposed to figure that out?

It's a difference of 16.667% from the 100% we might expect. So if we wanted to focus on our original goal of 300px (or, 37.5%), we'd, uh, add 16.667%? There's no way this is going to work:

See the Pen Background Focus: percentage (8th attempt) by Jay (@jsit) on CodePen.

Nope.

If we wanted to focus on the leftmost edge, we'd probably subtract 16.667% from 0%, right? That sounds like it could be right.

See the Pen Background Focus: percentage (9th attempt) by Jay (@jsit) on CodePen.

Cool!

To focus at 100% or 0%, you have to "overshoot" those values by a certain amount, when measured from the center.

So if we want to focus on 0%, or "100% of the way to the left of the center," we have to subtract 66.667% from 50%. If we want to focus on 100%, or "100% of the way to the right of the center," we have to add 66.667% to 50%.

I might have expected to have to add or subtract 50% to or from 50% to get to those edges: a 1:1 ratio of "how far I want to go from the center" to "what my background-position value should be." But instead, we have to use a 4:3 ratio. In other words, we have to use a value four-thirds more "away from the center."

Things are getting a little hairy here, so let's introduce some terms:

  • c: Desired focal point (in percent) from leftmost edge of background image
  • z: Zoom factor (background width ÷ bounding box width)
  • p: background-position, to focus on c, given z

So we take a focal point's distance from the center (c − 50), multiply it by 4/3, then add that result to "the center," or 50.

If you wanted to focus on the point at 600px (or 75%), my background-position value should be:

(75% − 50%) × 4/3 + 50% = 83.333%

Yes, that sounds like it could work! Please please please:

See the Pen Background Focus: percentage (10th attempt) by Jay (@jsit) on CodePen.

Awesome!

And if you wanted to focus on 200px, or 25%, you would do:

(25% − 50%) × 4/3 + 50% = 16.667%

See the Pen Background Focus: percentage (11th attempt) by Jay (@jsit) on CodePen.

Wow.

Let's generalize this:

(c − 50%) × 4/3 + 50% = p

So why 4/3? 4 is the ratio of our background-image width to our bounding box width; and 3 is... 1 less than 4. Could it be that simple? Let's try a larger background-image, this time 1000px wide, or 5 times the width of our bounding box. And let's again try to focus on the point at 200px. Here our equation would be:

(20% − 50%) × 5/4 + 50% = 12.5%

See the Pen Background Focus: percentage (12th attempt) by Jay (@jsit) on CodePen.

Oh my god. It works!

So to revisit our equation, with a variable background-to-bounding-box ratio:

(c − 50%) × z/(z − 1) + 50% = p

Let's turn this into English:

Given a point on a background-image at location c...

  1. with c expressed as a percentage of the width of the image
  2. where c is intended to lie in the horizontal center of the background image's bounding box
  3. and where the background-image is z times as wide as its bounding box

the correct background-position p (expressed as a percentage) is given by the following formula:

(c − 50%) × z/(z − 1) + 50% = p

Can we generalize this even more?

What if we wanted to align the point at 25% of the background-image with the point at 75% of the bounding box? Yikes!

Let's revisit our original formula:

(c − 50%) × z/(z − 1) + 50% = p

Now let's introduce some new terms:

  • b: Desired focal point (in percent) from the leftmost edge of the bounding box. Earlier we had assumed this to always be 50% so that the center of the bounding box would be focused on our target in the background-image.
  • d: background-image focal point (in percent) to align to bounding box's midpoint in order to get c to align to b in the bounding box; if d of the background-image aligns with 50% of the bounding box, then c of the background-image will align with b of the bounding box.

Let's think of it this way

To want to align position c of a background-image with position b of a bounding box is to want to align some other position, d, of a background-image with the center of the bounding box - and we already know how to do that. So can we figure out a way to derive d, the spot we need to be at 50%, from c, b, and z? Sure!

With our 800px wide background-image, in a 200px-wide bounding box (z = 4), if we want to focus the rightmost edge of the bounding box (b = 100%) on the position at 600px (c = 75%) in the image, we would want the center of the bounding box to be focused on the point at 500px (d = 62.5%).

How do we get from c (75%) to d (62.5%)? Where does that -12.5% difference come from?

Well, our b was 100%, 50% greater than our old "default" b of 50%. And 12.5% is 1/4 of that; 1/4 is the inverse of our z of 4. Is that where our d comes from? That would be:

d = c + (50% - b)/z

Looks promising. Now we can substitute d in for c in the original formula:

(d − 50%) × z/(z − 1) + 50% = p

Or:

(c + (50% − b)/z - 50%) × z/(z − 1) + 50% = p

Whew! Let's test this. Let's try to align the position at 25% in our background-image (200px) with the position at 75% in our bounding box. This would be:

p = (25% + (50% - 75%)/4 - 50%) × 4/(4 - 1) + 50%
p = -31.25% × 1.333 + 50%
p = 8.333%

See the Pen Background Focus: percentage (13th attempt) by Jay (@jsit) on CodePen.

Unbelievable! Let's double check. How about the point at 87.5% in our background-image (700px) aligned with the position at 33.333% in our bounding box:

p = (87.5% + (50% - 33.333%)/4 - 50%) × 4/(4 - 1) + 50%
p = 41.6667% × 1.333 + 50%
p = 105.555%

See the Pen Background Focus: percentage (14th attempt) by Jay (@jsit) on CodePen.

Looks good enough to me!

I'm sure there is something intuitive about this to certain types of people, but I am not one of those people.

Let's build a Sass function that will do all this ridiculous math for us.

See the Pen Background Focus: percentage (final Sass function) by Jay (@jsit) on CodePen.

My head is spinning.

When I began tackling this problem I did not expect it to be this difficult, but what a journey. I hope guiding you through my thought process has been enlightening, and that you may at some point find value in our little Sass function.

All the Pens embedded in this article can be found in this collection.


Focusing a `background-image` on a Precise Location with Percentages is a post from CSS-Tricks

Read the whole story
grudes
34 days ago
reply
Share this story
Delete
Next Page of Stories