Hacker Newsnew | past | comments | ask | show | jobs | submit | chrismorgan's commentslogin

> because the monsters who make browsers removed support for it

Most browsers never implemented it in the first place. Safari, Chrome, IE and Edge never had it. In terms of current browser names, it was only Firefox and Opera that ever had it, until 2013.


Huh, I would have sworn that Internet Explorer had the blink tag at one point, but I think my parents had Netscape and then Mozilla pretty early so maybe that's what I'm confusing it with.

Regardless, I stand by my comment. Monsters! I want my browser to be obnoxious.


Never mind, Microsoft got you with <marquee>.

In theory, in 1996 Netscape and Microsoft agreed to kill <blink> and <marquee> <https://www.w3.org/People/Raggett/book4/ch02.html>, but although they were kept out of the spec, neither removed its implementation, and then IE dominated the browser market, and <marquee> became popular enough that the remaining parties were bullied into shipping it (Netscape in 2002, Presto in 2003, no idea about the KHTML/WebKit timeline), and so ultimately it was put into the HTML Standard.


KHTML added <marquee> support in October 2003 (commit 7bcdd98aa in the Chromium repository).

I have to say, that is some excellent sleuthing.

I think I remember reading articles about how to implement blink in IE using behaviors, some IE only thing that didn't take hold(?), Maybe this was around IE5.

IE was holding back the progress even before Chrome and Safari were a thing.

> IE was holding back the progress

Oh those times. IE accepted <table><tr><td><tr></table> whereas Nestscape demanded <table><tr><td></td></tr></table> and would just not render anything else - just blank grey

Humans loved it, when they had to type all this by hand, because missing /td would not kill your page.

Permissiveness won out.

I also remember the day JavaScript hit the net.

and all those "chat rooms" that did <meta refresh> to look live suddenly had no defence against this

<script>document.write('http://twistys.com/folder/porn.jpg')</script>

or alert bombs


Oh those times. <script>document.createElement("table").appendChild(document.createElement("table"))</script> would crash IE, and some similar stupidities could even cause a BSOD as late as Windows 98.

(I think that was one such incantation, but if it wasn’t quite that it was close.)


  <div class=article>
  <div class=article-header>
  <div class=article-quote>
  <div class=quote-body>
  ... a bunch more HTML ...
  </div>
  </div>
  </div>
  </div>
Just one quibble over this specific example (not the broader concept, which is sound): it probably didn’t have to be div soup to begin with. Something like this may have been more reasonable:

  <article>
  <header>
  <blockquote>
  <p class=quote-body>
  ... a bunch more HTML ...
  </p>
  </blockquote>
  </header>
  </article>

This example also shows a weakness of custom tags compared with using the class attribute. An element can have only single name but may have several classes. And as classes are unordered set, one cannot in general emulate that with several elements as the nesting introduces an order absent in the class list.

I’d argue it’s a strength. You still have classes and custom attributes to reach for when you want an (effectively) unordered set, the difference is just that you define some boundary that’s exclusive. This reflects reality. Some helper classes work together by just slapping them together, but component-like classes, like a toggle and a hero image, don’t. If you do want to combine them, you need to think about how, potentially rearchitect, and implement it whether you’re using classes or tag names.

Good use case for @container, @scope and :has(), where you forgo class definitions and use --custom-properties on the parent scope/container which are inherited downwards based on the existence of a scoped DOM pattern/container query, or 'upwards' by using a :has(child-selector) on the parent.

Although be sure to avoid too many :has(:nth-child(n of complex selector)) in case of frequent DOM updates.


Backend developers of HN downvoting this smh.

Honestly it depends what you're doing. A tag name is only correct when it unambiguously specifies the content. As in, a header is just a header - there's no "dual nature" that we have to support by allowing multiple tag names. This means the ontology you're representing has to be "linear" - you can have more specific and less specific tags, but never a "fork" where you could really choose either more-specific tag in order to emphasise a different "part" of the tag. Classes should always be for secondary properties, which are not the main "essence" of the content.

All I say above is a just a particular way of thinking about document markup, of course. If you don't agree with it, then tags are probably the wrong way to express what you're thinking of.


Not trying to be rude but to me that is the essence of composition which feels perfect to me

Hot take: div soup isnt bad because html isn't purely structural. It's a natural consequence of a poor design decision. Div soup is a consequence of the design decision to couple html elements to styling, state management, etc.

