aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/learn
diff options
context:
space:
mode:
authorneil_tsai <cdcd71517@gmail.com>2021-06-08 14:05:30 +0800
committerIrvin <irvinfly@gmail.com>2021-06-10 00:03:40 +0800
commitb74677bb9f6c57b275a28cf1e3645726b6253031 (patch)
tree45f75c6783eff05232d43d0eb05284accbb5c5b1 /files/zh-tw/learn
parent628bd05d5462f588dbef85b8cdfe2ddd4d3e851c (diff)
downloadtranslated-content-b74677bb9f6c57b275a28cf1e3645726b6253031.tar.gz
translated-content-b74677bb9f6c57b275a28cf1e3645726b6253031.tar.bz2
translated-content-b74677bb9f6c57b275a28cf1e3645726b6253031.zip
同步 svelte-todo-list-beginning en-US 內容 - 2021/06/08
Diffstat (limited to 'files/zh-tw/learn')
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/01-todo-list-app.pngbin0 -> 18319 bytes
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/02-todos-component-rendered.pngbin0 -> 5217 bytes
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/03-unstyled-todo-app.pngbin0 -> 21608 bytes
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/04-svelte-accessibility-support.pngbin0 -> 9272 bytes
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/05-styled-todo-app.pngbin0 -> 19347 bytes
-rw-r--r--files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/index.html762
6 files changed, 762 insertions, 0 deletions
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/01-todo-list-app.png b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/01-todo-list-app.png
new file mode 100644
index 0000000000..c1fc9ddbe0
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/01-todo-list-app.png
Binary files differ
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/02-todos-component-rendered.png b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/02-todos-component-rendered.png
new file mode 100644
index 0000000000..e9f581d794
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/02-todos-component-rendered.png
Binary files differ
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/03-unstyled-todo-app.png b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/03-unstyled-todo-app.png
new file mode 100644
index 0000000000..057e0fd7ec
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/03-unstyled-todo-app.png
Binary files differ
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/04-svelte-accessibility-support.png b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/04-svelte-accessibility-support.png
new file mode 100644
index 0000000000..cd6240c124
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/04-svelte-accessibility-support.png
Binary files differ
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/05-styled-todo-app.png b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/05-styled-todo-app.png
new file mode 100644
index 0000000000..b3fe2aa7e3
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/05-styled-todo-app.png
Binary files differ
diff --git a/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/index.html b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/index.html
new file mode 100644
index 0000000000..6209101b37
--- /dev/null
+++ b/files/zh-tw/learn/tools_and_testing/client-side_javascript_frameworks/svelte_todo_list_beginning/index.html
@@ -0,0 +1,762 @@
+---
+title: Starting our Svelte Todo list app
+slug: >-
+ Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning
+tags:
+ - Beginner
+ - Components
+ - Frameworks
+ - JavaScript
+ - Learn
+ - Svelte
+ - client-side
+ - state
+---
+<div>{{LearnSidebar}}<br>
+{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</div>
+
+<p class="summary">Now that we have a basic understanding of how things work in Svelte, we can start building our example app: a todo list. In this article we will first have a look at the desired functionality of our app, then we'll create a <code>Todos.svelte</code> component and put static markup and styles in place, leaving everything ready to start developing our To-Do list app features, which we'll go on to in subsequent articles.</p>
+
+<p class="summary">We want our users to be able to browse, add and delete tasks, and also to mark them as complete. This will be the basic functionality that we'll be developing in this tutorial series, plus we'll look at some more advanced concepts along the way too.</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">Prerequisites:</th>
+ <td>
+ <p>At minimum, it is recommended that you are familiar with the core <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, and <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> languages, and have knowledge of the <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">terminal/command line</a>.</p>
+
+ <p>You'll need a terminal with node + npm installed to compile and build your app.</p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">Objective:</th>
+ <td>To learn how to create a Svelte component, render it inside another component, pass data into it using props, and save its state.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Code_along_with_us">Code along with us</h2>
+
+<h3 id="Git">Git</h3>
+
+<p>Clone the github repo (if you haven't already done it) with:</p>
+
+<pre class="brush: bash">git clone https://github.com/opensas/mdn-svelte-tutorial.git</pre>
+
+<p>Then to get to the current app state, run</p>
+
+<pre class="brush: bash">cd mdn-svelte-tutorial/02-starting-our-todo-app</pre>
+
+<p>Or directly download the folder's content:</p>
+
+<pre class="brush: bash">npx degit opensas/mdn-svelte-tutorial/02-starting-our-todo-app</pre>
+
+<p>Remember to run <code>npm install &amp;&amp; npm run dev</code> to start your app in development mode.</p>
+
+<h3 id="REPL">REPL</h3>
+
+<p>To code along with us using the REPL, start at</p>
+
+<p><a href="https://svelte.dev/repl/b7b831ea3a354d3789cefbc31e2ca495?version=3.23.2">https://svelte.dev/repl/b7b831ea3a354d3789cefbc31e2ca495?version=3.23.2</a></p>
+
+<h2 id="Todo_list_app_features">Todo list app features</h2>
+
+<p>This is how our Todo list app wil look like once it's ready:</p>
+
+<p><img alt="typical todo list app, with a title of 'what needs to be done', an input to enter more todos, and a list of todos with checkboxes" src="01-todo-list-app.png"></p>
+
+<p>Using this UI our user will be able to:</p>
+
+<ul>
+ <li>Browse their tasks.</li>
+ <li>Mark tasks as completed/pending without deleting them.</li>
+ <li>Remove tasks.</li>
+ <li>Add new tasks.</li>
+ <li>Filter tasks by status: all tasks, active tasks, or completed tasks.</li>
+ <li>Edit tasks.</li>
+ <li>Mark all tasks as active/completed.</li>
+ <li>Remove all completed tasks.</li>
+</ul>
+
+<h2 id="Building_our_first_component">Building our first component</h2>
+
+<p>Let's create a <code>Todos.svelte</code> component — this will contain our list of todos.</p>
+
+<ol>
+ <li>
+ <p>Create a new folder — <code>src/components</code>.</p>
+
+ <div class="notecard note">
+ <p><strong>Note</strong>: you can put your components anywhere inside the <code>src</code> folder, but the <code>components</code> folder is a recognized convention to follow, allowing you to find your components easily.</p>
+ </div>
+ </li>
+ <li>
+ <p>Create a file named <code>src/components/Todos.svelte</code> with the following content:</p>
+
+ <pre class="brush: html">&lt;h1&gt;Svelte To-Do list&lt;/h1&gt;</pre>
+ </li>
+ <li>
+ <p>Change the <code>title</code> element in <code>public/index.html</code> to contain the text <em>Svelte To-do list</em>:</p>
+
+ <pre class="brush: html">&lt;title&gt;Svelte To-Do list&lt;/title&gt;</pre>
+ </li>
+ <li>
+ <p>Open <code>src/App.svelte</code> and replace its contents with the following:</p>
+
+ <pre class="brush: html">&lt;script&gt;
+ import Todos from './components/Todos.svelte'
+&lt;/script&gt;
+
+&lt;Todos /&gt;</pre>
+ </li>
+ <li>
+ <p>In development mode, Svelte will issue a warning in the browser console when specifying a prop that doesn't exist in the component; in this case we have a <code>name</code> prop being specified when we instantiate the <code>App</code> component inside <code>src/main.js</code>, which isn't used inside <code>App</code>. The console should currently give you a message along the lines of "&lt;App&gt; was created with unknown prop 'name'". To get rid of this, remove the <code>name</code> prop from <code>src/main.js</code>; it should now look like so:</p>
+
+ <pre class="brush: js">import App from './App.svelte'
+
+const app = new App({
+ target: document.body
+})
+
+export default app</pre>
+ </li>
+</ol>
+
+<p>Now if you check your testing server URL you'll see our <code>Todos.svelte</code> component being rendered:</p>
+
+<p><img alt="basic component rendering which a title that says 'Svelte to-do list'" src="02-todos-component-rendered.png" style="border-style: solid; border-width: 1px; display: block; margin: 0 auto;"></p>
+
+<h2 id="Adding_static_markup">Adding static markup</h2>
+
+<p>For the moment we will start with a static markup representation of our app, so you can see what it will look like. Copy and paste the following into our <code>Todos.svelte</code> component file, replacing the existing content:</p>
+
+<pre class="brush: html">&lt;!-- Todos.svelte --&gt;
+&lt;div class="todoapp stack-large"&gt;
+
+ &lt;!-- NewTodo --&gt;
+ &lt;form&gt;
+ &lt;h2 class="label-wrapper"&gt;
+ &lt;label for="todo-0" class="label__lg"&gt;
+ What needs to be done?
+ &lt;/label&gt;
+ &lt;/h2&gt;
+ &lt;input type="text" id="todo-0" autocomplete="off"
+ class="input input__lg" /&gt;
+ &lt;button type="submit" disabled="" class="btn btn__primary btn__lg"&gt;
+ Add
+ &lt;/button&gt;
+ &lt;/form&gt;
+
+ &lt;!-- Filter --&gt;
+ &lt;div class="filters btn-group stack-exception"&gt;
+ &lt;button class="btn toggle-btn" aria-pressed="true"&gt;
+ &lt;span class="visually-hidden"&gt;Show&lt;/span&gt;
+ &lt;span&gt;All&lt;/span&gt;
+ &lt;span class="visually-hidden"&gt;tasks&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;button class="btn toggle-btn" aria-pressed="false"&gt;
+ &lt;span class="visually-hidden"&gt;Show&lt;/span&gt;
+ &lt;span&gt;Active&lt;/span&gt;
+ &lt;span class="visually-hidden"&gt;tasks&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;button class="btn toggle-btn" aria-pressed="false"&gt;
+ &lt;span class="visually-hidden"&gt;Show&lt;/span&gt;
+ &lt;span&gt;Completed&lt;/span&gt;
+ &lt;span class="visually-hidden"&gt;tasks&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;/div&gt;
+
+ &lt;!-- TodosStatus --&gt;
+ &lt;h2 id="list-heading"&gt;2 out of 3 items completed&lt;/h2&gt;
+
+ &lt;!-- Todos --&gt;
+ &lt;ul role="list" class="todo-list stack-large" aria-labelledby="list-heading"&gt;
+
+ &lt;!-- todo-1 (editing mode) --&gt;
+ &lt;li class="todo"&gt;
+ &lt;div class="stack-small"&gt;
+ &lt;form class="stack-small"&gt;
+ &lt;div class="form-group"&gt;
+ &lt;label for="todo-1" class="todo-label"&gt;
+ New name for 'Create a Svelte starter app'
+ &lt;/label&gt;
+ &lt;input type="text" id="todo-1" autocomplete="off" class="todo-text" /&gt;
+ &lt;/div&gt;
+ &lt;div class="btn-group"&gt;
+ &lt;button class="btn todo-cancel" type="button"&gt;
+ Cancel
+ &lt;span class="visually-hidden"&gt;renaming Create a Svelte starter app&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;button class="btn btn__primary todo-edit" type="submit"&gt;
+ Save
+ &lt;span class="visually-hidden"&gt;new name for Create a Svelte starter app&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;/div&gt;
+ &lt;/form&gt;
+ &lt;/div&gt;
+ &lt;/li&gt;
+
+ &lt;!-- todo-2 --&gt;
+ &lt;li class="todo"&gt;
+ &lt;div class="stack-small"&gt;
+ &lt;div class="c-cb"&gt;
+ &lt;input type="checkbox" id="todo-2" checked/&gt;
+ &lt;label for="todo-2" class="todo-label"&gt;
+ Create your first component
+ &lt;/label&gt;
+ &lt;/div&gt;
+ &lt;div class="btn-group"&gt;
+ &lt;button type="button" class="btn"&gt;
+ Edit
+ &lt;span class="visually-hidden"&gt;Create your first component&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;button type="button" class="btn btn__danger"&gt;
+ Delete
+ &lt;span class="visually-hidden"&gt;Create your first component&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;/div&gt;
+ &lt;/div&gt;
+ &lt;/li&gt;
+
+ &lt;!-- todo-3 --&gt;
+ &lt;li class="todo"&gt;
+ &lt;div class="stack-small"&gt;
+ &lt;div class="c-cb"&gt;
+ &lt;input type="checkbox" id="todo-3" /&gt;
+ &lt;label for="todo-3" class="todo-label"&gt;
+ Complete the rest of the tutorial
+ &lt;/label&gt;
+ &lt;/div&gt;
+ &lt;div class="btn-group"&gt;
+ &lt;button type="button" class="btn"&gt;
+ Edit
+ &lt;span class="visually-hidden"&gt;Complete the rest of the tutorial&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;button type="button" class="btn btn__danger"&gt;
+ Delete
+ &lt;span class="visually-hidden"&gt;Complete the rest of the tutorial&lt;/span&gt;
+ &lt;/button&gt;
+ &lt;/div&gt;
+ &lt;/div&gt;
+ &lt;/li&gt;
+ &lt;/ul&gt;
+
+ &lt;hr /&gt;
+
+ &lt;!-- MoreActions --&gt;
+ &lt;div class="btn-group"&gt;
+ &lt;button type="button" class="btn btn__primary"&gt;Check all&lt;/button&gt;
+ &lt;button type="button" class="btn btn__primary"&gt;Remove completed&lt;/button&gt;
+ &lt;/div&gt;
+
+&lt;/div&gt;</pre>
+
+<p>Check the rendered out again, and you'll see something like this:</p>
+
+<p><img alt="A todo list app, but unstyled, with a title of `what needs to be done`, inputs, checkboxes, etc." src="03-unstyled-todo-app.png" style="border-style: solid; border-width: 1px;"></p>
+
+<p>The HTML markup above is not very nicely styled and it's also functionally useless. Nevertheless, let's have a look at the markup and see how it relates to our desired features:</p>
+
+<ul>
+ <li>A label and a text box for entering new tasks.</li>
+ <li>Three buttons to filter by task status.</li>
+ <li>A label showing the total number of tasks and the completed tasks.</li>
+ <li>An unordered list, which holds a list item for each task.</li>
+ <li>When the task is being edited, the list item has an input and two button to cancel or save modifications.</li>
+ <li>If the task is not being edited, there's a checkbox to set the completed status, and two buttons to edit or delete the task.</li>
+ <li>Finally there are two buttons to check/uncheck all task and to remove completed tasks.</li>
+</ul>
+
+<p>In subsequent articles we'll get all these features working, and more besides.</p>
+
+<h3 id="Accessibility_features_of_the_todo_list">Accessibility features of the todo list</h3>
+
+<p>You may notice some unusual attributes here. For example:</p>
+
+<pre class="brush: html">&lt;button class="btn toggle-btn" aria-pressed="true"&gt;
+ &lt;span class="visually-hidden"&gt;Show&lt;/span&gt;
+ &lt;span&gt;All&lt;/span&gt;
+ &lt;span class="visually-hidden"&gt;tasks&lt;/span&gt;
+&lt;/button&gt;</pre>
+
+<p>Here, <code>aria-pressed</code> tells assistive technology (like screen readers) that the button can be in one of two states: <code>pressed</code> or <code>unpressed</code>. Think of these as analogs for on and off. Setting a value of <code>true</code> means that the button is pressed by default.</p>
+
+<p>The class <code>visually-hidden</code> has no effect yet, because we have not included any CSS. Once we have put our styles in place, though, any element with this class will be hidden from sighted users and still available to screen reader users — this is because these words are not needed by sighted users; they are there to provide more information about what the button does for screenreader users that do not have the extra visual context to help them.</p>
+
+<p>Further down, you can find the following <code>&lt;ul&gt;</code> element:</p>
+
+<pre class="brush: html">&lt;ul role="list" className="todo-list stack-large" aria-labelledby="list-heading"&gt;</pre>
+
+<p>The <code>role</code> attribute helps assistive technology explain what kind of semantic value an element has — or what its purpose is. A <code>&lt;ul&gt;</code> is treated like a list by default, but the styles we're about to add will break that functionality. This role will restore the "list" meaning to the <code>&lt;ul&gt;</code>  element. If you want to learn more about why this is necessary, you can check out Scott O'Hara’s article, “Fixing Lists”.</p>
+
+<p>The <code>aria-labelledby</code> attribute tells assistive technologies that we're treating our <code>&lt;h2&gt;</code> with an <code>id</code> of <code>list-heading</code> as the label that describes the purpose of the list beneath it. Making this association gives the list a more informative context, which could help screen reader users better understand the purpose of it.</p>
+
+<p>This seems like a good time to talk about how Svelte deals with accessibility; let's do that now.</p>
+
+<h2 id="Svelte_accessibility_support">Svelte accessibility support</h2>
+
+<p>Svelte has a special emphasis on accessibility. The intention is to encourage developers to write more accessible code "by default". Being a compiler, Svelte can statically analyze our HTML templates to provide accessibility warnings when components are being compiled.</p>
+
+<p>Accessibility (shortened to a11y) isn't always easy to get right, but Svelte will help by warning you if you write inaccessible markup.</p>
+
+<p>For example, if we add an <code>&lt;img&gt;</code> element to our <code>todos.svelte</code> component without its corresponding <code>alt</code> prop:</p>
+
+<pre class="brush: html">&lt;h1&gt;Svelte To-Do list&lt;/h1&gt;
+
+&lt;img height="32" width="88" src="https://www.w3.org/WAI/wcag2A"&gt;
+</pre>
+
+<p>The compiler will issue the following warning:</p>
+
+<pre class="brush: bash">(!) Plugin svelte: A11y: &lt;img&gt; element should have an alt attribute
+src/components/Todos.svelte
+1: &lt;h1&gt;Svelte To-Do list&lt;/h1&gt;
+2:
+3: &lt;img height="32" width="88" src="https://www.w3.org/WAI/wcag2A"&gt;
+ ^
+created public/build/bundle.js in 220ms
+
+[2020-07-15 04:07:43] waiting for changes...</pre>
+
+<p>Moreover, our editor can display this warning even before calling the compiler:</p>
+
+<p><img alt="A code editor window showing an image tag, with a popup error message saying that the element should have an alt attribute" src="04-svelte-accessibility-support.png"></p>
+
+<p>You can tell Svelte to ignore this warning for the next block of markup with a <a href="https://svelte.dev/docs#Comments">comment</a> beginning with <code>svelte-ignore</code>, like this:</p>
+
+<pre class="brush: html">&lt;!-- svelte-ignore a11y-missing-attribute --&gt;
+&lt;img height="32" width="88" src="https://www.w3.org/WAI/wcag2A"&gt;
+</pre>
+
+<div class="notecard note">
+<p><strong>Note</strong>: With VSCode you can automatically add this ignore comment by clicking on the <em>Quick fix...</em> link or pressing <kbd>Ctrl</kbd> + <kbd>.</kbd>.</p>
+</div>
+
+<p>If you want to globally disable this warning you can add this <code>onwarn</code> handler to your <code>rollup.config.js</code> file inside the configuration for the <code>Svelte</code> plugin, like this:</p>
+
+<pre class="brush: js">plugins: [
+ svelte({
+ dev: !production,
+ css: css =&gt; {
+ css.write('public/build/bundle.css');
+ },
+ // Warnings are normally passed straight to Rollup. You can
+ // optionally handle them here, for example to squelch
+ // warnings with a particular code
+ onwarn: (warning, handler) =&gt; {
+ // e.g. I don't care about screen readers -&gt; please DON'T DO THIS!!!
+ if (warning.code === 'a11y-missing-attribute') return;
+
+ // let Rollup handle all other warnings normally
+ handler(warning);
+ }
+ }),
+
+ ...
+]
+</pre>
+
+<p>By design, these warnings are implemented in the compiler itself, and not as a plug-in that you may choose to add to your project. The idea is to check for a11y issues in your markup by default and let you opt-out of specific warnings.</p>
+
+<div class="notecard note">
+<p><strong>Note</strong>: you should only disable these warnings if you have good reasons to do so, for example while building a quick prototype. It's important to be a good web citizen and make your pages accessible to the broadest possible userbase.</p>
+</div>
+
+<p>The accessibility rules checked by Svelte are taken from <a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#supported-rules">eslint-plugin-jsx-a11y</a>, a plugin for eslint that provides static checks for many accessibility rules on JSX elements. Svelte aims to implement all of them in its compiler, and most of them have already been ported to Svelte. On GitHub you can see <a href="https://github.com/sveltejs/svelte/issues/820">which accessibility checks are still missing</a>. You can check the meaning of each rule by clicking on its link.</p>
+
+<h2 id="Styling_our_markup">Styling our markup</h2>
+
+<p>Let's make the todo list look a little better. Replace the contents of the file <code>public/global.css</code> with the following:</p>
+
+<pre class="brush: css">/* RESETS */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+*:focus {
+ outline: 3px dashed #228bec;
+ outline-offset: 0;
+}
+html {
+ font: 62.5% / 1.15 sans-serif;
+}
+h1,
+h2 {
+ margin-bottom: 0;
+}
+ul {
+ list-style: none;
+ padding: 0;
+}
+button {
+ border: none;
+ margin: 0;
+ padding: 0;
+ width: auto;
+ overflow: visible;
+ background: transparent;
+ color: inherit;
+ font: inherit;
+ line-height: normal;
+ -webkit-font-smoothing: inherit;
+ -moz-osx-font-smoothing: inherit;
+ -webkit-appearance: none;
+}
+button::-moz-focus-inner {
+ border: 0;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit;
+ font-size: 100%;
+ line-height: 1.15;
+ margin: 0;
+}
+button,
+input {
+ overflow: visible;
+}
+input[type="text"] {
+ border-radius: 0;
+}
+body {
+ width: 100%;
+ max-width: 68rem;
+ margin: 0 auto;
+ font: 1.6rem/1.25 Arial, sans-serif;
+ background-color: #f5f5f5;
+ color: #4d4d4d;
+}
+@media screen and (min-width: 620px) {
+ body {
+ font-size: 1.9rem;
+ line-height: 1.31579;
+ }
+}
+/*END RESETS*/
+
+/* GLOBAL STYLES */
+.form-group &gt; input[type="text"] {
+ display: inline-block;
+ margin-top: 0.4rem;
+}
+.btn {
+ padding: 0.8rem 1rem 0.7rem;
+ border: 0.2rem solid #4d4d4d;
+ cursor: pointer;
+ text-transform: capitalize;
+}
+.btn.toggle-btn {
+ border-width: 1px;
+ border-color: #d3d3d3;
+}
+.btn.toggle-btn[aria-pressed="true"] {
+ text-decoration: underline;
+ border-color: #4d4d4d;
+}
+.btn__danger {
+ color: #fff;
+ background-color: #ca3c3c;
+ border-color: #bd2130;
+}
+.btn__filter {
+ border-color: lightgrey;
+}
+.btn__primary {
+ color: #fff;
+ background-color: #000;
+}
+.btn__primary:disabled {
+ color: darkgrey;
+ background-color:#565656;
+}
+.btn-group {
+ display: flex;
+ justify-content: space-between;
+}
+.btn-group &gt; * {
+ flex: 1 1 49%;
+}
+.btn-group &gt; * + * {
+ margin-left: 0.8rem;
+}
+.label-wrapper {
+ margin: 0;
+ flex: 0 0 100%;
+ text-align: center;
+}
+.visually-hidden {
+ position: absolute !important;
+ height: 1px;
+ width: 1px;
+ overflow: hidden;
+ clip: rect(1px 1px 1px 1px);
+ clip: rect(1px, 1px, 1px, 1px);
+ white-space: nowrap;
+}
+[class*="stack"] &gt; * {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+.stack-small &gt; * + * {
+ margin-top: 1.25rem;
+}
+.stack-large &gt; * + * {
+ margin-top: 2.5rem;
+}
+@media screen and (min-width: 550px) {
+ .stack-small &gt; * + * {
+ margin-top: 1.4rem;
+ }
+ .stack-large &gt; * + * {
+ margin-top: 2.8rem;
+ }
+}
+.stack-exception {
+ margin-top: 1.2rem;
+}
+/* END GLOBAL STYLES */
+
+.todoapp {
+ background: #fff;
+ margin: 2rem 0 4rem 0;
+ padding: 1rem;
+ position: relative;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
+}
+@media screen and (min-width: 550px) {
+ .todoapp {
+ padding: 4rem;
+ }
+}
+.todoapp &gt; * {
+ max-width: 50rem;
+ margin-left: auto;
+ margin-right: auto;
+}
+.todoapp &gt; form {
+ max-width: 100%;
+}
+.todoapp &gt; h1 {
+ display: block;
+ max-width: 100%;
+ text-align: center;
+ margin: 0;
+ margin-bottom: 1rem;
+}
+.label__lg {
+ line-height: 1.01567;
+ font-weight: 300;
+ padding: 0.8rem;
+ margin-bottom: 1rem;
+ text-align: center;
+}
+.input__lg {
+ padding: 2rem;
+ border: 2px solid #000;
+}
+.input__lg:focus {
+ border-color: #4d4d4d;
+ box-shadow: inset 0 0 0 2px;
+}
+[class*="__lg"] {
+ display: inline-block;
+ width: 100%;
+ font-size: 1.9rem;
+}
+[class*="__lg"]:not(:last-child) {
+ margin-bottom: 1rem;
+}
+@media screen and (min-width: 620px) {
+ [class*="__lg"] {
+ font-size: 2.4rem;
+ }
+}
+.filters {
+ width: 100%;
+ margin: unset auto;
+}
+/* Todo item styles */
+.todo {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+}
+.todo &gt; * {
+ flex: 0 0 100%;
+}
+.todo-text {
+ width: 100%;
+ min-height: 4.4rem;
+ padding: 0.4rem 0.8rem;
+ border: 2px solid #565656;
+}
+.todo-text:focus {
+ box-shadow: inset 0 0 0 2px;
+}
+/* CHECKBOX STYLES */
+.c-cb {
+ box-sizing: border-box;
+ font-family: Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ font-weight: 400;
+ font-size: 1.6rem;
+ line-height: 1.25;
+ display: block;
+ position: relative;
+ min-height: 44px;
+ padding-left: 40px;
+ clear: left;
+}
+.c-cb &gt; label::before,
+.c-cb &gt; input[type="checkbox"] {
+ box-sizing: border-box;
+ top: -2px;
+ left: -2px;
+ width: 44px;
+ height: 44px;
+}
+.c-cb &gt; input[type="checkbox"] {
+ -webkit-font-smoothing: antialiased;
+ cursor: pointer;
+ position: absolute;
+ z-index: 1;
+ margin: 0;
+ opacity: 0;
+}
+.c-cb &gt; label {
+ font-size: inherit;
+ font-family: inherit;
+ line-height: inherit;
+ display: inline-block;
+ margin-bottom: 0;
+ padding: 8px 15px 5px;
+ cursor: pointer;
+ touch-action: manipulation;
+}
+.c-cb &gt; label::before {
+ content: "";
+ position: absolute;
+ border: 2px solid currentColor;
+ background: transparent;
+}
+.c-cb &gt; input[type="checkbox"]:focus + label::before {
+ border-width: 4px;
+ outline: 3px dashed #228bec;
+}
+.c-cb &gt; label::after {
+ box-sizing: content-box;
+ content: "";
+ position: absolute;
+ top: 11px;
+ left: 9px;
+ width: 18px;
+ height: 7px;
+ transform: rotate(-45deg);
+ border: solid;
+ border-width: 0 0 5px 5px;
+ border-top-color: transparent;
+ opacity: 0;
+ background: transparent;
+}
+.c-cb &gt; input[type="checkbox"]:checked + label::after {
+ opacity: 1;
+}</pre>
+
+<p>With our markup styled, everything now looks better:</p>
+
+<p><img alt="Our todo list app, styled, with a title of 'what needs to be done', an input to enter more todos, and a list of todos with checkboxes" src="05-styled-todo-app.png"></p>
+
+<h2 id="The_code_so_far">The code so far</h2>
+
+<h3 id="Git_2">Git</h3>
+
+<p>To see the state of the code as it should be at the end of this article, access your copy of our repo like this:</p>
+
+<pre class="brush: bash">cd mdn-svelte-tutorial/03-adding-dynamic-behavior</pre>
+
+<p>Or directly download the folder's content:</p>
+
+<pre class="brush: bash">npx degit opensas/mdn-svelte-tutorial/03-adding-dynamic-behavior</pre>
+
+<p>Remember to run <code>npm install &amp;&amp; npm run dev</code> to start your app in development mode.</p>
+
+<h3 id="REPL_2">REPL</h3>
+
+<p>To see the current state of the code in a REPL, visit:</p>
+
+<p><a href="https://svelte.dev/repl/c862d964d48d473ca63ab91709a0a5a0?version=3.23.2">https://svelte.dev/repl/c862d964d48d473ca63ab91709a0a5a0?version=3.23.2</a></p>
+
+<h2 id="Summary">Summary</h2>
+
+<p>With our markup and styling in place our Todo list app is starting to take shape, and we have everything ready so that we can start to focus on the features we have to implement.</p>
+
+<p>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</p>
+
+<h2 id="In_this_module">In this module</h2>
+
+<ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introduction to client-side frameworks</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Framework main features</a></li>
+ <li>React
+ <ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Getting started with React</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Beginning our React todo list</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componentizing our React app</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">React interactivity: Events and state</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">React interactivity: Editing, filtering, conditional rendering</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accessibility in React</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">React resources</a></li>
+ </ul>
+ </li>
+ <li>Ember
+ <ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Getting started with Ember</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Ember app structure and componentization</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Ember interactivity: Events, classes and state</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Ember Interactivity: Footer functionality, conditional rendering</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Routing in Ember</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Ember resources and troubleshooting</a></li>
+ </ul>
+ </li>
+ <li>Vue
+ <ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Getting started with Vue</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Creating our first Vue component</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Rendering a list of Vue components</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Adding a new todo form: Vue events, methods, and models</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Styling Vue components with CSS</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Using Vue computed properties</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Vue conditional rendering: editing existing todos</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Focus management with Vue refs</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Vue resources</a></li>
+ </ul>
+ </li>
+ <li>Svelte
+ <ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started">Getting started with Svelte</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning">Starting our Svelte Todo list app</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props">Dynamic behavior in Svelte: working with variables and props</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components">Componentizing our Svelte app</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_reactivity_lifecycle_accessibility">Advanced Svelte: Reactivity, lifecycle, accessibility</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores">Working with Svelte stores</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_TypeScript">TypeScript support in Svelte</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_deployment_next">Deployment and next steps</a></li>
+ </ul>
+ </li>
+ <li>Angular
+ <ul>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_getting_started">Getting started with Angular</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_todo_list_beginning">Beginning our Angular todo list app</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_styling">Styling our Angular app</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_item_component">Creating an item component</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_filtering">Filtering our to-do items</a></li>
+ <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_building">Building Angular applications and further resources</a></li>
+ </ul>
+ </li>
+</ul>