Search code examples
c#puppeteerwebautomationpuppeteer-sharp

Style Property and Values


I am extracting name and values of each element in HTML DOM. For style attribute able to extract only property names not values.

My code is given below:

var elementHandles = await page.QuerySelectorAllAsync("a");
    foreach (var handle in elementHandles)
    {
        var elementStyle = await handle.GetPropertyAsync("style");
        var style = await elementStyle.JsonValueAsync();
        var output = style.ToString();
    }   

This is my output:

{{
  "0": "font-family",
  "1": "font-size",
  "2": "line-height",
  "3": "color",
  "4": "text-align"
}}

This is what I am expecting:

font-family:Arial, Helvetica, sans-serif; 
font-size: 12px; 
line-height: 16px; 
color: #999999;
text-align: left

Solution

  • The problem is how the CSSStyleDeclaration is serialized. If that´s how Chromium decides to serialize that object there is nothing we can do there.

    But, we can try to solve that from javascript using EvaluateFunctionAsync.

    foreach (var handle in elementHandles)
    {
      var style = await page.EvaluateFunctionAsync<Dictionary<string, string>>(
        "e => Object.entries(e.style).filter(i => isNaN(i[0]) && i[1]).map(i => { return { [i[0]] : i[1]}}).reduce((acc, cur) => { return {...acc, ...cur}}, {})", handle);
      var output = style.ToString();
    }
    

    Let's take a look at the javascript expression

    e=> //We send the HTML element instead of the style property
      Object.entries(e.style) //We get all the property/value pairs from the CSSStyleDeclaration object
        // We want to exclude number properties (like 0,1,2) and empty values
        .filter(i => isNaN(i[0]) && i[1]) 
        //We turn them into objects
        .map(i => { return { [i[0]] : i[1]}})
        //We merge them into one single object that will be returned to C#
        .reduce((acc, cur) => { return {...acc, ...cur}}, {})