It made sense in 1996. It does not make sense now.


There are many patches of almost-identical sites.

Some of them are due to many people using the same theme.

Some of them are expired or parked domains, which I reckon should be detected and excluded.


Yeah those clusters are interesting. They stand out, so they are the first thing I zoomed in on, then I realized they're all just stock resume sites. Quickly realize the clusters are something to avoid. Turns out to be an effective visualization method.

The thing I find interesting is where the grouping is robust to colour variations: one of the bigger groups is around 25% from left, 20% from bottom, all one theme but in a wide variety of colours.

Yeah, I wonder why parked domains are included. Are there not at least 1 million actual websites?

>Some of them are due to many people using the same theme.

Teeming masses of sites using what probably seems to the authors as a fresh, unconventional look but ends up being Yet Another.


I doubt anyone selecting a popular theme is confused by the fact that it’s popular. I use the default Mediawiki theme for mine, for instance.

I’ve also been doing it for quite a few years, and I think I had it rejected by a machine once, and I had it questioned by a human once.

I’ve had way more problems from systems that think TLDs are two or three characters (which has never been true).


Quite a bit of this, mainly later on, feels unjust. Many are problems about mobile devices, not the web. Sizes don’t mean what you might expect? They don’t on any platform. A pixel hasn’t been a physical pixel reliably for at least fifteen years, and far longer in some ecosystems. Physical units never matched reality reliably, which is part of the reason they have steadily been phased out or discouraged across all platforms (Firefox’s mozmm unit is a fun piece of history: it tried to be one physical millimetre).

> One way we could have ensured that designs are accessible is to make it impossible to build anything else.

The only way of achieving this is by hobbling the web in a way that I guarantee would have killed it.

> The <input> tag is like 30 years old, but that has apparently not been enough time for us to figure out how to make it usable!

It was enough time. <input> was fine. But then devices without physical keyboards came along, and ruined it.

You’ll have the same problems if you try adding text input to your landscape mobile game using the platform’s native toolkit. In these areas, the web is not the problem: phones are, due to their limited screen size and different input methods; and mixed-input devices/platforms are—Windows two-in-ones are full of touch/pen niggles Android doesn’t have, whether you’re web or native (and Android with a pointer has issues in the other direction).


Web as a platform is universally deployed on mobile devices. Whether it is theoretically impeccable or not (heh), the way it works in practice is such that it does not isolate the author from the shortcomings of the target native platform. Though it tries to, and it sort of promises that in the standards, it fails to consistently deliver, especially on iOS where Apple virtually does not allow competition. Such is the sad reality of the web platform.

Surely the web cannot be blamed for Apple refusing to support the web.

> It was enough time. <input> was fine. But then devices without physical keyboards came along, and ruined it.

Maybe the default text input method on touchscreens should be dictation.


> LocalStorage is not available in private browsing mode. Other browsers just treat it as ephemeral/SessionStorage basically.

Correction: it’s not available in Firefox either, throws on get/set. It’s the Chromium family that’s the odd one out, but it’s so popular and testing in other browsers’ private windows so uncommon that developers often don’t realise that localStorage is fallible.


I’ve been noticing DuckDuckGo search results increasingly frequently doing this. They used to either use the <meta name=description> (which is subject to abuse by the site) or show an excerpt from the page text highlighting the keyword matches (which is often most helpful), but from time to time now I see useful meta descriptions or keyword matches sidelined in favour of what I presume is Microsoft-generated clickbaity slop of a “learn more about such-and-such” kind, occasionally irrelevant to the actual article’s text or even inconsistent with it.

I feel like indentation is a really useful structural signal that has been hijacked, in C-family languages, by unnecessarily strict conventions and most recently by autoformatters, to correspond exclusively to language structure, when it could be used for semantic structure as well (or occasionally instead).

Much of the value of this block pattern is that it makes the scope of the intermediate variables clear, so that you have no doubt that you don’t need to keep them in mind outside that scope.

