Components

Search & Results

The surface the company is named after. The found state settled what a match looks like in all four registers the platform offers and then shipped none of them on a page, because the system had no page that answers a question. This is that page: a control, a register of answers, and one decision about where the light goes that the rest of the chapter had left open.

The control

A <form role="search"> around one .cf-field and one button. No new field drawing: a search box is a text input, and the system already has one — underlined, no box, mono label. Adding a second input style so this one could carry a magnifier would be two drawings for one thing.

<form class="cf-search" role="search" action="/suche" method="get">
  <div class="cf-field cf-search__field">
    <label class="cf-field__label" for="q">Suchbegriff</label>
    <input class="cf-field__input" type="search" id="q" name="q" value="Telemetrie"
           autocomplete="off" spellcheck="false" enterkeyhint="search">
  </div>
  <button class="cf-btn cf-btn--solid cf-search__submit" type="submit">
    Suchen
    <svg class="cf-arrow" aria-hidden="true"><use href="#cf-arrow"></use></svg>
  </button>
</form>
method="get", and it is not a preference. The query has to end up in the address, because a result set that cannot be linked, bookmarked or reached with the back button is not a page — it is a state that happened once. Every listing in this system already works this way. The filter is the URL is the rule, and a query is a filter — where a static file cannot answer one, the state gets an address of its own instead: the News topic filter is a page per topic, news-thema-<slug>.html, and never a query string nothing serves.
It wraps; it does not fold at a threshold. The row has two parts and the second is a fixed width, so flex-wrap answers “does it still fit” without adding a consumer to the breakpoint register. That register is a list to be added to deliberately, and two things in a row is not a reason.

The register of answers

An <ol>, because the order is a claim. Each result is a block of type standing on a rule — no box, no fill, no corner, nothing that would make it a card. That is the same claim the found state makes about a marked word one scale down: an isometric object has no bounding box, what places it is the lattice edge under it. A result is a paragraph standing on one.

Treffer

2 von 6
  1. Seite

    Expertise — Telemetrie-Analytik und Datenintegration

    Vier Felder, ein Problem: die Daten liegen an, nur nicht zusammen. Der Weg dahin ist in allen vier derselbe — vom Sensor bis zur Auswertung, ohne Bruchstelle in der Mitte.

    control-f.de/expertise

  2. Beitrag · 01.01.2025

    Digitale Zwillinge im Energiesektor: Simulation trifft Realität

    Das Datenfundament: Bevor irgendetwas simuliert wird, muss die Telemetrie stimmen. In den Projekten, die wir seit 2022 begleitet haben, lagen die Probleme fast immer davor.

    control-f.de/news/digitale-zwillinge-im-energiesektor

Both links above are live. Follow either one and the destination page opens scrolled to the quoted phrase with that phrase lit — which is the whole point of the next section.

<ol class="cf-results" role="list">
  <li class="cf-result">
    <p class="cf-result__meta">
      <span aria-hidden="true">01</span>
      <span>Seite</span>
    </p>
    <h3 class="cf-result__title">
      <a class="cf-result__link" href="/expertise#:~:text=Telemetrie%2DAnalytik">
        Expertise — <mark class="cf-mark">Telemetrie</mark>-Analytik
      </a>
    </h3>
    <p class="cf-result__excerpt">
      Vier Felder, ein Problem: die Daten liegen an, nur nicht zusammen.
    </p>
    <p class="cf-result__path">control-f.de/expertise</p>
  </li>
</ol>
Every result draws its own bottom rule, the last one included. The interior rules are divisions — content on both sides — and the closing one is an edge, which closes the register. Both are sanctioned uses in where a line may go. This is the one place the system deliberately does not follow .cf-blog-card:last-child { border-bottom: 0 }: that rule exists because the grid container already draws the bottom edge, and this list has no container.

Contour here, light there

The found state has two rungs. Every match is contour — the ground line alone. One match is light — the same word with lime behind it — and the chapter is explicit that there is exactly one, ever, because it means the hit the reader is on.

On a result page the reader is on none of them. They have not chosen yet; that is what the page is for. So .cf-mark--current has nothing to attach to and a result set is drawn entirely in contour — six matches, six ground lines, no light. The page's one lime moment goes where it goes on every other listing in the system: the call to action in the footer.

The light is not withheld, it is deferred. Every result link carries a #:~:text= fragment quoting the phrase in its own excerpt. Click one and the destination page arrives scrolled to that phrase with it drawn in the lit rung — by ::target-text, which base.css has styled since the found state shipped. The destination implements nothing. It only has to have drawn the state.

So the found state's two rungs are not two treatments of a word on one page. They are the question and the answer, one page apart: the register of candidates is contour, and the thing you were looking for lights up when you get there. That is the brand's own argument — data can be found in a space rather than read off a sheet — running across a navigation rather than inside a paragraph.

Encoding the fragment is the only fussy part, and it has one trap. - is the delimiter for the prefix-,start,end,-suffix form, so a literal hyphen inside the quoted phrase must be written %2D or the browser reads half the phrase as a prefix and matches nothing — silently, because a fragment that does not match simply does nothing. Space is %20, and non-ASCII is UTF-8 percent-encoded as usual (ü%C3%BC).

