Can't Style Multiple Elements

In Outlook web access OWA, the following selector is intended to select all aria descendants of an element ID, but only the first one gets selected. What am i doing wrong?

#ReadingPaneContainerId [aria-label='Message body']

I want to select all message bodies in the reading pane, in a conversation.

Thx!

also asked on sitepoint

you haven’t shown your html so I just made a codepen to show how this is actually selecting all the applicable descendants

Hi,

thx for your code. Your selector appears identical to my selector.

i’m using the selector to set zoom level with JavaScript. My script places a slider on the topbar of the page – that works fine. Zooming works fine too, but only the first descendent aria-label element gets zoomed.

var $$ = function (sel) {
     return document.querySelector(sel);
};

/* This doesn't zoom all message bodies, just the first one */

var msg = "#ReadingPaneContainerId [aria-label='Message body']";

     $$("#TopBar").insertAdjacentHTML(
          "beforeend",
          "<input type='range' min='50' max='200' id='slidZoom' value='100' step='1'>"
     );

     $$("#slidZoom").addEventListener("input", function () {
          $$(msg).style.zoom = $$("#slidZoom").value + "%";
     });

The html is the html on https://outlook.office.com/mail/. It’s a Microsoft website, known as Outlook Web Access. I tried to share the html contained within the ReadingPaneContainerId element. However, it’s a very huge amount, and it exceeds the character limit of this forum. I pasted the html fragment here:
https://justpaste.it/owa-fragment

couple of thoughts (may or may not be useful ones)

  • if you suspect the selector is the problem, what happens if you select something more conventional? (like say you select based on a class only, does that work better?)
    If yes, then is it possible that OWA is disrupting this selection?
    If not, then the selector can’t be the problem. Something else is the cause.

  • have you tried to set this up somewhere else like on a conventional browser with some test html? Does it work better there? Again, if yes, maybe OWA is doing something disruptive? If not, then the script may need to be reworked.

I added my javascript to your pen. Same problem. The issue must be the selector, or my script.

I can’t get anything to zoom. (was the ‘a’ supposed to zoom?)

Yep. Works for me. Video:

I changed the code to use this instead:
return document.querySelectorAll(sel);

and in my test I was able to get 3 nodes back (a, b, c) from my codepen.
Hopefully this is what will help you move forward.

btw zoom is not supposed to be used in customer-facing sites according to https://developer.mozilla.org/en-US/docs/Web/CSS/zoom
(this is probably why I couldn’t get it to work).

Instead I used fontSize property to do the same thing.

Great!

But the article you linked advises to use transform: scale. That’s not working for me either.

Uncaught TypeError: Cannot set properties of undefined (setting ‘transform’)

Seems to be some problem with applying zoom or transform to multiple elements using javascript.

Straight CSS works on multiple elements no problem:

#ReadingPaneContainerId [aria-label='Message body'] {
  zoom: 200%;
}

https://codepen.io/johnaweiss/pen/ZEowmob

If you look up querySelectorAll you will see it returns a list. So you have to iterate over it.

Yep. Here they show iteration:

Ok, but if i write straight css (without javascript) then no iteration is needed. So to avoid iterating, can i use javascript to write css, instead of using the .style property?

Well there are two or three ways:

I am sorry I didn’t understand you.
Why don’t you want to iterate?
It is a simple for loop that you are missing and then use the .item function with the index.

Generally, i avoid iteration. I believe it’s a performance hog, and ties up the processor. Also, loooops tend to be verbose code.

If we’re styling multiple elements, then of course iteration has to happen someplace. Why not let the highly-optimized browser rendering engine handle the iteration, instead of my Javascript? That’s why I believe straight CSS is going to give better performance.

More methods:

It seems insertRule requires the existence of a stylesheet, and the stylesheet must be served by the same host. While adding a style element with appendChild doesn’t require either. So the latter seems a better choice when it’s unknown whether there’s a stylesheet.

My fave:

// One liner function:
const addCSS = css => document.head.appendChild(document.createElement("style")).innerHTML=css;

// Usage: 
addCSS("body{ background:red; }")

Problem now is, if i keep adding style elements every time i drag the slider, we’re going to get a mountain of style tags in the page!

So maybe iteration is better in this case :confused:

@hbar1st Solved! This method doesn’t require iteration, and doesn’t generate a mountain of style tags. It just creates and keeps rewriting the same temporary style tag. Performance seems very fast, with no lags in the slider. Since i’m not iterating, only one line of code has to run each time the slider value changes.

transform:scale doesn’t appear to work at all with label tags, as you used in your code. Works with divs.

Another weird problem with transform:scale. Seems to cause divs to slide toward left side of window. Maybe just a codepen issue?

// reusable function to return node by selector
var $$ = function (sel) {
  return document.querySelector(sel);
};

// create slider

// slider for zoom
$$("#TopBar").insertAdjacentHTML(
  "beforeend",
  "<input type='range' min='50' max='200' id='slidZoom' value='100' step='1'>"
);

/* 
// slider for transform: scale
$$("#TopBar").insertAdjacentHTML(
  "beforeend",
  "<input type='range' min='0.5' max='2' id='slidZoom' value='1' step='0.1'>"
);
*/

// add temp style tag to hold the zoom css
var sheet = document.createElement("style");
document.head.appendChild(sheet);

// define selector for Outlook reading pane
var selector = "#ReadingPaneContainerId [aria-label='Message body']";

// define slider event
$$("#slidZoom").addEventListener("input", function () {

  // change text of temp stylesheet
  
  // works, using zoom
  sheet.innerHTML = selector + " {zoom: " + $$("#slidZoom").value + "%}";
  
  // transform:scale causes divs to slide toward left side of window
  // sheet.innerHTML = selector + " {transform: scale(" + $$("#slidZoom").value + ")}";
});

You should really be setting the font size instead of zoom. Zoom is non-standard, it doesn’t even work on Firefox. If you’re so insistent on avoiding iteration, then have you considered CSS custom properties?

You’ve made the mistaken assumption that i want to resize fonts only. I want to resize all the content.

I’m aware of that. For my personal usage, zoom works fine on Chrome. For general usage, Mozilla recommends transform:scale (not font-size). But i had issues with transform:scale. Would be great if someone here can solve my problem with transform:scale.

Can you share how that could help?

Update: Here’s a fix for the scale positioning issue
transform-origin: left center;

But subsequent elements don’t move down as desired. They overlap. How to fix that?
image

I started a separate thread for that issue.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.