Chwile Ulotne – jak zbudować prostą stronę w jednym pliku (i dlaczego czasem to wystarcza)

DEMO strony

„Nie bogactwo, a prostota szacunek budzi.”

Tą myślą otwiera się moja mini-strona Chwile Ulotne. Znajdziesz tam jedno zdjęcie, kilka zdań i dedykację. Zero „fajerwerków”, za to intencja: zatrzymać na moment to, co ważne.

Co tu właściwie jest?

Na stronie widać trzy rzeczy:

  1. Sentencja/tytuł – krótkie zdanie prowadzące odbiorcę.
  2. Obraz – jeden plik together.jpg z tekstem osadzonym bezpośrednio na grafice (poemat/kaption stanowi część obrazu).
  3. Dedykacja – „Z dedykacją ku pamięci Dziadka oraz zainspirowane wspomnieniami o pewnej dziewczynie.”

Technicznie to idealny przykład „one-file website”: wystarczy pojedynczy index.html z kilkoma stylami w <style> i minimalnym skryptem w <script> (albo nawet bez niego). Zero AI w kodzie – wszystko ręcznie, od człowieka. Siła tkwi w wyborze i kompozycji, nie w ilości bibliotek.

Dlaczego jeden plik?

  • Szybkość i czytelność: otwierasz edytor, zapisujesz, gotowe.
  • Kontrola: rozumiesz każdą linijkę.
  • Archiwizacja: jedna paczka, łatwo zachować i przenieść.

To nie jest rozwiązanie „na wszystko”, ale gdy treści jest mało, a przekaz ma być szczery i skupiony – to strzał w dziesiątkę.

Minimalny szablon „one-file” (HTML + CSS + JS)

Poniżej przykład, który odtwarza układ: tytuł, obraz, podpis/dedykacja. Zadbane typografia, responsywność i drobiazgowy „dotyk” w postaci płynnego pojawiania się treści. Bez bibliotek, bez frameworków, zero AI – czysty HTML/CSS/JS.

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chwile Ulotne</title>
    <style>
        body {
            background-color: black;
        }
        header, figcaption, footer{
            color: white;
        }
        .video-list {
            list-style-type: none;
            padding: 0;
            margin: 0;
        }
        header, main, li, figure, footer {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 20px;
        }
        header {
            position: absolute;
            left: 0;
            right: 0;
        }
        .fullscreen-list {
            margin: 0;
            padding: 0;
            list-style-type: none;
        }
        .fullscreen-list li {
            height: 100vh;
            width: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            box-sizing: border-box;
            padding: 20px;
            position: relative;
        }
        @media (max-width: 768px) {
            .fullscreen-list li {
                font-size: 1.5rem;
                padding: 10px;
            }
        }
        .fullscreen-list li:nth-child(1)::after,
        .fullscreen-list li:nth-child(2)::after{    
            color: white;
            content: "↓";
            position: absolute;
            bottom: 150px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 2rem;
            animation: bounce 2s infinite;
        }
        @keyframes bounce {
            0%, 20%, 50%, 80%, 100% {
                transform: translateX(-50%) translateY(0);
            }
            40% {
                transform: translateX(-50%) translateY(-10px);
            }
            60% {
                transform: translateX(-50%) translateY(-5px);
            }
        }
        p{
            color: white;
            text-align: center;
        }
        .spaceY{
            padding-top: 40px;
            padding-bottom: 10px;
        }
    </style>
</head>
<body>
    <header>
        <h1>„Nie bogactwo, a prostota szacunek budzi.”</h1>
    </header>
    <main>
        <ul class="video-list fullscreen-list">
            <li onclick="scrollToNext()">
                <iframe width="560" height="315" src="https://www.youtube.com/embed/o1UXBC7whrQ?si=jdZUw3Fkq_UBTUo1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
            </li>
            <li onclick="scrollToNext()">
                <iframe width="560" height="315" src="https://www.youtube.com/embed/kOzQ7yR7w74?si=nfySpFHXSyI2ESnl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
            </li>
            <li>
                <figure>
                <img width="460" src="together.jpg" alt="Together" />
                <figcaption>„Requiescat in pace” (R.I.P.).</figcaption>
                </figure>
                <div class="spaceY"></div>
                <p>„Z dedykacją ku pamięci Dziadka<br>
                    oraz zainspirowane wspomnieniami o pewnej dziewczynie.”
                <div class="spaceY"></div>
            </li>
               
        </ul>
    </main>
    <footer>
        
    </footer>
    <script>
        function scrollToNext() {
            window.scrollBy({
                top: window.innerHeight,
                behavior: 'smooth'
            });
        }

    </script>