Phrase in the excerptFragment
muss die Telemetrie stimmen#:~:text=muss%20die%20Telemetrie%20stimmen
Telemetrie-Analytik und Datenintegration#:~:text=Telemetrie%2DAnalytik%20und%20Datenintegration
Big Data-Plattformen für Telemetriedaten#:~:text=Big%20Data%2DPlattformen%20f%C3%BCr%20Telemetriedaten

Keep the quoted phrase to the shortest run that is unique on the target page. The fragment matches the first occurrence, so a phrase that repeats sends the reader to the wrong one, and a phrase long enough to span an element boundary the editor later changes will stop matching. Four to six words is the working band. Where a phrase cannot be made unique, the textStart,textEnd form (#:~:text=Bevor%20irgendetwas,stimmen) pins both ends instead.

No answer

Zero results is not an error and must not be drawn as one: the search worked, the answer is empty. It takes .cf-error--inline, the same component a listing renders in place of its grid when nothing is left to draw, served at 200.

0 Treffer

Dazu steht hier nichts.

Für Rhombendodekaeder gibt es auf control-f.de keine Fundstelle. Ein kürzerer Begriff oder ein anderer Bereich führt weiter — die Suche schneidet nicht an Wortgrenzen ab, Telemetrie findet also auch Telemetriedaten.

Name the term that failed and say what would work. “Keine Ergebnisse” tells the reader something they already know. The two things they do not know are whether the site understood the query and what to try instead — so the empty state quotes the term back and states one property of the index (substring matching, which is the property that matters in a language that compounds).

Anatomy

PartValue
.cf-searchflex row, --space-4 gap, aligned on the field's baseline rule; wraps below its own content width
.cf-search__fieldflex: 1 1 16rem — grows, and 16 rem is the basis at which a query is still readable
.cf-search__submit.cf-btn--solid. The one filled control on the page; its label is the foil, not lime
.cf-results1 px top rule in full ink — or none, when the section header above carries --flush and supplies it
.cf-result--space-6 (24 px) above and below, 1 px bottom rule in full ink, no box
Result on hover or focus--sheen-panel travels across, 480 ms — the same move the blog card and the accordion row make
.cf-result__metaGeist Mono, 11 px, uppercase, tabular, --text-secondary
Ordinaltwo digits, aria-hidden — the <ol> already carries the position
.cf-result__titlePublica Sans, --text-h4 (20 px), regular, --leading-normal
.cf-result__linkno underline at rest; 1 px underline at 0.2em on hover and :focus-visible
.cf-result__excerpt14 px, --leading-relaxed, capped at --measure-prose (53 ch), --text-secondary
.cf-result__pathGeist Mono, 11 px, --text-secondary, truncated at the end with an ellipsis
Matches.cf-mark throughout — contour rung, 2 px ground line. Never .cf-mark--current
Lime on the pagenone in this component. It is spent on the footer CTA
Why the link underline is 1 px and the match's ground line is 2 px. They are different marks and have to stay distinguishable inside the same sentence: an underline says this goes somewhere, a ground line says this is what you searched for. The found state took the heavier weight precisely so that a link and a match are never the same drawing — the found state measures the collision.

Behaviour

Accessibility

Rules

Do

  • Put the query in the URL and echo it back in the field, the title and the header.
  • Mark hits with <mark class="cf-mark">, server-rendered, in the title and the excerpt both.
  • Give every result a #:~:text= fragment quoting its own excerpt, four to six words, hyphens as %2D.
  • State the address of each answer. A ranking the reader cannot check is a ranking they have to trust.
  • Draw zero results with .cf-error--inline at 200, quoting the term that failed.

Don't

  • Never light a match on a result page. There is no current hit until the reader chooses one, and a lit candidate is a page pretending to have decided.
  • Don't make a result a card. No box, no fill, no corner — it stands on a rule like everything else in this system.
  • Don't intercept Ctrl+F to open this form. The browser's find belongs to the reader; this is an addition to it. → The found state
  • Don't let the search page be indexed. noindex, follow — the content lives on the pages it points at.
  • Don't quote a phrase in the fragment that repeats on the target page. It matches the first occurrence and fails silently.
  • Don't add a second input style for search. The system has one field drawing.

Where it lands

The Suche pattern is the whole page — header, control, six results, no pagination, the footer taking the page's one light. 404 routes to it, because a reader who has arrived at a page that does not exist is exactly the reader with a query.

The main navigation carries it now, and that question is closed. This note used to say the opposite and to say why: both Figma mockups draw a six-item nav bar, the bar is measured to 417 × 41, and a seventh item is a change to the drawing rather than to the code. It left the decision open — “nav, footer, or neither” — and the answer is both. Search is the seventh route, last in the list and before the language switch, because it is the one route that is a way of finding the others; the switch stays last because it is the one control that moves you between editions rather than through the site.

It is a label on the plate and not a control with a contour, and that follows the bar's own doctrine rather than taste: /suche is a page, the field is on it, and a search box in the chrome would be the second field drawing this system has spent the whole chapter refusing. Measured at 1280 px: the plate goes from 733 px to 802 px and its height does not move — 70 px, which is the label at --text-xs plus the list's --space-1 gap. The plate is max-content under a max-width: 100%, so nothing in the drawing had to move to make room, and the folded bar below 780 px carries the seventh link in the panel like the other six.