Specific Lens: Difference between revisions

From XPUB & Lens-Based wiki
Line 68: Line 68:
     transition: 0.25s outline, 0.25s background-color;
     transition: 0.25s outline, 0.25s background-color;
  }
  }
==CSS Pad for Specific Lens==
'''Link the Pad with the scratch1.0 firefox extension:'''
https://pad.xpub.nl/p/specific-lens


==Color Code and Border Style==
==Color Code and Border Style==

Revision as of 12:15, 3 March 2025

Description

CSS Position & Display Viewer (by hovering)

Icon for extension (104x104px

A firefox browser extension (linked with Doriane's "scratch1.0" browser extension plug-in) to highlight and show by hovering over any element the CSS display + CSS position on every webpage with a specific color code and border style.
The aim is to polish it and publish it on the Firefox extension shop!

The story behind it
We started to mess around with scratch1.0 by trying to "degridify" websites, meaning taking away and breaking the grid/flex display of any webpage. Some samples of experimentations can be found in the  ::WAYbefore section.

Troubleshooting Degridify

When making this, we faced a major issue: most of the corporate websites use specific classes, even probably frameworks, that make it very hard to break. So we worked mostly on StackOverflow, targeting the specific classes they use. Hence, this extension prototype can never be globalized to the whole WorldWideWeb. We had to make a choice :(

After this, talking with Doriane brought us to imagine the Specific Lens (maybe we should find a new name for it?). The idea was to highlight the display and position values used by the different elements on a webpage by hovering them.

Troubleshooting the Specific Lens

The first step was to target those values on every website, regardless of the specific classes they already use. For that, we had to write a script that could recognize those values. The script first checks for display and position assigned to an element, then it assigns an id to the element that corresponds to the values born by each property.
For example, a wiki <h1> has a display: inline; and position: static; so the script will assign to it class="display-inline position-static".
This piece of code then allows us to target each class with the CSS.

→ The JS code
var stuff = document.querySelectorAll("*"); // gets every element present in the HTML
stuff.forEach((element) => {
  const styles = window.getComputedStyle(element); // gets the element's style
  var display = styles.getPropertyValue("display"); // gets the display value
  var position = styles.getPropertyValue("position"); // gets the position value
  element.classList.add("display-" + display); // assigns the corresponding class for display
  element.classList.add("position-" + position); // assigns the corresponding class for position
});

Now that we can target every value for each property, we can style them! But...how??? What are the criteria used to differentiate every value???

At first, we decided to give a background-color to the position, and border styling to the display. They were all showing together, it was not ideal.
So we decided to switch and put borders on position and bg-color on display -- obviously it did not fix the issue :)

That is when we decided to highlight the properties only on hover.

...and we got a new issue: the hover was not focusing on one element but also on its parent(s), that was a real mess.

Troubleshooting the Specific Lens #2

To solve this, Doriane helped us to target specific elements with CSS. It started by declaring variables and defaults, that will then help us to tweak and play with styling more easily:

/* Default properties that will be changed by the following declarations */
*{
   outline: 0px solid black;
   background-color: initial;
   transition: 2.8s outline, 2.8s background-color ;
}
/* Styling the position properties with borders */
.position-absolute { --s: dotted; --p: "absolute"; }
.position-relative { --s: dashed;  --p: "relative"; }
.position-sticky { --s: groove;  --p: "sticky"; }
.position-fixed { --s: double;  --p: "fixed"; }
.position-static { --s: solid; --p: "static"; }
/* Styling the display properties with background colours */
.display-block { --b: LightPink; --d: "block"; } 
.display-inline { --b: MistyRose; --d: "inline"; } 
.display-inline-block { --b: HotPink; --d: "inline-block"; } 
.display-grid { --b: Plum ; --d: "grid"; } 
.display-flex { --b: MediumOrchid; --d: "flex"; } 
.display-table { --b: Lavender; --d: "table"; } 

Then, we targeted the actual hovered element with this piece of CSS:

*:hover:not(:has(*:hover)){
   --s: solid;
   outline: 10px var(--s) black;
   background-color: var(--b);
   border-radius: 0 !important;
   transition: 0.25s outline, 0.25s background-color;
}

Color Code and Border Style

For clarity and legibility, we decided on a meticulous styling of the different properties.
position values use border styling and display values use background-color styling.

Position

absolute: dotted
relative: dashed
sticky: groove
double: double
static: solid

Display

block: LightPink
inline: MistyRose
inline-block: HotPink
grid: Plum
flex: MediumOrchid
table: Lavender

Ideas/ToDo's for the future

→ Add a legend for the colour/border coding
→ Toggle Switch(?) to show the properties just by hovering or showing constantly.
→ A search tool to find webpages, using specific CSS Display Properties and CSS Position Properties.

Screenshots Extension in action

::after

The current and improved version of the Specific Lens is now highlighting elements when we hover them. It displays a little info-box in the bottom-right corner of the screen giving information about the display and position values used by the hovered element.
It also has a smooth transition on the hover.

::before

The first version of the Specific Lens was showing everything all at once, a bit overwhelming :)

::WAYbefore

While we were first working on this extension, the first version of it was meant to "degridify" websites. We were targeting specific classes and displays to mess with the grids.

Code

manifest.json

 
{
  "manifest_version": 2,
  "name": "Specific Lens",
  "author": "XPUB",
  "version": "1.0",

  "description": "CSS Position & Display Viewer by hovering",
  "icons": {
    "48": "icons/SpecificLens_Icon.png"
  },

  "permissions": [
    "*://localhost/*",
    "activeTab",
    "<all_urls>",
    "storage"
  ],
  "browser_action": {
    "default_icon": "icons/SpecificLens_Icon.png",
    "default_title": "scratch",
    "default_popup": "popup/popup.html"
  },
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["main.js"]
    }
  ]
}