</body>
</html>

Co warto zauważyć:

  • Wszystkie style w <style>, zero zewnętrznych arkuszy.
  • Responsywność dzięki szerokościom procentowym.
  • Mały skrypt tylko do ustawienia animacji wejścia – można go usunąć, jeśli wolisz absolutne minimum.

Warstwa emocji

Strona nie jest „portfolio” ani „landingiem” do sprzedaży. To przystań. Zdjęcie opowiada o dwóch osobach – o pamięci, która mówi szeptem, i o drodze, która dopiero się rysuje. Proste słowa, jeden obraz, krótka dedykacja… i wystarczy.

Kiedy prostota wygrywa?

  • Gdy treść udźwignie ciszę (nie potrzebuje wielu sekcji i efektów).
  • Gdy chcesz, by odbiorca skupił się na jednym komunikacie.
  • Gdy liczysz na lekkość publikacji i łatwość przeniesienia.

Jeśli kiedyś ta strona urośnie – dołożysz nawigację, więcej zdjęć, osobne pliki CSS/JS. Dziś jednak niech wygra to, co najważniejsze: przesłanie.


PS: „One-file website” to także świetne ćwiczenie rzemiosła. Każdy znak ma znaczenie. Każda linia jest decyzją. I może właśnie dlatego – choć tak prosta – taka strona bywa bardziej osobista niż niejedna wielka witryna.

Kalkulator w przeglądarce z JavaScript

Pokażę jak to dzięki pomocy jednej funkcji JavaScript – eval() i podstawowej znajomości HTML, CSS i JavaScript można zbudować kalkulator w przeglądarce internetowej.

Od prostej wersji z obliczeniami w konsoli:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Calculator</title>
</head>

<body>
  <p>
    <button onclick="
      calculation +='1';
      console.log(calculation);
      ">
      1
    </button>
    <button onclick="
    calculation +='2';
    console.log(calculation);
    ">
      2
    </button>
    <button onclick="
    calculation +='3';
    console.log(calculation);
    ">
      3
    </button>
    <button onclick="
    calculation += ' + ';
    ">
      +
    </button>
  </p>
  <p>
    <button onclick="
      calculation +='4';
      console.log(calculation);
      ">
      4
    </button>
    <button onclick="
      calculation +='5';
      console.log(calculation);
      ">
      5
    </button>
    <button onclick="
      calculation +='6';
      console.log(calculation);
      ">
      6
    </button>
    <button onclick="
      calculation += ' - ';
      ">
      -
    </button>
  </p>
  <p>
    <button onclick="
      calculation +='7';
      console.log(calculation);
      ">
      7
    </button>
    <button onclick="
      calculation +='8';
      console.log(calculation);
      ">
      8
    </button>
    <button onclick="
      calculation +='9';
      console.log(calculation);
      ">
      9
    </button>
    <button onclick="
      calculation += ' * ';
      ">
      *
    </button>
  </p>
  <p>
    <button onclick="
    calculation +='0';
    console.log(calculation);
    ">
      0
    </button>
    <button onclick="
calculation += '.';
">
      .
    </button>

    <button onclick="
    calculation = eval(calculation);
    console.log(calculation);
    ">
      =
    </button>

    <button onclick="
      calculation += ' / ';
      ">
      /
    </button>
  </p>
  <p>
    <button onclick="
    calculation = '';
    console.log(0);
    ">
      Clear
    </button>
  </p>

  <script>
    let calculation = "";
  </script>
</body>

</html>

 

 

Z dodaniem domyślnych stylów i animacji z Bootstrap-a:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calculator</title>
  <!-- Add Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    .calc-button {
      width: 60px;
      height: 60px;
      margin: 5px;
    }

    .display {
      font-size: 2rem;
      margin-bottom: 20px;
      text-align: right;
      padding: 10px;
    }
  </style>
</head>