But it’s also about logical grouping of concepts. And that you can achieve with simple ad hoc indentation:

  fn foo(cfg_file: &str) -> anyhow::Result<()> {
      // Load the configuration from the file.
          // Cached regular expression for stripping comments.
          static STRIP_COMMENTS: LazyLock<Regex> = LazyLock::new(|| {
              RegexBuilder::new(r"//.*").multi_line(true).build().expect("regex build failed")
          });

          // Load the raw bytes of the file.
          let raw_data = fs::read(cfg_file)?;

          // Convert to a string to the regex can work on it.
          let data_string = String::from_utf8(&raw_data)?;

          // Strip out all comments.
          let stripped_data = STRIP_COMMENTS.replace(&config_string, "");

          // Parse as JSON.
          let config = serde_json::from_str(&stripped_data)?;

      // Do some work based on this data.
          send_http_request(&config.url1)?;
          send_http_request(&config.url2)?;
          send_http_request(&config.url3)?;

      Ok(())
  }
(Aside: that code is dreadful. None of the inner-level comments are useful, and should be deleted (one of them is even misleading). .multi_line(true) does nothing here (it only changes the meanings of ^ and $; see also .dot_matches_new_line(true)). There is no binding config_string (it was named data_string). String::from_utf8 doesn’t take a reference. fs::read_to_string should have been used instead of fs::read + String::from_utf8. Regex::replace_all was presumably intended.)

It might seem odd if you’re not used to it, but I’ve been finding it useful for grouping, especially in languages that aren’t expression-oriented. Tooling may be able to make it foldable, too.

I’ve been making a lightweight markup language for the last few years, and its structure (meaning things like heading levels, lists, &c.) has over time become almost entirely indentation-based. I find it really nice. (AsciiDoc is violently flat. reStructuredText is mostly indented but not with headings. Markdown is mostly flat with painfully bad and footgunny rules around indentation.)

—⁂—

A related issue. You frequently end up with multiple levels of indentation where you really only want one. A simple case I wrote yesterday in Svelte and was bothered by:

  $effect(() => {
      if (loaded) {
          … lots of code …
      }
  });
In some ancient code styles it might have been written like this instead:

  $effect(() => { if (loaded) {
      … lots of code …
  } });
Not the prettiest due to the extra mandatory curlies, but it’s fine, and the structure reasonable. In Rust it’s nicer:

  effect(|| if loaded {
      … lots of code …
  });
But rustfmt would insist on returning it to this disappointment:

  effect(|| {
      if loaded {
          // … lots of code …
      }
  });
Perhaps the biggest reason around normalising indentation and brace practice was bugs like the “goto fail” one. I think there’s a different path: make the curly braces mandatory (like Rust does), and have tooling check that matching braces are at the same level of indentation. Then the problem can’t occur. Once that’s taken care of, I really see no reason not to write things more compactly, when you decide it is nicer, which I find quite frequently compared with things like rustfmt.

I would like to see people experiment with indentation a bit more.

—⁂—

One related concept from Microsoft: regions. Cleanest in C♯, `#region …` / `#endregion` pragmas which can introduce code folding or outlining or whatever in IDEs.


This has the effect that you’re shifting the list rather than the item. And yet your actual controls are anchored to the item.

On a touch device, to shift an item from the middle of a list to the top:

• With traditional drag-and-drop: press in the middle (long press or regular press on a movement grabby), drag upwards, release.

• With this: tap in the middle, on the item, then press anywhere, drag down, release.

It’s uncomfortable. The logical entity you’re manipulating is the item, but you’re having to do it by interacting with the list, and if your drag starts on the item it’ll achieve the opposite of what you want.

It may also interact a little poorly with retracting browser chrome, which is very common on mobile. I’d definitely say it does on Firefox for Android with top address bar.

As for other platforms… ouch. With a precise touchpad it’s bizarre and uncomfortable but functional (though the scroll direction thing will probably hit even harder and be even more frustrating); with a mouse with indexed scrolling it’s fairly fundamentally unusable.

All up, although it’s an interesting direction to explore, I don’t like it at all at present, and doubt the scrolling aspect can be salvaged. Direct manipulation is good.


I agree, this doesn't make sense. Also how can you place the item when there is no space to put it? If you want to mimic reality you should: 1) drag and drop outside of the list the item you want to move putsode the list 2) drag and drop the item in the place you want to put your selection 3) place your pick in the empty space 4) quietly discard the item you dislodged 5) wait for people to point out you are now missing one item 6) drag and drop the person under the carpet 7) repeat until no criticism

It should be at least theoretically possible: each IP address is assigned to an organisation running the IP routing prefix, and you can look that up easily, and they should have some sort of abuse channel, or at the very least a legal system should be able to compel them to cooperate and give up the information they’re required to have.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: