42

重複の可能性:
HTML が「chucknorris」を色と見なすのはなぜですか?

プロパティはどのようにbgcolor計算されますか?

次のhtmlコードを使用すると...

<body bgcolor="#Deine Mutter hat eine Farbe und die ist grün."></body>

...私が得るのは次の色です。

#Deine Mutter hat eine Farbe und die ist grün.

ところで: CSS で使用しようとすると、機能せず、標準の色が適用されます。

body{
    color: #IchwillGOLD;
}

なんで?

4

2 に答える 2

18

これに対する私の最初の試みは、エラーに関する小さな試行であり、システムのいくつかの興味深い特性を見つけましたが、答えを形成するには十分ではありませんでした. 次に注目したのはスタンダード。これが標準であると私が信じた理由は、3 つの異なるブラウザーでテストしたところ、実際にはすべて同じことをしたからです。標準を使用して、何が起こるかを知りました:

  1. 16 進数ではないすべての文字はゼロに置き換えられます (したがって、ゼロ、1 ~ 9、および ae のみが残ります)。
  2. 文字列は 3 の倍数になるように最後にゼロが埋め込まれます
  3. 次に、文字列は 3 つの等しい部分に分割され、それぞれが色を表します
  4. 結果の文字列が 8 文字を超える場合は、各文字列の最後の 8 文字を取得します。
  5. 各文字列がゼロで始まる限り、最初の文字は各文字列から削除されます (この特定の文字列では、ゼロで始まるため発生しません)De
  6. これらの文字列のそれぞれから最初の 2 文字が取得され、色の構成要素の 1 つとして使用する数値に変換されます。

00FA00このようにして、あなたはあなたが得るのを見るでしょうDeine Mutter hat eine Farbe und die ist grün.

html5 標準ではプロセスがより正確に説明されており、実際にはここでさらにいくつかのケースが説明されています

于 2012-11-14T15:37:40.020 に答える
9

コメントで述べたように、HTMLParserはそれをCSSプロパティとして追加し、Jasperによってすでに回答されているように、それは仕様によるものです。

実装

WebkitはHTMLParser.cppのhtmlを解析し、パーサーがinBodyの場合、bgColor属性をHTMLBodyElement.cppのCssColorとして追加します。

// Color parsing that matches HTML's "rules for parsing a legacy color value"
void HTMLElement::addHTMLColorToStyle(StylePropertySet* style, CSSPropertyID propertyID, const String& attributeValue)
{
    // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.)
    if (attributeValue.isEmpty())
        return;

    String colorString = attributeValue.stripWhiteSpace();

    // "transparent" doesn't apply a color either.
    if (equalIgnoringCase(colorString, "transparent"))
        return;

    // If the string is a named CSS color or a 3/6-digit hex color, use that.
    Color parsedColor(colorString);
    if (!parsedColor.isValid())
        parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString));

    style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));
}

この方法で終了する可能性があります。

static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString)

次のようなレガシーカラーをサポートすることだと思います:body bgcolor = ff0000(Mozilla Gecko Test)。

  1. 先頭の#をスキップ
  2. 最初の128文字を取得し、非16進文字を0に置き換えます。1120
  3. 非BMP文字は、文字列に2つの「文字」として表示されるため、「00」に置き換えられます。
  4. 数字が返されない場合は黒になります
  5. 数字を3つのコンポーネントに分割してから、各コンポーネントの最後の8桁を検索します。

Webkit / HTMLElement.cpp:parseColorStringWithCrazyLegacyRulesのコード:

static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString)
{
    // Per spec, only look at the first 128 digits of the string.
    const size_t maxColorLength = 128;
    // We'll pad the buffer with two extra 0s later, so reserve two more than the max.
    Vector<char, maxColorLength+2> digitBuffer;
    size_t i = 0;
    // Skip a leading #.
    if (colorString[0] == '#')
        i = 1;

    // Grab the first 128 characters, replacing non-hex characters with 0.
    // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String.
    for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) {
        if (!isASCIIHexDigit(colorString[i]))
            digitBuffer.append('0');
        else
            digitBuffer.append(colorString[i]);
    }

    if (!digitBuffer.size())
        return Color::black;

    // Pad the buffer out to at least the next multiple of three in size.
    digitBuffer.append('0');
    digitBuffer.append('0');

    if (digitBuffer.size() < 6)
        return makeRGB(toASCIIHexValue(digitBuffer[0]), toASCIIHexValue(digitBuffer[1]), toASCIIHexValue(digitBuffer[2]));

    // Split the digits into three components, then search the last 8 digits of each component.
    ASSERT(digitBuffer.size() >= 6);
    size_t componentLength = digitBuffer.size() / 3;
    size_t componentSearchWindowLength = min<size_t>(componentLength, 8);
    size_t redIndex = componentLength - componentSearchWindowLength;
    size_t greenIndex = componentLength * 2 - componentSearchWindowLength;
    size_t blueIndex = componentLength * 3 - componentSearchWindowLength;
    // Skip digits until one of them is non-zero, 
    // or we've only got two digits left in the component.
    while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' 
        && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) {
        redIndex++;
        greenIndex++;
        blueIndex++;
    }
    ASSERT(redIndex + 1 < componentLength);
    ASSERT(greenIndex >= componentLength);
    ASSERT(greenIndex + 1 < componentLength * 2);
    ASSERT(blueIndex >= componentLength * 2);
    ASSERT(blueIndex + 1 < digitBuffer.size());

    int redValue = toASCIIHexValue(digitBuffer[redIndex], digitBuffer[redIndex + 1]);
    int greenValue = toASCIIHexValue(digitBuffer[greenIndex], digitBuffer[greenIndex + 1]);
    int blueValue = toASCIIHexValue(digitBuffer[blueIndex], digitBuffer[blueIndex + 1]);
    return makeRGB(redValue, greenValue, blueValue);
}
于 2012-11-14T16:30:24.207 に答える