main.js

to implement an external PAD for CSS specifications
(see below js for getting property value Display and Position)

 
(() => {
  /**
   * Check and set a global guard variable.
   * If this content script is injected into the same page again,
   * it will do nothing next time.
   */
  if (window.hasRun) {
    return;
  }
  window.hasRun = true;

  let pad_root = "https://cached-pad.osp.kitchen/";
  let default_pad = "https://pad.constantvzw.org/p/declarations-scratch";

  function fetch_request(url, callback) {
    // fetching the pad
    let new_url = pad_root + "/p/" + url.split("/p/")[1];

    fetch(`${url}/export/txt`, {
      method: "GET",
      mode: "cors",
    })
      .then((response) => response.text())
      .then((css) => inject_css(css));
  }

  function inject_css(css) {
    console.log("pad loaded!");

    // remove previously imported pad as style
    let etherstyle = document.getElementById("etherstyle");
    if (etherstyle) {
      etherstyle.remove();
    }

    // import new pad as style
    let el = document.createElement("style");
    el.id = "etherstyle";
    el.type = "text/css";
    el.innerText = css;
    document.head.appendChild(el);

    let everything = document.querySelectorAll("*");
    for (thing of everything) {
      thing.setAttribute("tabindex", "0");
    }
  }

  function load_pad(pad) {
    fetch_request(pad, inject_css);
  }

  // --- storage
  browser.storage.local
    .get("etherpad")
    .then(function (result) {
      if (result.etherpad) {
        etherpad = result.etherpad;
      } else {
        etherpad = default_pad;
      }
    })
    .then(function () {
      console.log("loading pad", etherpad);
      load_pad(etherpad);
    });

  // --- update
  browser.runtime.onMessage.addListener((message) => {
    if (message.command === "etherpadchange") {
      new_pad = message.url;
      console.log("changing etherpad", new_pad);
      browser.storage.local.set({ etherpad: new_pad });
      load_pad(new_pad);
    }
  });
})();

// get property value for CSS Display and CSS Position
var stuff = document.querySelectorAll("*");

stuff.forEach((element) => {
  const styles = window.getComputedStyle(element);

  var display = styles.getPropertyValue("display");

  var position = styles.getPropertyValue("position");

  element.classList.add("display-" + display);
  element.classList.add("position-" + position);
});