<body class="bg-light">

  <div class="container mt-5">
    <div class="row justify-content-center">
      <div class="col-md-4">
        <div class="card p-3 shadow">
          <div class="display bg-white border rounded" id="display">0</div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('1')">1</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('2')">2</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('3')">3</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' + ')">+</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('4')">4</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('5')">5</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('6')">6</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' - ')">-</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('7')">7</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('8')">8</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('9')">9</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' * ')">*</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('0')">0</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('.')">.</button>
            <button class="btn btn-success calc-button" onclick="calculate()">=</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' / ')">/</button>
          </div>

          <div class="d-flex justify-content-center">
            <button class="btn btn-danger calc-button" onclick="clearCalculation()">Clear</button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Add Bootstrap JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>

  <script>
    let calculation = '';

    function updateCalculation(value) {
      calculation += value;
      document.getElementById('display').innerText = calculation;
    }

    function calculate() {
      try {
        calculation = eval(calculation);
        document.getElementById('display').innerText = calculation;
      } catch (e) {
        document.getElementById('display').innerText = 'Error';
      }
    }

    function clearCalculation() {
      calculation = '';
      document.getElementById('display').innerText = '0';
    }
  </script>
</body>

</html>

 

Później dodaniem więcej animacji korzystając z biblioteki jQuery:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calculator</title>

  <!-- Add Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
  <!-- Add jQuery -->
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <!-- Add jQuery UI for animations -->
  <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet">
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

  <style>
    .calc-button {
      width: 70px;
      height: 70px;
      margin: 8px;
      font-size: 1.5rem;
    }

    .display {
      font-size: 2.5rem;
      margin-bottom: 20px;
      text-align: right;
      padding: 15px;
      background-color: #f8f9fa;
    }

    .container {
      margin-top: 50px;
    }

    .btn-primary,
    .btn-warning,
    .btn-danger,
    .btn-success {
      transition: transform 0.1s ease;
    }
  </style>
</head>

<body class="bg-light">

  <div class="container">
    <div class="row justify-content-center">
      <div class="col-md-4">
        <div class="card p-4 shadow-lg rounded">
          <div class="display border rounded" id="display">0</div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('1')">1</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('2')">2</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('3')">3</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' + ')">+</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('4')">4</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('5')">5</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('6')">6</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' - ')">-</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('7')">7</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('8')">8</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('9')">9</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' * ')">*</button>
          </div>

          <div class="d-flex justify-content-between">
            <button class="btn btn-primary calc-button" onclick="updateCalculation('0')">0</button>
            <button class="btn btn-primary calc-button" onclick="updateCalculation('.')">.</button>
            <button class="btn btn-success calc-button" onclick="calculate()">=</button>
            <button class="btn btn-warning calc-button" onclick="updateCalculation(' / ')">/</button>
          </div>

          <div class="d-flex justify-content-center">
            <button class="btn btn-danger calc-button" onclick="clearCalculation()">Clear</button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Add Bootstrap JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>

  <script>
    let calculation = '';

    function updateCalculation(value) {
      // Add animations for button press
      animateButton(value);

      calculation += value;
      $("#display").text(calculation);
    }

    function calculate() {
      try {
        calculation = eval(calculation);
        $("#display").text(calculation).effect("bounce", { times: 3 }, 500);
      } catch (e) {
        $("#display").text('Error').effect("shake", { times: 3 }, 500);
      }
    }

    function clearCalculation() {
      calculation = '';
      $("#display").text('0').fadeOut(100).fadeIn(100);
    }

    // Add animation for button clicks
    function animateButton(value) {
      $(".btn").each(function () {
        if ($(this).text() === value) {
          $(this).addClass("pressed");
          $(this).css("transform", "scale(0.95)");
          setTimeout(() => {
            $(this).css("transform", "scale(1)");
          }, 100);
        }
      });
    }

    // Animation for button press style
    $(".btn").on("mousedown", function () {
      $(this).css("transform", "scale(0.95)");
    });
    $(".btn").on("mouseup", function () {
      $(this).css("transform", "scale(1)");
    });
  </script>

</body>

</html>

 

