# Dynamically position button using polynomial regression

## But why?

I wanted to implement a design similar to the one below, where the button is always be positioned above the portal.

## Solution

I wanted to experiment with a bruteforce solution to position the button dynamically based on the screen size.

To achieve this I:

1. Collected datapoints for the optimal position on different screen sizes.
2. Then trained a model based on these datapoints to predict optimal button position.
3. Finally positioned the button based on the returned coordinates when the page load.

#### Step 1: Collect datapoints

To collect the datapoints I added a new target at the center of the button on the background:

Then I added a JavaScript function to log the coordinates of my mouse & the screen size on each click:

``````var inputs = [];
var outputs = [];

document.onmousedown = function(e) {
var x = e.pageX;
var y = e.pageY;
var h = screen.availHeight;
var w = screen.availWidth;

console.log('w:', w, 'h:', h, 'x:', x, 'y:', y);

inputs.push({w: w, h: h});
outputs.push({x: x, y: y});
}``````

Then I started clicking on the target while changing the screen size as shown in the video below:

#### Step 2: Find optimal button position

Once I collected enough datapoints I converted them to a list of inputs (w, h) & outputs (x, y):

``````> 'X = [' + inputs.map((e, i) => {return `(\${e.w}, \${e.h})`;}).join(', ') + ']';
< X = [(2318, 1422), (2290, 1422), (2262, 1422), (2202, 1422), ...]

> 'Y = [' + outputs.map((e, i) => {return `(\${e.x}, \${e.y})`;}).join(', ') + ']';
< Y = [(416, 210), (413, 207), (414, 210), (413, 212), (414, 208), ...]``````

Then I used Gradient boosting technique with Multi Output Regressor from sklearn to train a regression model on these points:

``````from sklearn.ensemble import GradientBoostingRegressor
from sklearn.multioutput import MultiOutputRegressor

X = [...]
Y = [...]

model.fit(X, Y)

model.predict([[(2262, 1422)]])``````

Then I wrapped this model into a small Flask app that takes screen width & height as arguments and returns the optimal (x, y) coordinates for the button:

``````from flask import Flask, request, jsonify
from sklearn.multioutput import MultiOutputRegressor

@app.route('/button_position')
def my_route():
w = request.args.get('w', default = 100, type = int)
h = request.args.get('h', default = 100, type = int)

X = [...]
Y = [...]

model.fit(X, Y)

proposed_position = model.predict([[w, h]])

return jsonify([proposed_position, proposed_position])``````

#### Step 3: Position button on page load

Now that we have the model & api ready, we have to request the optimal button position from the api when loading the page and update the button position based on the coordinates that we get.

``````function position_apply_btn() {
var h = window.innerHeight;
var w = window.innerWidth;

fetch('http://127.0.0.1:5000/button_position?w=' + w + '&h=' + h)
.then(response => {
return response.json();
})
.then(json => {
let x = json;
let y = json;

set_position(x, y);
});
}

function set_position(x, y) {
e = document.getElementById('action-btn');

e.style.left = x - e.offsetWidth / 2 + 'px';
e.style.top = y - e.offsetHeight / 2 + 'px';
}

position_apply_btn();``````

## Conclusion

I was surprised how well this turned out. I wonder if a similar but more optimized method (e.g. automatic screen resizes, optimal screen sizes …) can be used in a practical way to facilitate responsive web design?

✉️ Subscribe via email
Thanks for Subscribing!
Subscription failed. Please try again later.