Kończąc na kalkulatorze z motywem prosto z Matrix-a:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Matrix Calculator</title>

  <style>
    body,
    html {
      margin: 0;
      padding: 0;
      height: 100%;
      background-color: #000;
      color: #00ff00;
      font-family: 'Courier New', monospace;
      overflow: hidden;
    }

    #matrix-bg {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
      pointer-events: none;
    }

    .matrix-column {
      position: absolute;
      top: -50px;
      font-size: 14px;
      line-height: 1.5;
    }

    .container {
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      z-index: 2;
    }

    .calculator {
      background-color: rgba(0, 20, 0, 0.8);
      border: 2px solid #00ff00;
      border-radius: 10px;
      padding: 20px;
      box-shadow: 0 0 20px #00ff00;
      transition: all 0.5s ease;
    }

    .calculator:hover {
      transform: scale(1.05);
      box-shadow: 0 0 30px #00ff00;
    }

    .display {
      width: 240px;
      height: 60px;
      margin-bottom: 20px;
      text-align: right;
      padding: 15px;
      background-color: #001400;
      color: #00ff00;
      border-radius: 5px;
      border: 1px solid #00ff00;
      text-shadow: 0 0 5px #00ff00;
      transition: all 0.5s ease;
      overflow-x: scroll;
      overflow-y: hidden;
      white-space: nowrap;
      font-size: 2.5rem;
      display: flexbox;
      align-items: center;
      justify-content: flex-end;
      cursor: text;
      user-select: text;
    }

    .display-content {
      transition: all 0.3s ease;
    }

    .display.animate .display-content {
      animation: pulse 0.5s;
    }

    @keyframes pulse {
      0% {
        transform: scale(1);
      }

      50% {
        transform: scale(1.1);
      }

      100% {
        transform: scale(1);
      }
    }

    .btn {
      width: 60px;
      height: 60px;
      margin: 5px;
      font-size: 1.2rem;
      background-color: #001400;
      color: #00ff00;
      border: 1px solid #00ff00;
      border-radius: 5px;
      transition: all 0.3s ease;
      position: relative;
      overflow: hidden;
    }

    .btn::before {
      content: '';
      position: absolute;
      top: 50%;
      left: 50%;
      width: 0;
      height: 0;
      background-color: rgba(0, 255, 0, 0.5);
      border-radius: 50%;
      transform: translate(-50%, -50%);
      transition: width 0.6s ease, height 0.6s ease;
    }

    .btn:hover {
      color: #000;
      box-shadow: 0 0 15px #00ff00;
    }

    .btn:hover::before {
      width: 200%;
      height: 200%;
    }

    .btn:active {
      transform: scale(0.95);
      box-shadow: 0 0 5px #00ff00;
    }

    .btn span {
      position: relative;
      z-index: 1;
    }

    @keyframes glowPulse {
      0% {
        box-shadow: 0 0 5px #00ff00;
      }

      50% {
        box-shadow: 0 0 20px #00ff00;
      }

      100% {
        box-shadow: 0 0 5px #00ff00;
      }
    }

    .btn:focus {
      outline: none;
      animation: glowPulse 1s infinite;
    }

    .display:focus {
      outline: none;
      box-shadow: 0 0 15px #00ff00;
    }
  </style>
</head>

<body>
  <div id="matrix-bg"></div>

  <div class="container">
    <div class="calculator">
      <div class="display" id="display">
        <div class="display-content">0</div>
      </div>
      <div>
        <button class="btn" data-value="7"><span>7</span></button>
        <button class="btn" data-value="8"><span>8</span></button>
        <button class="btn" data-value="9"><span>9</span></button>
        <button class="btn" data-value="+"><span>+</span></button>
      </div>
      <div>
        <button class="btn" data-value="4"><span>4</span></button>
        <button class="btn" data-value="5"><span>5</span></button>
        <button class="btn" data-value="6"><span>6</span></button>
        <button class="btn" data-value="-"><span>-</span></button>
      </div>
      <div>
        <button class="btn" data-value="1"><span>1</span></button>
        <button class="btn" data-value="2"><span>2</span></button>
        <button class="btn" data-value="3"><span>3</span></button>
        <button class="btn" data-value="*"><span>*</span></button>
      </div>
      <div>
        <button class="btn" data-value="0"><span>0</span></button>
        <button class="btn" data-value="."><span>.</span></button>
        <button class="btn" data-value="="><span>=</span></button>
        <button class="btn" data-value="/"><span>/</span></button>
      </div>
      <div>
        <button class="btn" data-value="clear"><span>Clear</span></button>
      </div>
    </div>
  </div>

  <script>
    const matrixBg = document.getElementById('matrix-bg');
    const display = document.getElementById('display');
    const displayContent = display.querySelector('.display-content');
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()_+-=[]{}|;:,.<>?';
    const rows = Math.floor((window.innerHeight + 50) / 20);
    let calculation = '';
    let isDisplayFocused = false;

    function createColumn() {
      const column = document.createElement('div');
      column.className = 'matrix-column';
      column.style.left = `${Math.random() * window.innerWidth}px`;
      let y = -50;
      let output = '';
      for (let j = 0; j < rows; j++) {
        output += characters[Math.floor(Math.random() * characters.length)] + '<br><br>';
      }
      column.innerHTML = output;
      matrixBg.appendChild(column);

      function updateColumn() {
        y += 5;
        if (y > window.innerHeight) {
          matrixBg.removeChild(column);
        } else {
          column.style.transform = `translateY(${y}px)`;
          requestAnimationFrame(updateColumn);
        }
      }
      requestAnimationFrame(updateColumn);
    }

    function startMatrixEffect() {
      createColumn();
      setTimeout(startMatrixEffect, Math.random() * 500);
    }

    for (let i = 0; i < 5; i++) {
      setTimeout(startMatrixEffect, i * 200);
    }

    function updateDisplay() {
      const scrollPosition = display.scrollLeft;
      displayContent.textContent = calculation || '0';
      display.classList.add('animate');
      setTimeout(() => display.classList.remove('animate'), 500);

      if (!isDisplayFocused) {
        display.scrollLeft = display.scrollWidth;
      } else {
        display.scrollLeft = scrollPosition;
      }
    }

    function handleButtonClick(e) {
      const btn = e.target.closest('.btn');
      if (!btn) return;

      btn.classList.add('active');
      setTimeout(() => btn.classList.remove('active'), 200);

      const value = btn.dataset.value;
      if (value === '=') {
        try {
          calculation = eval(calculation).toString();
        } catch (error) {
          calculation = 'Error';
        }
      } else if (value === 'clear') {
        calculation = '';
      } else {
        calculation += value;
      }
      updateDisplay();
    }

    document.querySelector('.calculator').addEventListener('click', handleButtonClick);

    // Make the display focusable
    display.tabIndex = 0;

    // Track focus state
    display.addEventListener('focus', () => {
      isDisplayFocused = true;
    });

    display.addEventListener('blur', () => {
      isDisplayFocused = false;
    });

    // Prevent default calculator behavior when interacting with the display
    display.addEventListener('mousedown', (e) => {
      e.stopPropagation();
    });

    display.addEventListener('touchstart', (e) => {
      e.stopPropagation();
    });

    // Prevent keyboard input on the display
    display.addEventListener('keydown', (e) => {
      e.preventDefault();
    });

    let lastTime = 0;
    function animate(currentTime) {
      if (currentTime - lastTime > 500) {
        createColumn();
        lastTime = currentTime;
      }
      requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
  </script>
</body>

</html>

 

Tutaj link do repozytorium z wszystkimi wersjami aplikacji: kalkulator-github

 

Oraz proste demo z działania:

 

Tabele w HTML i animacja JavaScript

W tym wpisie zaprezentuję możliwe zastosowanie HTML, CSS i JS do strony, w której są  odpowiednio ostylowane dwie tabele i animacja przewijania strony w JS.

Środowisko programistyczne użyte do utworzenia projektu to Visual Studio Code z rozszerzeniem „Live Server„.
Po zainstalowaniu i włączeniu wtyczki klikamy prawym przyciskiem myszy na utworzonym pliku HTML, a następnie w „open with Live Server”. Powinna nam się otworzyć domyślna przeglądarka z podglądem strony webowej.

Poniżej zdjęcia poglądowe jak to mniej więcej powinno wyglądać:

Od razu umieszczę końcowy kod ze szczegółowymi komentarzami, a następnie opiszę co po kolei tworzyłem.

<!-- plik HTML -->
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8"/>
<title>Let's go start</title>
<!-- zewnętrzny arkusz stylów-->
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<h1 class="header">
    <div class="wrapper">

        <table> <!--tabela w HTML-->
            <tr> <!-- naglowek -->
                <th colspan="4">USŁUGI INTERNETOWE</th> 
             </tr>
            <tr> <!-- naglowki-->
               <th>Nr</th> <th>HOSTING</th> <th>DOMENA_1</th> <th>DOMENA_2</th>
            </tr>
            <tr> <!-- wiersz-->
               <td>1</td> <td>100</td> <td>0</td> <td>40</td> <!-- kolumny-->
            </tr>
            <tr> 
                <td>2</td> <td>100</td> <td>40</td> <td>40</td> <!-- kolumny-->
             </tr>
             <tr> 
                <td>3</td> <td>120</td> <td>50</td> <td>50</td> <!-- kolumny-->
             </tr>
             <tr id="scroll"> <!-- utworzenie id w celu umożliwienia identyfikacji do animacji-->
                <td colspan="4">przewiń w dół</td>
             </tr>
         </table>
        
       
    </div>
    <div class="wrapper">
    <table>
        <tr>
            <th colspan="3">PODSUMOWANIE USŁUG INTERNETOWYCH<br>
                            na dzień xx.xx.xxxx</th>
        </tr>
        <tr>
            <th>HOSTING</th> <th>DOMENA_1</th> <th>DOMENA_2</th>
        </tr>
        <tr>
            <td>jest do xx.xx.xxxx</td> <td>jest do xx.xx.xxxx</td> <td>jest do xx.xx.xxxx</td>
        </tr>
        <tr>
            <td colspan="3">Dotychczasowy poniesiony koszt</td>
        </tr>
        <tr>
            <td>320</td> <td>90</td> <td>130</td>
        </tr>
        <tr>
            <td colspan="2">410</td>  <td>130</td>
        </tr>
        <tr>
            <td colspan="3">540 - łącznie zł</td>
        </tr>
    </table>
    </div>
</h1>
<!-- zewnętrzny plik javascript-->
<script src="js/script.js"></script>
</body>
</html>
/* plik CSS */
body{ /* tło strony */
    background-color: rgb(79, 173, 76);
}
.header{ /*kolor tekstu*/
    color: darkblue;
}
.wrapper{ /* najczęściej stosowana metoda wyśrodkowania elemntu
            wrapper musi być rozciągnięty na całą szerokość i wysokość okna */    
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

table, th, tr, td { /* utworzenie obramowania */
    border: 1px solid black;
}
th, td{ /* utworzenie odpowiedniego odstępu od obramowania i wycentrowania zawartości*/
    padding: 20px;
    text-align: center;
}
//plik JS
//pobranie elementu o id 'scroll' i w momencie jego kliknięcia wywołanie funkcji scroll()
document.getElementById("scroll").onclick = function() {scroll()};


//funkcja scroll z zainicjowana na 0 zmienną i oraz wywołaniem podfunkcji move()
function scroll(){
    i = 0;   
    move();
}


function move(){
    i++; //zwiększanie o jeden zmiennej i
    window.scrollBy(0,1); //przesuwanie ekranu w pionie
    /*jeżeli i będzie mniejsza o wysokość ekranu, wykonuj co pewien czas upłynięcia funkcję move(),
    czyli inaczej mówiąc przesuwaj w dół zawartość ekranu o całą jego wysokość względem czasu*/
    if (i < screen.height) setTimeout('move()',1);
}

Najpierw utworzyłem strukturę katalogów.
Odpowiednio folder js dla plików JS, CSS dla arkuszów styli, index.html pozostał w głównym katalogu. Oraz odpowiednio w katalogu css plik style.css, a w js script.js.

Na wstępie pisania strony tworzę typowy plik html w strukturze HTML5.
Od razu dodaje zewnętrzny arkusz styli w znaczniku head. A na końcu ciała body odwołanie do zewnętrznego skryptu JavaScript.

Początkowo mam zamiar wszystko wypośrodkować więc tworzę do tego celu div-a z nazwą klasy wrapper. Potem tak jak jest napisane w pliku arkuszów styli za pomocą .wrapper odwołuje się do tego elementu oraz go wypośrodkowuje w poziomie i pionie.

Przyszedł czas na utworzenie tabel.
Słowo kluczowe/ znacznik table odpowiada za utworzenie tabeli.
tr – to wiersz
th– nagłówek
td– podział na kolumny
Najpierw tworzymy wiersz, następnie w zależności ile chcemy kolumn tyle tworzymy nagłówków. Kolumny możemy łączyć za pomocą słowa kluczowego colspan, jako argument podajemy na ile kolumn dana kolumna ma się rozszerzyć.
Kolejno tworzymy następne wiersze i kolumny.
Czas na stylizację. Dodajemy do tabeli i wszystkiego co wewnątrz obramowanie. Stosując przecinek jak pokazane w przykładzie możemy bez multiplikowania kodu użyć do kilku elementów tego samego bloku CSS. Odpowiednio następnie dodaje odstęp w tabeli od obramowania i wypośrodkowuje tekst, żeby to w miarę estetycznie wyglądało.

Kolej na drugą tabelę. Pamiętam o tym, żeby tabela była umieszczona we wrapperze, żeby zachować odpowiednie ostylowanie co do wyśrodkowania.

I teraz końcowo dodaje identyfikator scroll do ostatniego wiersza w pierwszej tabeli w celu umożliwienia odwołania się w skrypcie do wywołania funkcji scroll po kliknięciu na wiersz w tabeli.

Plik JS to prosta głównie jedna funkcja move() odpowiedzialna za przewijanie strony w dół ekranu.

Poniżej końcowy efekt:

O

Link do repo:

https://github.com/traininguniverse/simple-table