From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../accessibility_troubleshooting/index.html | 129 ++ .../accessibility/css_and_javascript/index.html | 373 ++++ files/ja/learn/accessibility/html/index.html | 564 ++++++ files/ja/learn/accessibility/index.html | 63 + files/ja/learn/accessibility/mobile/index.html | 316 +++ files/ja/learn/accessibility/multimedia/index.html | 371 ++++ .../learn/accessibility/wai-aria_basics/index.html | 434 +++++ .../accessibility/what_is_accessibility/index.html | 233 +++ .../available_text_editors/index.html | 296 +++ .../index.html | 172 ++ .../common_questions/common_web_layouts/index.html | 108 ++ .../design_for_all_types_of_users/index.html | 219 +++ .../how_does_the_internet_work/index.html | 99 + .../how_much_does_it_cost/index.html | 155 ++ .../html_features_for_accessibility/index.html | 55 + files/ja/learn/common_questions/index.html | 136 ++ .../index.html | 120 ++ .../set_up_a_local_testing_server/index.html | 110 ++ .../thinking_before_coding/index.html | 177 ++ .../upload_files_to_a_web_server/index.html | 177 ++ .../common_questions/using_github_pages/index.html | 108 ++ .../what_are_browser_developer_tools/index.html | 182 ++ .../what_are_hyperlinks/index.html | 95 + .../what_is_a_domain_name/index.html | 160 ++ .../common_questions/what_is_a_url/index.html | 159 ++ .../what_is_a_web_server/index.html | 119 ++ .../what_is_accessibility/index.html | 90 + .../what_software_do_i_need/index.html | 222 +++ .../advanced_styling_effects/index.html | 426 +++++ .../backgrounds_and_borders/index.html | 338 ++++ .../cascade_and_inheritance/index.html | 339 ++++ .../css/building_blocks/debugging_css/index.html | 206 ++ .../handling_different_text_directions/index.html | 153 ++ .../images_media_form_elements/index.html | 201 ++ files/ja/learn/css/building_blocks/index.html | 88 + .../css/building_blocks/organizing/index.html | 375 ++++ .../building_blocks/overflowing_content/index.html | 132 ++ .../selectors/attribute_selectors/index.html | 180 ++ .../selectors/combinators/index.html | 118 ++ .../learn/css/building_blocks/selectors/index.html | 233 +++ .../pseudo-classes_and_pseudo-elements/index.html | 397 ++++ .../type_class_and_id_selectors/index.html | 126 ++ .../building_blocks/sizing_items_in_css/index.html | 139 ++ .../css/building_blocks/styling_tables/index.html | 316 +++ .../css/building_blocks/the_box_model/index.html | 343 ++++ .../building_blocks/values_and_units/index.html | 407 ++++ files/ja/learn/css/css_layout/flexbox/index.html | 349 ++++ files/ja/learn/css/css_layout/floats/index.html | 528 +++++ .../fundamental_layout_comprehension/index.html | 91 + files/ja/learn/css/css_layout/grids/index.html | 722 +++++++ files/ja/learn/css/css_layout/index.html | 80 + .../learn/css/css_layout/introduction/index.html | 720 +++++++ .../css_layout/legacy_layout_methods/index.html | 588 ++++++ .../learn/css/css_layout/media_queries/index.html | 445 +++++ .../css_layout/multiple-column_layout/index.html | 417 ++++ .../ja/learn/css/css_layout/normal_flow/index.html | 103 + .../ja/learn/css/css_layout/positioning/index.html | 588 ++++++ .../practical_positioning_examples/index.html | 421 ++++ .../css/css_layout/responsive_design/index.html | 334 ++++ .../supporting_older_browsers/index.html | 248 +++ .../css/first_steps/getting_started/index.html | 263 +++ .../first_steps/how_css_is_structured/index.html | 530 +++++ .../learn/css/first_steps/how_css_works/index.html | 164 ++ files/ja/learn/css/first_steps/index.html | 53 + .../using_your_new_knowledge/index.html | 100 + .../learn/css/first_steps/what_is_css/index.html | 129 ++ .../learn/css/howto/create_fancy_boxes/index.html | 305 +++ .../learn/css/howto/generated_content/index.html | 88 + files/ja/learn/css/howto/index.html | 90 + files/ja/learn/css/index.html | 68 + .../fundamental_css_comprehension/index.html | 133 ++ .../styling_boxes/a_cool_looking_box/index.html | 100 + .../creating_fancy_letterheaded_paper/index.html | 108 ++ .../learn/css/styling_text/fundamentals/index.html | 748 ++++++++ files/ja/learn/css/styling_text/index.html | 55 + .../css/styling_text/styling_links/index.html | 453 +++++ .../css/styling_text/styling_lists/index.html | 398 ++++ .../styling_text/typesetting_a_homepage/index.html | 126 ++ .../index.html" | 219 +++ .../advanced_styling_for_html_forms/index.html | 556 ++++++ files/ja/learn/forms/form_validation/index.html | 840 ++++++++ .../example_1/index.html | 415 ++++ .../example_2/index.html | 212 ++ .../example_3/index.html | 246 +++ .../example_4/index.html | 296 +++ .../example_5/index.html | 289 +++ .../how_to_build_custom_form_widgets/index.html | 901 +++++++++ .../example/index.html | 164 ++ .../forms/how_to_structure_an_html_form/index.html | 329 ++++ files/ja/learn/forms/html5_input_types/index.html | 289 +++ .../forms/html_forms_in_legacy_browsers/index.html | 219 +++ files/ja/learn/forms/index.html | 96 + .../ja/learn/forms/other_form_controls/index.html | 333 ++++ .../index.html | 2017 ++++++++++++++++++++ .../sending_and_retrieving_form_data/index.html | 341 ++++ .../sending_forms_through_javascript/index.html | 396 ++++ files/ja/learn/forms/styling_html_forms/index.html | 398 ++++ .../learn/forms/the_native_form_widgets/index.html | 339 ++++ files/ja/learn/forms/ui_pseudo-classes/index.html | 616 ++++++ .../learn/forms/your_first_form/example/index.html | 113 ++ files/ja/learn/forms/your_first_form/index.html | 313 +++ files/ja/learn/front-end_web_developer/index.html | 193 ++ .../css_basics/index.html | 295 +++ .../dealing_with_files/index.html | 117 ++ .../how_the_web_works/index.html | 110 ++ .../html_basics/index.html | 239 +++ .../learn/getting_started_with_the_web/index.html | 65 + .../installing_basic_software/index.html | 80 + .../javascript_basics/index.html | 437 +++++ .../what_will_your_website_look_like/index.html | 110 ++ .../index.html" | 133 ++ files/ja/learn/how_to_contribute/index.html | 86 + .../add_a_hit_map_on_top_of_an_image/index.html | 126 ++ .../html/howto/define_terms_with_html/index.html | 151 ++ files/ja/learn/html/howto/index.html | 141 ++ .../html/howto/use_data_attributes/index.html | 82 + .../use_javascript_within_a_webpage/index.html | 107 ++ files/ja/learn/html/index.html | 61 + .../advanced_text_formatting/index.html | 674 +++++++ .../creating_hyperlinks/index.html | 338 ++++ .../introduction_to_html/debugging_html/index.html | 185 ++ .../document_and_website_structure/index.html | 293 +++ .../getting_started/index.html | 786 ++++++++ .../html_text_fundamentals/index.html | 717 +++++++ .../ja/learn/html/introduction_to_html/index.html | 65 + .../marking_up_a_letter/index.html | 105 + .../structuring_a_page_of_content/index.html | 107 ++ .../the_head_metadata_in_html/index.html | 292 +++ .../adding_vector_graphics_to_the_web/index.html | 370 ++++ .../images_in_html/index.html | 521 +++++ .../learn/html/multimedia_and_embedding/index.html | 78 + .../mozilla_splash_page/index.html | 129 ++ .../other_embedding_technologies/index.html | 399 ++++ .../responsive_images/index.html | 282 +++ .../video_and_audio_content/index.html | 307 +++ files/ja/learn/html/tables/advanced/index.html | 475 +++++ files/ja/learn/html/tables/basics/index.html | 569 ++++++ files/ja/learn/html/tables/index.html | 43 + .../html/tables/structuring_planet_data/index.html | 87 + files/ja/learn/index.html | 131 ++ files/ja/learn/index/index.html | 10 + .../javascript/asynchronous/concepts/index.html | 162 ++ files/ja/learn/javascript/asynchronous/index.html | 51 + .../build_your_own_function/index.html | 262 +++ .../building_blocks/conditionals/index.html | 782 ++++++++ .../javascript/building_blocks/events/index.html | 597 ++++++ .../building_blocks/functions/index.html | 407 ++++ .../building_blocks/image_gallery/index.html | 142 ++ .../ja/learn/javascript/building_blocks/index.html | 56 + .../building_blocks/looping_code/index.html | 933 +++++++++ .../building_blocks/return_values/index.html | 201 ++ .../client-side_storage/index.html | 796 ++++++++ .../drawing_graphics/index.html | 879 +++++++++ .../client-side_web_apis/fetching_data/index.html | 389 ++++ .../javascript/client-side_web_apis/index.html | 51 + .../client-side_web_apis/introduction/index.html | 317 +++ .../manipulating_documents/index.html | 349 ++++ .../third_party_apis/index.html | 442 +++++ .../video_and_audio_apis/index.html | 507 +++++ .../first_steps/a_first_splash/index.html | 610 ++++++ .../learn/javascript/first_steps/arrays/index.html | 568 ++++++ files/ja/learn/javascript/first_steps/index.html | 84 + .../learn/javascript/first_steps/math/index.html | 469 +++++ .../first_steps/silly_story_generator/index.html | 151 ++ .../javascript/first_steps/strings/index.html | 240 +++ .../first_steps/useful_string_methods/index.html | 680 +++++++ .../javascript/first_steps/variables/index.html | 342 ++++ .../first_steps/what_is_javascript/index.html | 434 +++++ .../first_steps/what_went_wrong/index.html | 265 +++ files/ja/learn/javascript/howto/index.html | 302 +++ files/ja/learn/javascript/index.html | 93 + .../adding_bouncing_balls_features/index.html | 223 +++ .../ja/learn/javascript/objects/basics/index.html | 277 +++ files/ja/learn/javascript/objects/index.html | 53 + .../javascript/objects/inheritance/index.html | 412 ++++ files/ja/learn/javascript/objects/json/index.html | 357 ++++ .../objects/object-oriented_js/index.html | 291 +++ .../objects/object_building_practice/index.html | 314 +++ .../objects/object_prototypes/index.html | 314 +++ .../index.html | 101 + .../business_case_for_performance/index.html | 83 + files/ja/learn/performance/index.html | 120 ++ .../performance/measuring_performance/index.html | 105 + .../performance/perceived_performance/index.html | 111 ++ .../performance/web_performance_basics/index.html | 89 + .../performance/what_is_web_performance/index.html | 90 + .../performance/why_web_performance/index.html | 101 + files/ja/learn/release_notes/index.html | 69 + .../django/development_environment/index.html | 433 +++++ files/ja/learn/server-side/django/index.html | 69 + .../server-side/django/introduction/index.html | 281 +++ .../ja/learn/server-side/django/models/index.html | 461 +++++ .../server-side/django/skeleton_website/index.html | 398 ++++ .../tutorial_local_library_website/index.html | 99 + .../django/web_application_security/index.html | 180 ++ .../express_nodejs/deployment/index.html | 525 +++++ .../development_environment/index.html | 410 ++++ .../displaying_data/author_detail_page/index.html | 89 + .../displaying_data/author_list_page/index.html | 85 + .../displaying_data/book_detail_page/index.html | 112 ++ .../displaying_data/book_list_page/index.html | 68 + .../index.html | 91 + .../bookinstance_list_page/index.html | 69 + .../date_formatting_using_moment/index.html | 60 + .../flow_control_using_async/index.html | 137 ++ .../displaying_data/genre_detail_page/index.html | 121 ++ .../displaying_data/home_page/index.html | 133 ++ .../express_nodejs/displaying_data/index.html | 92 + .../locallibrary_base_template/index.html | 69 + .../displaying_data/template_primer/index.html | 149 ++ .../server-side/express_nodejs/forms/index.html | 263 +++ .../ja/learn/server-side/express_nodejs/index.html | 79 + .../installing_on_pws_cloud_foundry/index.html | 242 +++ .../express_nodejs/introduction/index.html | 528 +++++ .../server-side/express_nodejs/mongoose/index.html | 799 ++++++++ .../server-side/express_nodejs/routes/index.html | 640 +++++++ .../express_nodejs/skeleton_website/index.html | 512 +++++ .../tutorial_local_library_website/index.html | 98 + .../first_steps/client-server_overview/index.html | 329 ++++ files/ja/learn/server-side/first_steps/index.html | 47 + .../first_steps/introduction/index.html | 227 +++ .../first_steps/web_frameworks/index.html | 328 ++++ .../first_steps/website_security/index.html | 181 ++ files/ja/learn/server-side/index.html | 59 + .../node_server_without_framework/index.html | 163 ++ .../client-side_javascript_frameworks/index.html | 138 ++ .../react_components/index.html | 450 +++++ .../react_getting_started/index.html | 468 +++++ .../react_todo_list_beginning/index.html | 599 ++++++ .../vue_getting_started/index.html | 301 +++ .../cross_browser_testing/accessibility/index.html | 624 ++++++ .../automated_testing/index.html | 620 ++++++ .../feature_detection/index.html | 357 ++++ .../cross_browser_testing/html_and_css/index.html | 508 +++++ .../cross_browser_testing/index.html | 47 + .../cross_browser_testing/introduction/index.html | 209 ++ .../cross_browser_testing/javascript/index.html | 521 +++++ .../testing_strategies/index.html | 372 ++++ .../your_own_automation_environment/index.html | 688 +++++++ files/ja/learn/tools_and_testing/index.html | 49 + 240 files changed, 68185 insertions(+) create mode 100644 files/ja/learn/accessibility/accessibility_troubleshooting/index.html create mode 100644 files/ja/learn/accessibility/css_and_javascript/index.html create mode 100644 files/ja/learn/accessibility/html/index.html create mode 100644 files/ja/learn/accessibility/index.html create mode 100644 files/ja/learn/accessibility/mobile/index.html create mode 100644 files/ja/learn/accessibility/multimedia/index.html create mode 100644 files/ja/learn/accessibility/wai-aria_basics/index.html create mode 100644 files/ja/learn/accessibility/what_is_accessibility/index.html create mode 100644 files/ja/learn/common_questions/available_text_editors/index.html create mode 100644 files/ja/learn/common_questions/checking_that_your_web_site_is_working_properly/index.html create mode 100644 files/ja/learn/common_questions/common_web_layouts/index.html create mode 100644 files/ja/learn/common_questions/design_for_all_types_of_users/index.html create mode 100644 files/ja/learn/common_questions/how_does_the_internet_work/index.html create mode 100644 files/ja/learn/common_questions/how_much_does_it_cost/index.html create mode 100644 files/ja/learn/common_questions/html_features_for_accessibility/index.html create mode 100644 files/ja/learn/common_questions/index.html create mode 100644 files/ja/learn/common_questions/pages_sites_servers_and_search_engines/index.html create mode 100644 files/ja/learn/common_questions/set_up_a_local_testing_server/index.html create mode 100644 files/ja/learn/common_questions/thinking_before_coding/index.html create mode 100644 files/ja/learn/common_questions/upload_files_to_a_web_server/index.html create mode 100644 files/ja/learn/common_questions/using_github_pages/index.html create mode 100644 files/ja/learn/common_questions/what_are_browser_developer_tools/index.html create mode 100644 files/ja/learn/common_questions/what_are_hyperlinks/index.html create mode 100644 files/ja/learn/common_questions/what_is_a_domain_name/index.html create mode 100644 files/ja/learn/common_questions/what_is_a_url/index.html create mode 100644 files/ja/learn/common_questions/what_is_a_web_server/index.html create mode 100644 files/ja/learn/common_questions/what_is_accessibility/index.html create mode 100644 files/ja/learn/common_questions/what_software_do_i_need/index.html create mode 100644 files/ja/learn/css/building_blocks/advanced_styling_effects/index.html create mode 100644 files/ja/learn/css/building_blocks/backgrounds_and_borders/index.html create mode 100644 files/ja/learn/css/building_blocks/cascade_and_inheritance/index.html create mode 100644 files/ja/learn/css/building_blocks/debugging_css/index.html create mode 100644 files/ja/learn/css/building_blocks/handling_different_text_directions/index.html create mode 100644 files/ja/learn/css/building_blocks/images_media_form_elements/index.html create mode 100644 files/ja/learn/css/building_blocks/index.html create mode 100644 files/ja/learn/css/building_blocks/organizing/index.html create mode 100644 files/ja/learn/css/building_blocks/overflowing_content/index.html create mode 100644 files/ja/learn/css/building_blocks/selectors/attribute_selectors/index.html create mode 100644 files/ja/learn/css/building_blocks/selectors/combinators/index.html create mode 100644 files/ja/learn/css/building_blocks/selectors/index.html create mode 100644 files/ja/learn/css/building_blocks/selectors/pseudo-classes_and_pseudo-elements/index.html create mode 100644 files/ja/learn/css/building_blocks/selectors/type_class_and_id_selectors/index.html create mode 100644 files/ja/learn/css/building_blocks/sizing_items_in_css/index.html create mode 100644 files/ja/learn/css/building_blocks/styling_tables/index.html create mode 100644 files/ja/learn/css/building_blocks/the_box_model/index.html create mode 100644 files/ja/learn/css/building_blocks/values_and_units/index.html create mode 100644 files/ja/learn/css/css_layout/flexbox/index.html create mode 100644 files/ja/learn/css/css_layout/floats/index.html create mode 100644 files/ja/learn/css/css_layout/fundamental_layout_comprehension/index.html create mode 100644 files/ja/learn/css/css_layout/grids/index.html create mode 100644 files/ja/learn/css/css_layout/index.html create mode 100644 files/ja/learn/css/css_layout/introduction/index.html create mode 100644 files/ja/learn/css/css_layout/legacy_layout_methods/index.html create mode 100644 files/ja/learn/css/css_layout/media_queries/index.html create mode 100644 files/ja/learn/css/css_layout/multiple-column_layout/index.html create mode 100644 files/ja/learn/css/css_layout/normal_flow/index.html create mode 100644 files/ja/learn/css/css_layout/positioning/index.html create mode 100644 files/ja/learn/css/css_layout/practical_positioning_examples/index.html create mode 100644 files/ja/learn/css/css_layout/responsive_design/index.html create mode 100644 files/ja/learn/css/css_layout/supporting_older_browsers/index.html create mode 100644 files/ja/learn/css/first_steps/getting_started/index.html create mode 100644 files/ja/learn/css/first_steps/how_css_is_structured/index.html create mode 100644 files/ja/learn/css/first_steps/how_css_works/index.html create mode 100644 files/ja/learn/css/first_steps/index.html create mode 100644 files/ja/learn/css/first_steps/using_your_new_knowledge/index.html create mode 100644 files/ja/learn/css/first_steps/what_is_css/index.html create mode 100644 files/ja/learn/css/howto/create_fancy_boxes/index.html create mode 100644 files/ja/learn/css/howto/generated_content/index.html create mode 100644 files/ja/learn/css/howto/index.html create mode 100644 files/ja/learn/css/index.html create mode 100644 files/ja/learn/css/introduction_to_css/fundamental_css_comprehension/index.html create mode 100644 files/ja/learn/css/styling_boxes/a_cool_looking_box/index.html create mode 100644 files/ja/learn/css/styling_boxes/creating_fancy_letterheaded_paper/index.html create mode 100644 files/ja/learn/css/styling_text/fundamentals/index.html create mode 100644 files/ja/learn/css/styling_text/index.html create mode 100644 files/ja/learn/css/styling_text/styling_links/index.html create mode 100644 files/ja/learn/css/styling_text/styling_lists/index.html create mode 100644 files/ja/learn/css/styling_text/typesetting_a_homepage/index.html create mode 100644 "files/ja/learn/css/styling_text/\343\202\246\343\202\247\343\203\226\343\203\225\343\202\251\343\203\263\343\203\210/index.html" create mode 100644 files/ja/learn/forms/advanced_styling_for_html_forms/index.html create mode 100644 files/ja/learn/forms/form_validation/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/example_1/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/example_2/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/example_3/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/example_4/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/example_5/index.html create mode 100644 files/ja/learn/forms/how_to_build_custom_form_widgets/index.html create mode 100644 files/ja/learn/forms/how_to_structure_an_html_form/example/index.html create mode 100644 files/ja/learn/forms/how_to_structure_an_html_form/index.html create mode 100644 files/ja/learn/forms/html5_input_types/index.html create mode 100644 files/ja/learn/forms/html_forms_in_legacy_browsers/index.html create mode 100644 files/ja/learn/forms/index.html create mode 100644 files/ja/learn/forms/other_form_controls/index.html create mode 100644 files/ja/learn/forms/property_compatibility_table_for_form_controls/index.html create mode 100644 files/ja/learn/forms/sending_and_retrieving_form_data/index.html create mode 100644 files/ja/learn/forms/sending_forms_through_javascript/index.html create mode 100644 files/ja/learn/forms/styling_html_forms/index.html create mode 100644 files/ja/learn/forms/the_native_form_widgets/index.html create mode 100644 files/ja/learn/forms/ui_pseudo-classes/index.html create mode 100644 files/ja/learn/forms/your_first_form/example/index.html create mode 100644 files/ja/learn/forms/your_first_form/index.html create mode 100644 files/ja/learn/front-end_web_developer/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/css_basics/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/dealing_with_files/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/how_the_web_works/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/html_basics/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/installing_basic_software/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/javascript_basics/index.html create mode 100644 files/ja/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html create mode 100644 "files/ja/learn/getting_started_with_the_web/\343\202\246\343\202\247\343\203\226\343\202\265\343\202\244\343\203\210\343\202\222\345\205\254\351\226\213\343\201\231\343\202\213/index.html" create mode 100644 files/ja/learn/how_to_contribute/index.html create mode 100644 files/ja/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html create mode 100644 files/ja/learn/html/howto/define_terms_with_html/index.html create mode 100644 files/ja/learn/html/howto/index.html create mode 100644 files/ja/learn/html/howto/use_data_attributes/index.html create mode 100644 files/ja/learn/html/howto/use_javascript_within_a_webpage/index.html create mode 100644 files/ja/learn/html/index.html create mode 100644 files/ja/learn/html/introduction_to_html/advanced_text_formatting/index.html create mode 100644 files/ja/learn/html/introduction_to_html/creating_hyperlinks/index.html create mode 100644 files/ja/learn/html/introduction_to_html/debugging_html/index.html create mode 100644 files/ja/learn/html/introduction_to_html/document_and_website_structure/index.html create mode 100644 files/ja/learn/html/introduction_to_html/getting_started/index.html create mode 100644 files/ja/learn/html/introduction_to_html/html_text_fundamentals/index.html create mode 100644 files/ja/learn/html/introduction_to_html/index.html create mode 100644 files/ja/learn/html/introduction_to_html/marking_up_a_letter/index.html create mode 100644 files/ja/learn/html/introduction_to_html/structuring_a_page_of_content/index.html create mode 100644 files/ja/learn/html/introduction_to_html/the_head_metadata_in_html/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/images_in_html/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/responsive_images/index.html create mode 100644 files/ja/learn/html/multimedia_and_embedding/video_and_audio_content/index.html create mode 100644 files/ja/learn/html/tables/advanced/index.html create mode 100644 files/ja/learn/html/tables/basics/index.html create mode 100644 files/ja/learn/html/tables/index.html create mode 100644 files/ja/learn/html/tables/structuring_planet_data/index.html create mode 100644 files/ja/learn/index.html create mode 100644 files/ja/learn/index/index.html create mode 100644 files/ja/learn/javascript/asynchronous/concepts/index.html create mode 100644 files/ja/learn/javascript/asynchronous/index.html create mode 100644 files/ja/learn/javascript/building_blocks/build_your_own_function/index.html create mode 100644 files/ja/learn/javascript/building_blocks/conditionals/index.html create mode 100644 files/ja/learn/javascript/building_blocks/events/index.html create mode 100644 files/ja/learn/javascript/building_blocks/functions/index.html create mode 100644 files/ja/learn/javascript/building_blocks/image_gallery/index.html create mode 100644 files/ja/learn/javascript/building_blocks/index.html create mode 100644 files/ja/learn/javascript/building_blocks/looping_code/index.html create mode 100644 files/ja/learn/javascript/building_blocks/return_values/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/client-side_storage/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/drawing_graphics/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/fetching_data/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/introduction/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/manipulating_documents/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/third_party_apis/index.html create mode 100644 files/ja/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html create mode 100644 files/ja/learn/javascript/first_steps/a_first_splash/index.html create mode 100644 files/ja/learn/javascript/first_steps/arrays/index.html create mode 100644 files/ja/learn/javascript/first_steps/index.html create mode 100644 files/ja/learn/javascript/first_steps/math/index.html create mode 100644 files/ja/learn/javascript/first_steps/silly_story_generator/index.html create mode 100644 files/ja/learn/javascript/first_steps/strings/index.html create mode 100644 files/ja/learn/javascript/first_steps/useful_string_methods/index.html create mode 100644 files/ja/learn/javascript/first_steps/variables/index.html create mode 100644 files/ja/learn/javascript/first_steps/what_is_javascript/index.html create mode 100644 files/ja/learn/javascript/first_steps/what_went_wrong/index.html create mode 100644 files/ja/learn/javascript/howto/index.html create mode 100644 files/ja/learn/javascript/index.html create mode 100644 files/ja/learn/javascript/objects/adding_bouncing_balls_features/index.html create mode 100644 files/ja/learn/javascript/objects/basics/index.html create mode 100644 files/ja/learn/javascript/objects/index.html create mode 100644 files/ja/learn/javascript/objects/inheritance/index.html create mode 100644 files/ja/learn/javascript/objects/json/index.html create mode 100644 files/ja/learn/javascript/objects/object-oriented_js/index.html create mode 100644 files/ja/learn/javascript/objects/object_building_practice/index.html create mode 100644 files/ja/learn/javascript/objects/object_prototypes/index.html create mode 100644 files/ja/learn/javascript/objects/test_your_skills_colon__object_basics/index.html create mode 100644 files/ja/learn/performance/business_case_for_performance/index.html create mode 100644 files/ja/learn/performance/index.html create mode 100644 files/ja/learn/performance/measuring_performance/index.html create mode 100644 files/ja/learn/performance/perceived_performance/index.html create mode 100644 files/ja/learn/performance/web_performance_basics/index.html create mode 100644 files/ja/learn/performance/what_is_web_performance/index.html create mode 100644 files/ja/learn/performance/why_web_performance/index.html create mode 100644 files/ja/learn/release_notes/index.html create mode 100644 files/ja/learn/server-side/django/development_environment/index.html create mode 100644 files/ja/learn/server-side/django/index.html create mode 100644 files/ja/learn/server-side/django/introduction/index.html create mode 100644 files/ja/learn/server-side/django/models/index.html create mode 100644 files/ja/learn/server-side/django/skeleton_website/index.html create mode 100644 files/ja/learn/server-side/django/tutorial_local_library_website/index.html create mode 100644 files/ja/learn/server-side/django/web_application_security/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/deployment/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/development_environment/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/home_page/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/displaying_data/template_primer/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/forms/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/installing_on_pws_cloud_foundry/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/introduction/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/mongoose/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/routes/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/skeleton_website/index.html create mode 100644 files/ja/learn/server-side/express_nodejs/tutorial_local_library_website/index.html create mode 100644 files/ja/learn/server-side/first_steps/client-server_overview/index.html create mode 100644 files/ja/learn/server-side/first_steps/index.html create mode 100644 files/ja/learn/server-side/first_steps/introduction/index.html create mode 100644 files/ja/learn/server-side/first_steps/web_frameworks/index.html create mode 100644 files/ja/learn/server-side/first_steps/website_security/index.html create mode 100644 files/ja/learn/server-side/index.html create mode 100644 files/ja/learn/server-side/node_server_without_framework/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html create mode 100644 files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html create mode 100644 files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html create mode 100644 files/ja/learn/tools_and_testing/index.html (limited to 'files/ja/learn') diff --git a/files/ja/learn/accessibility/accessibility_troubleshooting/index.html b/files/ja/learn/accessibility/accessibility_troubleshooting/index.html new file mode 100644 index 0000000000..a43b4a509b --- /dev/null +++ b/files/ja/learn/accessibility/accessibility_troubleshooting/index.html @@ -0,0 +1,129 @@ +--- +title: '評価: アクセシビリティのトラブルシューティング' +slug: Learn/Accessibility/Accessibility_troubleshooting +tags: + - Accessibility + - Assesment + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Learn + - WAI-ARIA +translation_of: Learn/Accessibility/Accessibility_troubleshooting +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}
+ +

このモジュールの評価では、あなたが診断、修正するべきいくつかのアクセシビリティの問題を持った簡単なサイトを表示します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、HTML、CSS、JavaScript に対する基本的な理解、このコースのこれまでの記事への理解。
学習目標:アクセシビリティの基礎に対する基本的な知識をテストすること。
+ +

開始地点

+ +

評価を始めるために、例を含むファイルの ZIP を取得してください。あなたのコンピューターのいずれかのディレクトリーにそのコンテンツを解凍してください。

+ +

あるいは、JSBinGlitch のようなサイトを使って試験できます。HTML, CSS, JavaScript をオンラインエディターのいずれかにペーストします。もし使っているオンラインエディターに個別の CSS/JS パネルがない場合、適当な <style> / <script> 要素内に置いて下さい。

+ +

解凍が完了した評価サイトは次のように見えるはずです:

+ +

+ +

この評価の開始時点であなたがサイトを表示したとき、いくつかの違いや問題を見つけることでしょう。これは主にマークアップ中の違いが原因であり、CSS が正しく適用されずにスタイリングの問題を引き起こしています。心配しないでください。以降の節でそれらの問題を修正します!

+ +
+

: もし行き詰まって助けを求める場合 — ページ最下部の {{anch("Assessment or further help")}} セクションを見てください。

+
+ +

プロジェクトの概要

+ +

このプロジェクトでは、熊の「事実」に関する記事を表示する架空の自然のサイトが表示されます。現状では、これはいくつものアクセシビリティの問題を持っています。あなたの仕事は現状のサイトを見て、全力を尽くして修正し、以下の質問に答えることです。 

+ +

+ +

テキストは現在のカラースキームのせいで読みづらくなっています。現状のカラーコントラスト (テキスト/背景) をテストして、テストの結果を報告し、割り当てられた色を変更して修正できますか?

+ +

セマンティック HTML

+ +
    +
  1. コンテンツはまだあまりアクセシブルではありません。スクリーンリーダーを使ってナビゲートしようとしたとき、何が起こるか報告してください。
  2. +
  3. スクリーンリーダーのユーザーがナビゲートしやすいように、記事のテキストを変更できますか?
  4. +
  5. サイトのナビゲーションメニュー ( <div class="nav"></div> で囲まれた部分) は正しい HTML5 セマンティック要素の中に入れることでよりアクセシブルになったかもしれません。どれを変更する必要がありますか?変更してください。
  6. +
+ +
+

: タグをスタイル付けする CSS ルールセレクターは、セマンティック見出しのために適切に変更する必要があります。パラグラフ要素を加えると、スタイルもより良く見えることに気がつくでしょう。

+
+ +

画像

+ +

現状の画像はスクリーンリーダーのユーザーにとってアクセシブルではありません。修正できますか?

+ +

オーディオプレイヤー

+ +
    +
  1. <audio> プレイヤーは聴覚障害者にとってアクセシブルではありません。それらのユーザーのために何らかのアクセシブルな代替手段を加えることができますか?
  2. +
  3. <audio> プレイヤーは、HTML5 をサポートしていない古いブラウザーを使用しているユーザーにとってアクセシブルではありません。彼らに対してどのようにオーディオにアクセスさせることができますか?
  4. +
+ +

フォーム

+ +
    +
  1. トップにある検索フォームの <input> 要素はラベルとともに使用できるかもしれませんが、表示されるテキストを追加するとデザインを悪化させる可能性がありますし、視覚に問題のないユーザーにとってはあまり必要ありません。スクリーンリーダーにのみアクセシブルなラベルをどうやって追加すればいいでしょう?
  2. +
  3. コメントフォームの中の 2 つの <input> 要素は表示されるテキストラベルを含んでいますが、それらのラベルと明確に関連付けられていません。どのように関連付けますか?いくつかの CSS ルールも修正しなければいけない点に注意してください。
  4. +
+ +

コメント show/hide 制御

+ +

現状のコメント show/hide 制御ボタンは、キーボードからアクセスすることができません。タブキーによるフォーカス、リターンキーによる有効化という形で、キーボードをアクセシブルにすることができますか?

+ +

テーブル

+ +

現状のデータテーブルはあまりアクセシブルではありません。スクリーンリーダーのユーザーにとって行と列を関連付けることは難しく、またテーブルが何を示しているのかを明確にする概要もありません。この問題を解決するために何らかの機能を HTML に追加することはできますか?

+ +

他には?

+ +

このウェブサイトをよりアクセシブルにする 2 つ以上の改善アイデアを挙げることができますか?

+ +

評価とヒント

+ +

あなたの作業を教師やメンターに渡して採点してもらったり、行き詰まってヒントが欲しい場合は次のようにしてください:

+ +
    +
  1. 成果をオンラインで共有できるエディター、例えば CodePen, jsFiddle, Glitch に置きます。
  2. +
  3. 採点や手助けのための投稿を MDN Discourse forum Learning category に書いてください。投稿には次のものを(英語で)入れて下さい: +
      +
    • "Assessment wanted for Accessibility troubleshooting"のような説明的なタイトル。
    • +
    • 何を試して、どうしてほしいのかの詳細。つまり行き詰まって助けてほしいのか、採点評価してほしいのか。
    • +
    • オンラインで共有できるエディター (上記ステップ 1 で触れたもの)での例のリンク。これは身につけるとよい習慣です — コーティングの問題を、他の人がコードを見ずに助けるのは困難です。
    • +
    • 助けてもらいたい問題が見つかるような、タスクや評価のページのリンク
    • +
    +
  4. +
+ +

{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/accessibility/css_and_javascript/index.html b/files/ja/learn/accessibility/css_and_javascript/index.html new file mode 100644 index 0000000000..76ea71cce1 --- /dev/null +++ b/files/ja/learn/accessibility/css_and_javascript/index.html @@ -0,0 +1,373 @@ +--- +title: CSS と JavaScript のアクセシビリティの ベスト・プラクティス +slug: Learn/Accessibility/CSS_and_JavaScript +tags: + - Accessibility + - Article + - CSS + - CodingScripting + - Guide + - JavaScript + - Learn + - color + - contrast + - hiding + - unobtrusive + - ひかえめ + - アクセシビリティ + - ガイド + - コントラスト + - 学習 + - 色 + - 隠す +translation_of: Learn/Accessibility/CSS_and_JavaScript +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}
+ +

CSS と JavaScript も、適切に使えばアクセシブルなウェブ体験を可能にしてくれる可能性がありますが、誤用すると、大幅にアクセシビリティを悪化させることがあります。本記事では、複雑なコンテンツでもできる限りアクセシブルにすることを保証するために考慮すべき、CSS と JavaScript のベスト・プラクティスのいくつかを概観します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、HTML と CSS と JavaScript に関する基本的な理解、アクセシビリティとは何かに関する理解。
学習目標:アクセシビリティを損わず、最大化するように、自身のウェブドキュメントで CSS と JavaScript を適切に使うことに慣れること。
+ +

CSS と JavaScript はアクセシブルなの?

+ +

CSS と JavaScript は、アクセシビリティに関して HTML と同じだけの直接的重要性があるわけではありません。ですが、それでも使い方によっては、アクセシビリティを高めることも損うこともありえます。別の言葉で言うと、自分の CSS と JavaScript の使い方によってドキュメントのアクセシビリティを台無しにしていないと確認するために、いくつかのベスト・プラクティスを考慮することが重要です。

+ +

CSS

+ +

CSS を見ることから始めましょう。

+ +

正しいセマンティクスと、ユーザの予期すること

+ +

CSS を使って、どのような HTML 要素をどのように見せかけることも可能です。しかし、このことは、そうすべきだと意味しているわけではありません。「HTML: アクセシビリティの基礎」という記事でしばしば述べたように、可能な場合にはいつでも、役割にふさわしい意味の要素を使うべきです。そうしないと、混乱を巻き起こしかねませんし、あらゆる人にとっての——とりわけ障碍のあるユーザーにとっての——使い勝手の問題を引き起こしかねません。正しいセマンティクスを使うことは、ユーザーの予期することと大いに関係があります。つまり、要素とは、その機能にしたがって、特定の見かけをしており特定のふるまいをするものであり、こうした通常の慣習をユーザーは予期するものなのです。

+ +

一例として、開発者が見出し要素を適切に使ってコンテンツをマークアップしていなかった場合には、スクリーン・リーダーのユーザーは、見出し要素を通じてページの見通しを得ることができないでしょう。同様に、見出しのようには見えないように見出しにスタイルをつけた場合には、見出しは視覚的な目的を失ってしまいます。

+ +

大まかな目安はこうです。つまり、自分のデザインに合わせるように、ページ項目のスタイル付けを更新するのは構いません。しかし、その項目が予期されるのとは全然違う見かけになったり、予期されるのとは全然違うふるまいをしたりするほど大幅にスタイル付けを変えてはいけません。以下の節では、考慮すべき主な HTML 項目について概説します。

+ +

「標準的」なテキストコンテンツ構造

+ +

見出し、段落、リスト——これらは、ページの中心的テキストコンテンツです。

+ +
<h1>見出し</h1>
+
+<p>段落</p>
+
+<ul>
+  <li>わたしのリストには</li>
+  <li>二つの項目があるよ。</li>
+</ul>
+ +

ある種の典型的な CSS は以下のようなものかもしれません。

+ +
h1 {
+  font-size: 5rem;
+}
+
+p, li {
+  line-height: 1.5;
+  font-size: 1.6rem;
+}
+ +

なすべきことは以下の通りです。

+ + + +

より詳しくは、HTML テキストの基礎テキストのスタイリングを参照してください。

+ +

強調したテキスト

+ +

囲んでいるテキストに対して特定の強調を与えるインライン・マークアップは、たとえば以下のようなものです。

+ +
<p>そのお湯は<em>とても熱いよ</em>。</p>
+
+<p>表面に集まる水滴は、<strong>結露</strong>と呼ばれます。</p>
+ +

強調したテキストに対して、なんらかの単純な色付けを加えたいかもしれません。

+ +
strong, em {
+  color: #a60000;
+}
+ +

けれども、なんらかの目立つ方法で強調要素をスタイル付けする必要はめったにないでしょう。太字とイタリック体のテキストという標準的慣習はとても認識しやすく、そのスタイルを変更することは混乱を招きかねません。強調についてのさらなる情報は、強調と重要性を参照してください。

+ +

略語

+ +

略語、頭文字語、つまり頭文字で表したものを、その展開形と関連付けることを可能とする要素は、たとえば以下のようなものです。

+ +
<p>ウェブ・コンテンツは、<abbr title="Hypertext Markup Language">HTML</abbr>を使ってマークアップされています。</p>
+ +

この場合も、なんらかの単純な方法でスタイルを付けたいかもしれません。

+ +
abbr {
+  color: #a60000;
+}
+ +

略語に対する公認のスタイル付けの慣習は、点線の下線です。そして、点線の下線から大きく逸脱するのは愚かしいことです。略語についてのさらなる情報は、略語を参照してください。

+ + + +

ハイパーリンク——ウェブ上の新たな場所に行く方法——は、たとえば以下のようなものです。

+ +
<p><a href="https://www.mozilla.org">Mozilla のホームページ</a>に来てくださいね。</p>
+ +

ある種のとても簡単なリンクのスタイル付けを以下に示します。

+ +
a {
+  color: #ff0000;
+}
+
+a:hover, a:visited, a:focus {
+  color: #a60000;
+  text-decoration: none;
+}
+
+a:active {
+  color: #000000;
+  background-color: #a60000;
+}
+ +

標準的なリンクの慣習は、下線を引いた、標準状態とは異なる色 (デフォルトは青) と、そのリンクを以前にたどったことがある場合の別の色変化 (デフォルトは紫) と、そのリンクがアクティブになっている場合のさらに別の色 (デフォルトは赤) です。さらに、リンクにマウスオーバーした場合には、マウスポインターがポインターアイコンに変化しますし、リンクは、(たとえばタブキーを押して) フォーカスが当たったり、アクティブ化されたりすると、ハイライトされます。以下の画像は、Firefox でのハイライト (点線の輪郭線) と Chrome でのハイライト (青い輪郭線) の双方を示したものです。

+ +

+ +

+ +

ユーザーがリンクを対話的に操作する際にユーザーに対してフィードバックを与え続ける限りは、リンクのスタイルに関して創造性を発揮して構いません。状態が変化する際には何かが明確に生じるべきであり、かつ、ポインターカーソルも輪郭線も——この両者は、キーボード・コントロールを使う人々にとって非常に重要なアクセシビリティの助けなのです——除去するべきではありませんが。

+ +

フォーム要素

+ +

ユーザーがウェブサイトにデータを入力できるようにする要素であり、たとえば以下のようなものです。

+ +
<div>
+  <label for="name">お名前を入力してください</label>
+  <input type="text" id="name" name="name">
+</div>
+ +

form-css.html の例 (ライブも見てください) において、ある種の適切な例示的 CSS が見られます。

+ +

フォーム用に書く CSS のほとんどは、要素のサイズを変更したり、ラベルと入力欄を整列したり、それらをすっきり整えたりするためのものでしょう。

+ +

ですが、フォーム要素にフォーカスが当たったときにそのフォーム要素が受けとる、予期された視覚的フィードバックからは、逸脱しすぎるべきではありません。そのことは、リンクの場合 (上記参照) と基本的に同様です。フォームのフォーカス / ホバー状態に対してスタイルを付けて、このふるまいがブラウザ間でより首尾一貫したものとなるようにしてもよいでしょうし、あるいは、自分のページ・デザインとより良く適合するようにしてもよいでしょう。しかし、予期される視覚的フィードバックをすべて捨て去ってはなりません。再び言いますが、これらの手がかりが、何が起きているのかを知る手助けになってくれるだろう、と人々は当てにしているのです。

+ +

テーブル

+ +

表データを提示するためのテーブルです。

+ +

table-css.html の例 (ライブも見てください) において、テーブルの HTML と CSS の、適切で簡潔な例を見られます。

+ +

テーブル CSS は一般に、テーブルを自分のデザインによりうまく適合させて、見苦しさを減らすのに役立ちます。テーブルの見出しが目立つようにすること (普通は太字を使います)、異なる行同士が見分けやすいようにシマウマ的配色を使うことは、良い考えです。

+ +

色とそのコントラスト

+ +

自分のウェブサイト用のカラー・スキームを選ぶときには、テキスト (前景) の色が背景色と十分に差があることを確認してください。あなたのデザインはかっこよく見えるかもしれませんが、もし色盲などの視覚障碍のある人々がコンテンツを読めなかったら、まったく良いデザインではありません。

+ +

問題を起こさない程度に十分にコントラストが大きいかどうかを調べる簡単な方法があります。前景色と背景色を入力して調べることができる、コントラストのチェック用ツールが、オンライン上にいくつもあります。たとえば、WebAIM の Color Contrast Checker は、簡単に使えますし、色のコントラストに関して WCAG の基準に適合するためには何を行えば良いのかについて、説明もしてくれます。

+ +
+

注意: コントラスト比を高くすることによって、光沢のある画面のスマートフォンまたはタブレットを使う人が陽光のような明るい環境でページを読みやすくもなるでしょう。

+
+ +

もう一つ別のコツは、標識や案内について色だけに頼らないことです。というのも、色だけに頼るのは、色が見えない人々にとってまったく良くないからです。必須のフォーム・フィールドを赤でマークする代わりに、たとえば、アスタリスクと赤でマークしましょう。

+ +

ものごとを隠す

+ +

すべてのコンテンツをいちどきに示さないことを視覚的デザインが求めているような、多くの事例があります。たとえば、Tabbed info box example の例 (ソースコードを参照)  では、三つの情報パネルがありますが、それらをお互いの上に配置しており、クリックするとそれぞれの情報パネルを表示できるタブを設けています (これはキーボード・アクセシブルでもあります。つまり、情報パネルを選ぶのに、クリックする代わりに、タブキーとエンターキー / リターンキーとを使うこともできます)。

+ +

+ +

スクリーン・リーダーのユーザーは、こうしたことは何も気にしません。ソースの順序が意味をなしている限りはコンテンツに満足しますし、コンテンツすべてに到達できます。(この例で使われているような) 絶対的な位置指定は、一般的に、視覚効果のためにコンテンツを隠す最善の仕組みの一つとして見られるものです。なぜなら、これは、スクリーン・リーダーがコンテンツに到達するの邪魔しないからです。

+ +

一方で、 {{cssxref("visibility")}}:hidden も {{cssxref("display")}}:none も、スクリーン・リーダーからコンテンツを隠してしまうので、使うべきではありません。もちろん、スクリーン・リーダーからこのコンテンツを隠したいと思う然るべき理由がない限りは、ということですが。

+ +
+

注意: Invisible Content Just for Screen Reader Users には、この話題をめぐる多くのさらに有用な詳細があります。

+
+ +

ユーザーがスタイルを上書きできることを受け入れる

+ +

ユーザーがスタイルを上書きできることを受け入れる

+ +

ユーザーは、自分のカスタム・スタイルでスタイルを上書きできます。たとえば以下のとおりです。

+ + + +

ユーザーは様々な理由から、スタイルの上書きを行うかもしれません。視覚障碍のあるユーザーは、すべての訪問先のウェブサイトでテキストを大きくしたいかもしれませんし、あるいは、重度の色覚障碍のあるユーザーは、すべてのウェブサイトを自分でも見やすい高コントラストの色にしたいかもしれません。その必要性がいかなるものであるにせよ、(スタイルの上書きという) この事態にはなじんでおくべきですし、そうした変更が自分のデザインにおいてうまく機能するように、自分のデザインを十分に柔軟なものとしておくべきです。例として、主なコンテンツ領域がより大きいテキストを扱えて (その領域は、全体を見られるようにスクロールし始めるかもしれません)、ただ隠したり完全に破綻したりしないように、気をつけると良いでしょう。

+ +

JavaScript

+ +

JavaScript も、その使い方によっては、アクセシビリティをぶち壊しにする可能性があります。

+ +

モダンな JavaScript は強力な言語です。簡単なコンテンツと UI の更新から、本格的な 2D ゲームや 3D ゲームに至るまで、近頃では JavaScript を使ってとても多くのことができます。すべてのコンテンツがすべての人々にとって 100% アクセシブルであるべきだ、といった決まりはありません。自分にできることをし、自分のアプリをできる限りアクセシブルにする必要があるだけなのです。

+ +

単純なコンテンツと機能——たとえば、テキスト、画像、テーブル、フォーム、関数を起動する押しボタン——は、まず間違いなく、アクセシブルにするのが簡単です。HTML: アクセシビリティの基礎 の記事で見たように、考慮すべき重要な事項は以下のとおりです。

+ + + +

機能が欠けているところに機能を盛り込むように JavaScript を使う方法の例も見ました (Building keyboard accessibility back in を参照)。この例は理想的ではありません。実際、ただふさわしい要素をふさわしい役割に使うべきなのです。が、この例は、使われるマークアップを何らかの理由で統制できない状況においては、こうしたこともあり得るのだと示しています。非意味的な、JavaScript で実装されたウィジェットについて、アクセシビリティを向上させる別の方法は、WAI-ARIA を用いて追加的なセマンティクスをスクリーン・リーダーのユーザーに提供することです。次の記事では、このことも詳しく扱います。

+ +

3D ゲームのような複雑な機能は、アクセシブルにするのがそう簡単ではありません。WebGL を使って作られた複雑な 3D ゲームは {{htmlelement("canvas")}} 要素上に描画されるでしょうが、今のところ {{htmlelement("canvas")}} 要素には、重度の視覚障碍のあるユーザーが利用できるように代替テキストもしくは他の情報を提供する手段がないのです。 そうしたゲームは、こうした人々のグループを実際に主要な対象者の一部としてはいないのだ、というのはもっともです。それに、そのゲームを、目の見えない人々にとって 100% アクセシブルにせよ、と期待するのも不合理でしょう。しかし、マウスを使わないユーザーにとって利用可能なようにキーボード・コントロールを実装することや、 色覚障碍のある人々にとって利用可能なようにカラー・スキームに十分なコントラストを持たせることならできるでしょう。

+ +

過度の JavaScript にともなう問題

+ +

JavaScript に頼りすぎると、しばしば問題が起きます。ときどき、何でもかんでも JavaScript で行われたウェブサイト—— HTML が JavaScript により生成され、CSS が JavaScript により生成され、といった調子のもの——を見るでしょう。これには、あらゆる種類のアクセシビリティの問題および付随するその他の問題があり、お勧めできません。

+ +

ふさわしい役割にふさわしい要素を使うのと同様に、ふさわしい役割にふさわしい技術を使っていることも確認しておくべきです!  JavaScript で実装されたキラキラの 3D 情報ボックスが必要なのか、あるいは、プレーンな古めかしいテキストでも用が足りそうか、ということについて注意深く考えてください。複雑で非標準的なフォーム・ウィジェットが必要なのか、あるいは、テキスト入力でも用が足りそうか、ということについて注意深く考えてください。そして、とにかく可能な場合に JavaScript を使ってすべての HTML コンテンツを生成する、などということはしないでください。

+ +

ひかえめに保つこと

+ +

コンテンツを作るときには、ひかえめな (unobtrusive) JavaScript  を心に留めておくべきです。ひかえめな JavaScript という考え方は、次のようなものです。すなわち、機能を拡張できるところならどこでも使うべきだけれども、機能を盛り込むためにはまったく使うべきではない——基本的機能は JavaScript なしでも理想的には動くはずなのだから。もっとも、これが常に選択できるとは限らないことはよく理解されているのですが。しかし再び言いますが、この考えの大部分を占めるのは、可能な箇所ではブラウザーの組み込み機能を使うということです。

+ +

ひかえめな JavaScript の適切な使用例には、次のものが含まれます。

+ + + +

一例として、やっつけ仕事のクライアントサイドのフォーム検査の例を書きました。form-validation.html を参照してください (demo live も参照してください). ここでは、単純なフォームが見えます。一方または双方のフィールドを空にしたままフォームを送信しようとすると、送信が失敗し、エラーメッセージ・ボックスが現れて、何が間違っているのかを教えてくれます。

+ +

この種のフォーム検査はひかえめです。JavaScript が利用できなくても、依然としてまったく申し分なくフォームを使えます。それに、分別のあるフォームの実装なら何であれ、サーバーサイドの検査も作動させておくことでしょう。なぜなら、悪意のあるユーザーがクライアントサイドの検査を (たとえば、ブラウザで JavaScript をオフにしておくことによって) 迂回することは、あまりに容易だからです。クライアントサイドの検査は、それでも実際に、エラーを報告するためには有用なのです。ユーザーは、自分のおかした間違いについて、サーバーまでのラウンドトリップおよびページリロードを待つ必要なしに、すぐに知ることができます。これは使い勝手の上での明らかな利点です。

+ +
+

注意: この単純なデモではサーバーサイドの検査を実装しませんでした。

+
+ +

このフォーム検査も、とてもアクセシブルにしておきました。{{htmlelement("label")}} 要素を用いて、フォーム・ラベルがそのラベルの入力欄に曖昧な点なしに紐付けられるようにして、それによってスクリーン・リーダーがラベルを一緒に読み上げられるようにしました。

+ +
<label for="name">お名前を入力してください (Enter your name):</label>
+<input type="text" name="name" id="name">
+ +

フォームが送信されるときにだけ検査をしています。これは、UI をあまりに頻繁に更新しないようにするため、そして、スクリーン・リーダーのユーザーを (また、おそらくは他のユーザーも) 潜在的に混乱させることがないようにするためです。

+ +
form.onsubmit = validate;
+
+function validate(e) {
+  errorList.innerHTML = '';
+  for(var i = 0; i < formItems.length; i++) {
+    var testItem = formItems[i];
+    if(testItem.input.value === '') {
+      errorField.style.left = '360px';
+      createLink(testItem);
+    }
+  }
+
+  if(errorList.innerHTML !== '') {
+    e.preventDefault();
+  }
+}
+ +
+

注意: この例では、絶対的な位置指定を用いてエラーメッセージ・ボックスを隠したり見せたりしています。visibility や display などの他の方法を使っているわけではありません。なぜなら、絶対的な位置指定は、スクリーン・リーダーがコンテンツを読めるようにしておくことを妨げないからです。

+
+ +

現実のフォーム検査は、これよりもっと複雑でしょう。入力された名前が実際に名前のようであることを確認したいかもしれませんし、入力された年齢が実際に数であり、かつ現実的である (たとえば、負数ではなく、4 桁でもない、など) ということを確認したいかもしれません。ここでは、各入力フィールドに値が入れられたことを確認する (if(testItem.input.value === '') という) 簡単な検査を実装しただけです。

+ +

検査が実行された際に、もしテストに通れば、フォームが送信されます。もしエラーがあれば (つまり if(errorList.innerHTML !== '') であれば)、 (preventDefault() を用いて) フォームの送信を中止し、生成されたエラーメッセージをすべて表示します (下記参照)。この仕組みは、エラーが存在するときにだけエラーが表示される、ということを意味します。そしてそのことは、使い勝手のうえで、より良いことなのです。

+ +

フォームが送信される際に値が入れられていない入力それぞれについて、リンクを有するリスト項目を作って、それを errorList  に挿入しています。

+ +
function createLink(testItem) {
+  var listItem = document.createElement('li');
+  var anchor = document.createElement('a');
+  anchor.textContent = testItem.input.name + ' field is empty: fill in your ' + testItem.input.name + '.';
+  anchor.href = '#' + testItem.input.name;
+  anchor.onclick = function() {
+    testItem.input.focus();
+  };
+  listItem.appendChild(anchor);
+  errorList.appendChild(listItem);
+}
+ +

各リンクは二つの役割を果たします。つまり、何のエラーなのかを教えてくれますし、さらに、そのリンクをクリックする / アクティブにすると問題の入力要素へ直接ジャンプして入力を訂正できるようになっています。

+ +
+

注意: この例の focus()  の部分は少し手が込んでいます。Chrome と Edge (と、IE の新しいバージョン) は、リンクがクリックされたときに要素にフォーカスを当てるので、onclick/focus() ブロックを必要としません。Safari  はリンク自体とともにフォーム要素をハイライトするだけであり、そのため、実際にフォーム要素にフォーカスを当てるには onclick/focus() ブロックが必要です。Firefox は、こうした状況において入力要素に適切にフォーカスを当てることはまったくありません。よって、Firefox  のユーザーは、現時点ではこの onclick/focus() ブロックの利益を享受できません (それ以外のすべてはうまく機能するのですが)。Firefox  の問題はすぐに修正されるはずです。というのも、他のブラウザと同等のふるまいを Firefox  にさせるための作業が、今なされている最中ですから ({{bug(277178)}} を参照).

+
+ +

さらに、ソース順における先頭に errorField  を置いてあります (CSS を使って、UI 上では別のところに配置してありますが)。これが意味することは、ユーザーが、ページの最初に戻ることで、自分のフォーム送信でまさに何が間違っているのかも分かるし、問題の入力要素にも行ける、ということです。

+ +

最後の注記ですが、このデモではいくつか WAI-ARIA 属性を使いました。ページリロードをともなわずに絶えず更新するコンテンツの領域が引き起こすアクセシビリティの問題を、解決する手助けとするためです (スクリーン・リーダーは、デフォルトでは、こうしたコンテンツを拾い上げたり、ユーザーにこうしたコンテンツを警告したりはしないでしょう)。

+ +
<div class="errors" role="alert" aria-relevant="all">
+  <ul>
+  </ul>
+</div>
+ +

もっと詳細に WAI-ARIA を扱う次の記事で、これらの属性について説明します。

+ +
+

注意: HTML5 フォームには required 属性や min/minlength 属性や max/maxlength  属性のような組み込みの検査の仕組みがあること (より詳しくは、{{htmlelement("input")}} 要素のリファレンスを参照) について考える読者もおそらくいることでしょう。このデモでは、結局これらの属性は使いませんでした。なぜなら、これらの属性についてのクロスブラウザ・サポートが当てにならないからです (たとえば IE10 以上のみでのサポートだったり、Safari ではサポートされていなかったりします)。

+
+ +
+

注意: WebAIM の Usable and Accessible Form Validation and Error Recovery は、アクセシブルなフォーム検査についてのさらに有用な情報をいくつか教えてくれます。

+
+ +

JavaScript のアクセシビリティのその他の問題

+ +

JavaScript で実装しつつアクセシビリティについて考えるときに意識すべきことは他にもあります。見つけ次第、さらなる事項を追加するつもりです。

+ +

マウスに特有のイベント

+ +

 お気づきのとおり、ユーザーとの対話的動作のほとんどは、イベントハンドラーを使ってクライアントサイドの JavaScript で実装されます。イベントハンドラーによって、特定のイベントが起きるのに応じて関数を実行できるようになります。ある種のイベントには、アクセシビリティの問題があるかもしれません。読者が見つけることになるであろう主な例は、mouseovermouseoutdblclick などの、マウスに特有のイベントです。これらのイベントに応じて動作する機能は、キーボード・コントロールのような他の仕組みを用いていると、アクセシブルではなくなります。

+ +

こうした問題を軽減するには、これらのイベントと、他の手段によってアクティブにできるような類似のイベントとの二重化をすべきです (いわゆるデバイスとは独立なイベントハンドラーです)。focusblur は、キーボードのユーザーに対するアクセシビリティを提供してくれることでしょう。

+ +

これが有用になりうる場合においてハイライトを行う事例を見てみましょう。ときにはサムネイル画像を設けたいことがあります。そのサムネイル画像にマウスオーバーした場合またはフォーカスが当たった場合に、その画像の、より大きなバージョンを表示するものです (電子商取引の商品カタログ上で見受けられるようなものです)。

+ +

とても簡単な例を作りました。これは、mouse-and-keyboard-events.html で見られます (ソースコード も参照)。このコードは、ズームインした画像を表示する関数と隠す関数という、二つの関数を特徴としています。これらの関数は、これらの関数をイベントハンドラーとして設定する以下の行により実行されます。

+ +
imgThumb.onmouseover = showImg;
+imgThumb.onmouseout = hideImg;
+
+imgThumb.onfocus = showImg;
+imgThumb.onblur = hideImg;
+ +

最初の 2 行は、それぞれ、マウスポインターがサムネイル上にホバーしたときと、マウスポインターがサムネイル上にホバーするのをやめたときに、関数を動作させます。しかしこれだと、ズームしたビューにキーボードを通じてアクセスすることはできません。それをできるようにするために、後ろの方の 2 行を含めました。この 2 行は、画像にフォーカスが当たったときと、画像からフォーカスが外れた (フォーカスが停止した) ときに、関数を動作させます。こうしたことは、タブキーで画像上に移動することでできることです。なぜなら、画像に tabindex="0" を含めておいたからです。

+ +

click クリックイベントは興味深いものです。マウス依存のように聞こえる名前ですが、ほとんどのブラウザーは、フォーカスの当たっているリンクまたはフォーム要素上でエンター / リターンが押された後に、あるいは、そうした要素がタッチスクリーン装置上でタップされたときに、onclick  イベントハンドラーをアクティブにすることでしょう。しかしこれは、tabindex を用いて、デフォルトではフォーカス可能ではないイベントがフォーカスを持つようにしていると、デフォルトのままではうまく機能しません。そうした場合では、まさにそのキーが具体的にはいつ押されたのかを検出する必要があります (Building keyboard accessibility back in を参照)。

+ +

まとめ

+ +

ウェブページ上での CSS と JavaScript の使用にまつわるアクセシビリティの問題について、このページが適切な量の細部と理解をもたらしたのであれば幸いです。

+ +

次は WAI-ARIA の番です!

+ +
{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}
+ +
+

このモジュール内

+ + +
diff --git a/files/ja/learn/accessibility/html/index.html b/files/ja/learn/accessibility/html/index.html new file mode 100644 index 0000000000..519594ad89 --- /dev/null +++ b/files/ja/learn/accessibility/html/index.html @@ -0,0 +1,564 @@ +--- +title: 'HTML: アクセシビリティの基礎' +slug: Learn/Accessibility/HTML +tags: + - AT + - Accessibility + - Article + - Beginner + - Buttons + - CodingScripting + - Forms + - HTML + - Learn + - Links + - a11y + - assistive technology + - keyboard + - screenreader + - semantics + - アクセシビリティ + - キーボード + - スクリーンリーダー + - セマンティクス + - フォーム + - ボタン + - リンク + - 初心者 + - 学習 + - 意味 +translation_of: Learn/Accessibility/HTML +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}
+ +

正確な HTML要素が、常に正しい目的で使用されているかを確認するだけで、たくさんのウェブコンテンツがアクセシブルになります。 ここでは、最大限のアクセシビリティを確保するために、HTML をどのように使用できるかについて詳しく説明します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピュータの知識、HTML に関する基本的な理解 (HTML 概論 を参照)、アクセシビリティとは何か に関する理解。
学習目標:HTML のうち、どの機能にアクセシビリティ上の利点があるのか、また、自身のウェブドキュメントでそうした機能を適切に使うにはどうしたらよいのか、ということに精通すること。
+ +

HTML とアクセシビリティ

+ +

HTML について学習を進めるのにつれて——資料をたくさん読んだり、たくさんの例を見たりするのにつれて——共通の主題を繰り返し見続けることになるでしょう。つまり、意味的な (セマンティックな) HTML を使うことの重要性という主題です (これは、POSH すなわち Plain Old Semantic HTML (簡潔な昔ながらの意味的 HTML) と呼ばれることがあります)。これが意味することは、できる限り、ふさわしい HTML 要素をふさわしい目的に使う、ということです。

+ +

これが何故それほど重要なのか、不思議に思うかもしれません。何しろ、CSS と JavaScript の組み合わせを使って、ほぼすべての HTML 要素を、どのような仕方であれ望みどおりに振る舞わせることができるわけですから。たとえば、サイト上で動画を再生するためのコントロール・ボタンを、次のようにマークアップすることもできます。

+ +
<div>動画を再生する</div>
+ +

けれども、後にさらに詳しく見るとおり、この役割にふさわしい要素を使うことには、とても意味があります。

+ +
<button>動画を再生する</button>
+ +

HTML の <button> は、ある種の適切なスタイルが (おそらくそのスタイルを上書きしたいと思うでしょうが) デフォルトで適用されているだけでなく、組み込みのキーボード・アクセシビリティも備えています。つまり、<button> 同士の間をタブで移動できますし、リターン / エンターを使って <button> をアクティブにできます。

+ +

もしプロジェクトの最初から首尾一貫して意味的な HTML を書くならば、意味的な HTML を書く方が非意味的な (駄目な) マークアップを書くよりも長くなったりはしません。それに、意味的な HTML には、アクセシビリティ以外の他の利点もあります。

+ +
    +
  1. より開発しやすい——上述のとおり、ある種の機能がただで手に入りますし、それに、より理解しやすいという点はまず間違いないところです。
  2. +
  3. モバイル機器に関して、より優れている——意味的な HTML は非意味的なスパゲッティ・コードよりも、ファイルサイズの点でほぼ間違いなく軽量ですし、レスポンシブにするのも簡単です。
  4. +
  5. SEO に関しても良好である——検索エンジンは、非意味的な <div> などに含まれるキーワードよりも、見出しやリンクなどの中のキーワードの方に重みを持たせているので、ドキュメントが顧客に見つけてもらいやすくなるでしょう。
  6. +
+ +

それでは、ここからアクセシブルな HTML をより詳しく見てゆきましょう。

+ +
+

: 自分のローカルコンピューターにスクリーンリーダーを用意することは良い考えです。そうすれば、以下に示す例について、ある程度のテストができます。より詳しくは、Screenreaders guide を参照してください。

+
+ +

良いセマンティクス

+ +

良いセマンティクスの重要性について、そして、ふさわしい役割にふさわしい HTML 要素を使うべきである理由については、すでに述べました。このことは無視してはなりません。なぜなら、適切に扱わないとアクセシビリティがひどく損なわれてしまう主な箇所のうちの一つだからです。

+ +

ウェブ上のどこかで、実は、人々は HTML のマークアップに関してとても変なことをしています。HTML の悪用のうちには、まだ完全に忘れ去られたわけではない過去の遺物的な慣行によるものもあり、ただ単純な無知によるものもあります。いずれにせよ、そうした駄目なコードは、どこで見たものであれ、可能な場合にはいつでも置き換えるべきです。

+ +

ときには、駄目なマークアップを取り去れる状況にいるとは限りません。自分で完全に制御しきれるわけではない、ある種のサーバーサイド・フレームワークによって、生成されたページなのかもしれません。あるいは、自分のページ上に、自分が管理していない (広告バナーのような) 第三者のコンテンツを含むかもしれません。

+ +

しかし、目標は「全か無か」というものではありません。自分ができる改善のことごとくが、アクセシビリティの理念に役立つことでしょう。

+ +

テキストコンテンツ

+ +

スクリーンリーダーのユーザーが得られる最良のアクセシビリティ支援の一つは、見出しや段落やリストなどの適切なコンテンツ構造です。きちんと意味を備えた例は、以下のようなものになるでしょう。

+ +
<h1>見出し</h1>
+
+<p>これは文書のうちの最初のセクションです。</p>
+
+<p>ここにも、もう一つ段落を足すつもり。</p>
+
+<ol>
+  <li>ここには</li>
+  <li>読んでもらいたいことの</li>
+  <li>リストがあります。</li>
+</ol>
+
+<h2>下位見出し</h2>
+
+<p>これは文書のうちの最初のサブセクションです。みんながこのコンテンツを見つけられるといいな!</p>
+
+<h2>2 番目の下位見出し</h2>
+
+<p>これはコンテンツのうちで 2 番目のサブセクションです。この前のものより面白いと思いますよ。</p>
+ +

スクリーンリーダーを使って試せるように、より長いテキストのバージョンを用意してあります (good-semantics.html を参照)。これの全体をナビゲートして (経巡って) みれば、これはとても見通しが得やすいものだということがわかるでしょう。

+ +
    +
  1. コンテンツの中を進んでゆくのにつれて、スクリーンリーダーは各ヘッダを読み上げて、どれが見出しでどれが段落なのかといったことを知らせてくれます。
  2. +
  3. どのような速度が快適であるにせよ、その速度で進んでいけるように、スクリーンリーダーは各要素の後で停止します。
  4. +
  5. 多くのスクリーンリーダーでは、次の見出し / 前の見出しへとジャンプできます。
  6. +
  7. 多くのスクリーンリーダーでは、すべての見出しの一覧を取り出せます。それらの見出しを、特定のコンテンツを見つけるための手軽な目次のようにも使えます。
  8. +
+ +

ときには、たとえば以下のように、体裁用の HTML や改行を使って見出しや段落などを書く人もいます。

+ +
<font size="7">見出し</font>
+<br><br>
+これは文書のうちの最初のセクションです。
+<br><br>
+ここにも、もう一つ段落を足すつもり。
+<br><br>
+1. ここには
+<br><br>
+2. 読んでもらいたいことの
+<br><br>
+3. リストがあります。
+<br><br>
+<font size="5">下位見出し</font>
+<br><br>
+これは文書のうちの最初のサブセクションです。みんながこのコンテンツを見つけられるといいな!
+<br><br>
+<font size="5">2 番目の下位見出し</font>
+<br><br>
+これはコンテンツのうちで 2 番目のサブセクションです。この前のものより面白いと思いますよ。
+ +

より長いバージョンをスクリーンリーダーで試してみれば (bad-semantics.html を参照)、とても良い体験が得られる、とはいかないことでしょう。スクリーンリーダーは、標識として使えるものを何も得られないので、有用な目次は取得できません。また、ページ全体を単一の巨大な塊として見ることになるので、ページ全体が一度にひとかたまりで読み上げられるだけなのです。 

+ +

アクセシビリティ以外の他の問題もあります。たとえば、CSS を使ってコンテンツにスタイルをつけることや、あるいは、JavaScript でコンテンツを操作することが、より難しくなるのです。なぜなら、セレクターとして使える要素がないからです。

+ +

明確な言葉を使う

+ +

使っている言い回しもアクセシビリティに影響を与えることがあります。一般に、過度に複雑ではない、明確な言葉を使うべきです。また、不必要な専門用語 (ジャーゴン) や俗語を使わないようにしましょう。これは、認知的な障害またはその他の障害を抱える人たちの助けとなるだけではありません。母語以外で書かれたテキストの読者や、年少者の助けにもなりますし、実際のところあらゆる人の助けになります!  それに加えて、スクリーンリーダーによって明確に読み上げられない言い回しや文字を使うことを避けるように努めるべきです。たとえば、以下のようなことです。

+ + + +

ページレイアウト

+ +

古き悪しき時代には、HTML テーブルを使って (つまり、ヘッダー、フッター、サイドバー、主要コンテンツの列、などなどを含む、別々のテーブル・セルを使って)、ページレイアウトを作成していたものです。これは良い考えではありません。なぜなら、スクリーンリーダーが、こんがらがった読み上げを発する可能性が高いからです。特に、レイアウトが複雑で多くの入れ子になったテーブルがある場合には、そうなりがちです。

+ +

table-layout.html の例を試してみてください。これは、以下のような感じになっています。

+ +
<table width="1200">
+      <!-- 主要な見出しの行 -->
+      <tr id="heading">
+        <td colspan="6">
+
+          <h1 align="center">Header</h1>
+
+        </td>
+      </tr>
+      <!-- ナビゲーション・メニューの行 -->
+      <tr id="nav" bgcolor="#ffffff">
+        <td width="200">
+          <a href="#" align="center">Home</a>
+        </td>
+        <td width="200">
+          <a href="#" align="center">Our team</a>
+        </td>
+        <td width="200">
+          <a href="#" align="center">Projects</a>
+        </td>
+        <td width="200">
+          <a href="#" align="center">Contact</a>
+        </td>
+        <td width="300">
+          <form width="300">
+            <input type="search" name="q" placeholder="Search query" width="300">
+          </form>
+        </td>
+        <td width="100">
+          <button width="100">Go!</button>
+        </td>
+      </tr>
+      <!-- 間隔をあけるための詰め物の行 -->
+      <tr id="spacer" height="10">
+        <td>
+
+        </td>
+      </tr>
+      <!-- 主要なコンテンツと余談の行 -->
+      <tr id="main">
+        <td id="content" colspan="4" bgcolor="#ffffff">
+
+          <!-- 主要なコンテンツがここに来る -->
+        </td>
+        <td id="aside" colspan="2" bgcolor="#ff80ff" valign="top">
+          <h2>Related</h2>
+
+          <!-- 余談的コンテンツがここに来る -->
+
+        </td>
+      </tr>
+      <!-- 間隔をあけるための詰め物の行 -->
+      <tr id="spacer" height="10">
+        <td>
+
+        </td>
+      </tr>
+      <!-- フッターの行 -->
+      <tr id="footer" bgcolor="#ffffff">
+        <td colspan="6">
+          <p>©Copyright 2050 by nobody. All rights reversed.</p>
+        </td>
+      </tr>
+    </table>
+ +

 スクリーンリーダーを使ってこれを読んで回ろうとすると、おそらくスクリーンリーダーは、見るべきテーブルがありますよ、と教えてくれるでしょう (もっとも、一部のスクリーンリーダーは、テーブル・レイアウトとデータ・テーブルとの違いを推測できるでしょうが)。すると、(使っているスクリーンリーダーによりますが) オブジェクトとしてのテーブルのところまで行って、そのテーブルの項目をそれぞれ別々に見て、それからやっと、テーブルから抜けて元の場所に戻り、コンテンツを読んで回ることを続ける、というふうにせざるを得ない可能性が高いでしょう。

+ +

テーブル・レイアウトは過去の遺物です。テーブル・レイアウトは、CSS のサポートがブラウザに広く行き渡っていなかった当時には意味を持っていましたが、スクリーンリーダーのユーザーに対して混乱を巻き起こします。しかも、他の多くの理由でも有害です (テーブルの乱用ですし、ほぼ間違いなくマークアップをより多く要しますし、デザインの柔軟さを損ねます)。テーブル・レイアウトをしてはなりません!

+ +

直前にした体験を、よりモダンなウェブサイトの構成例 (以下のような感じです) と比較することで、上記のような (テーブル・レイアウトは駄目だという) 主張の正しさを確認できます。

+ +
<header>
+  <h1>Header</h1>
+</header>
+
+<nav>
+  <!-- 主なナビゲーションはここです。 -->
+</nav>
+
+<!-- ここにページの主要コンテンツが来ます。 -->
+<main>
+
+  <!-- 主要コンテンツは記事を含みます。 -->
+  <article>
+    <h2>Article heading</h2>
+
+    <!-- 記事の中身はここです。 -->
+  </article>
+
+  <aside>
+    <h2>Related</h2>
+
+    <!-- 余談の中身はここです。 -->
+  </aside>
+
+</main>
+
+<!-- そしてここには、ウェブサイトの全ページを通じて使う主要なフッターが来ます。 -->
+
+<footer>
+  <!-- フッターの中身はここです。 -->
+</footer>
+ +

よりモダンな構造の例をスクリーンリーダーで試してみれば、もはやレイアウト・マークアップが妨げになることもなく、コンテンツの読み上げを混乱させることもない、とわかるでしょう。また、これは、コード・サイズの点で、より無駄がなく、より小さくなっています。これが意味することは、コードの保守が容易になるということ、そして、ユーザがダウンロードするのに帯域幅が小さくて済むということです (特に、接続が遅い人たちにとってはこれが効きます)。

+ +

レイアウトを作る際に考慮すべきもう一つの事柄は、上記の例に見られるように HTML5 の意味的要素を用いることです (コンテンツセクショニング を参照)。 入れ子になった {{htmlelement("div")}} 要素だけを使ってレイアウトを作ることもできますが、適切なセクショニング (区分け) 要素を使って、主要なナビゲーション ({{htmlelement("nav")}}) やフッター ({{htmlelement("footer")}}) や繰り返し現れるコンテンツ単位 ({{htmlelement("article")}}) などを囲う方が良いのです。これらの区分け要素は、いまナビゲートしている最中のコンテンツについての追加的な手がかりをユーザーに与えられるように、スクリーンリーダー (および他のツール) に追加的な意味 (セマンティクス) を提供してくれます (スクリーンリーダー・サポートとはどのようなものなのかについての考え方に関しては、Screen Reader Support for new HTML5 Section Elements を参照)。

+ +
+

: コンテンツは、ちゃんと意味的なものにしておき、レイアウトも魅惑的にしておくだけでなく、ソース順において論理的に意味をなすようにもしておくべきです。あとで CSS を使えば必ず望みどおりの場所にコンテンツを配置できますが、ソース順は、その順で読み始めるのが適切なようにしておくべきです。そうすれば、スクリーンリーダーのユーザーが読み上げさせたものが、意味をなすことでしょう。

+
+ +

UI コントロール

+ +

ここで UI コントロールという言葉によって意味しているのは、ユーザーが対話的に操作する対象の、ウェブドキュメントの主要部分のことであり、もっとも一般的には、ボタン、リンク、およびフォーム・コントロールのことです。本節では、そうしたコントロールを作る際に認識しておくべき基本的なアクセシビリティの問題を見てゆきましょう。WAI-ARIA とマルチメディアに関する後続の記事で、UI アクセシビリティの他の側面について見ることにします。

+ +

UI コントロールのアクセシビリティに対する一つの重要な側面は、ブラウザがデフォルトでは 、UI コントロールをキーボードで操作できるようにしている、ということです。このことは、native-keyboard-accessibility.html の例 (ソースコード を参照) を用いて試せます。これを新規タブで開いて、タブキーを押してみてください。二、三回押してみた後には、フォーカス可能な異なる要素の間をタブ・フォーカスが動き回り始めたのだと分かるはずです。どの要素にフォーカスが当たっているのかが分かるように、どのブラウザでも、フォーカスの当たっている要素には、ハイライトされたデフォルトのスタイルが付与されます (そのスタイルは、異なるブラウザ間では少し差があります)。

+ +

+ +

その後、エンターキー / リターンキーを押すと、フォーカスの当たっているリンクをたどることもできますし、または、ボタンを押すこともできますし (ボタンにメッセージ警告を出させるための JavaScript を含めておきました)、あるいは、テキスト入力欄にテキストを入力するためのタイピングを開始することもできます (他のフォーム要素には別のコントロールがあります。たとえば、{{htmlelement("select")}} 要素は、選択肢を表示させることや、上下の矢印キーを用いて選択肢の間を行ったり来たりさせることができます)。

+ +
+

: 異なるブラウザでは、異なるキーボード・コントロール・オプションを使用可能としている場合があります。さらに詳しいことは、Using native keyboard accessibility を参照してください。

+
+ +

こうした振る舞いは、たとえば以下のように単に適切な要素を用いるだけで、本質的にはただで手に入ります。

+ +
<h1>Links</h1>
+
+<p>This is a link to <a href="https://www.mozilla.org">Mozilla</a>.</p>
+
+<p>Another link, to the <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.</p>
+
+<h2>Buttons</h2>
+
+<p>
+  <button data-message="This is from the first button">Click me!</button>
+  <button data-message="This is from the second button">Click me too!</button>
+  <button data-message="This is from the third button">And me!</button>
+</p>
+
+<h2>Form</h2>
+
+<form>
+  <div>
+    <label for="name">Fill in your name:</label>
+    <input type="text" id="name" name="name">
+  </div>
+  <div>
+    <label for="age">Enter your age:</label>
+    <input type="text" id="age" name="age">
+  </div>
+  <div>
+    <label for="mood">Choose your mood:</label>
+    <select id="mood" name="mood">
+      <option>Happy</option>
+      <option>Sad</option>
+      <option>Angry</option>
+      <option>Worried</option>
+    </select>
+  </div>
+</form>
+ +

これは、リンクやボタンやフォーム要素やラベルを適切に用いることを意味しています (フォーム・コントロール用の {{htmlelement("label")}} 要素を含めています)。

+ +

しかし、またしてもですが、人が HTML で変なことをする場合がときにはあるものです。たとえば、次のように {{htmlelement("div")}} を用いてマークアップしたボタンを見かけることも、ときにはあります。

+ +
<div data-message="This is from the first button">Click me!</div>
+<div data-message="This is from the second button">Click me too!</div>
+<div data-message="This is from the third button">And me!</div>
+ +

しかし、そうしたコードを使うことは、勧められることではありません。単に {{htmlelement("button")}} 要素を使っていたなら得られていたはずの、ネイティブなキーボード・アクセシビリティを直ちに失ってしまううえに、当該ボタンが得るデフォルトの CSS スタイル付けを何も得られないからです。

+ +

キーボード・アクセシビリティを呼び戻すように盛り込む

+ +

そうした利点を呼び戻すように追加するには、ちょっとした作業が必要です (fake-div-buttons.html で例示的コードを試せます。ソースコード も参照してください)。ここでは、各ボタンに tabindex="0" という属性を付与することによって、見せかけの <div> ボタンにフォーカスを当てられるようにしました (タブキーを通じてのフォーカスを含みます)。

+ +
<div data-message="This is from the first button" tabindex="0">Click me!</div>
+<div data-message="This is from the second button" tabindex="0">Click me too!</div>
+<div data-message="This is from the third button" tabindex="0">And me!</div>
+ +

基本的には、{{htmlattrxref("tabindex")}} 属性は、タブキーでの移動が可能な要素に、単なるデフォルトのソース順でのタブ移動の代わりとなる特別あつらえのタブ順序 (正数の順で指定されるもの) を持たせられるようにすることを、主に意図したものです。これはほとんどの場合、筋の悪い考え方です。なぜなら、重大な混乱を招きかねないからです。本当に必要な場合にのみ、{{htmlattrxref("tabindex")}} 属性を使うようにしてください。たとえば、レイアウトによって、物事がソースコードとはまるで違った見かけ上の順序で示されており、かつ、より論理的に物事を機能させたいと望んでいるような場合です。tabindex には、あと二つの選択肢があります。

+ + + +

上記のような追加作業によって、タブキーでボタンに移動できるようにはなりますが、エンターキー / リターンキーを介してボタンをアクティブにすることはできるようになりません。それを可能とするには、以下のようなちょっとした JavaScript のごまかしを追加せねばなりません。

+ +
document.onkeydown = function(e) {
+  if(e.keyCode === 13) { // The Enter/Return key
+    document.activeElement.onclick(e);
+  }
+};
+ +

ここでは、キーボード上でいつボタンが押されたのかを検出するために、document オブジェクトにリスナーを追加しています。どのボタンが押されたのかを、イベント・オブジェクトの keyCode プロパティを介して調べています。 [訳注: 以上の二つの文の「ボタン」はキーボード上のキーのことのようです。また、keyCode プロパティは非推奨になっています。]もしエンターキー / リターンキーに合致するキーコードだったら、document.activeElement.onclick() を用い、ボタンの onclick ハンドラーに記憶されている関数を実行します [訳注: この文の「ボタン」は <div> ボタンのことのようです]。activeElement は、ページ上で現在フォーカスの当たっている要素を教えてくれます。

+ +
+

: 自分の独自のイベントハンドラーを、イベントハンドラー・プロパティ (たとえば onclick) を介して設定した場合にのみ、この技法がうまくいくだろうということに留意すべきです。addEventListener だと、うまくいきません。

+
+ +

これでは、機能を呼び戻すように盛り込むための、余計な厄介ごとの山ですね。それに、これにともなう他の問題もきっとあるはずです。そもそも、単にふさわしい要素をふさわしい役割に使うべきなのです。

+ +

意味の通るテキストラベル

+ +

UI コントロールのテキストラベルはあらゆるユーザーにとって大変有益ですが、そうしたラベルを適切なものにしておくことは、とりわけ、障碍のあるユーザーにとって重要です。

+ +

ボタンとリンクテキストのラベルが、理解可能であり、かつ弁別性のあるものになっていることを、確認すべきです。ラベルとして単に「ここをクリック」を使うのはいけません。なぜなら、スクリーンリーダーのユーザーは、ボタンとフォーム・コントロールの一覧をまとめ上げることがあるからです。以下のスクリーンショットは、Mac 上の VoiceOver によって一覧化されたコントロールを示しています。

+ +

+ +

ラベルが存在している段落の文脈内においてラベルが意味をなすようにするだけでなく、文脈を離れてもラベルが意味をなすように (ラベルが単独で読まれても意味をなすように) してください。たとえば、以下のものは、良いリンクテキストの例を示しています。

+ +
<p>クジラは本当にすごい生き物です。<a href="whales.html">クジラについてもっと知ってくださいね</a>。</p>
+ +

しかしこれは駄目なリンクテキストです。

+ +
<p>クジラは本当にすごい生き物です。クジラについてもっと知るには、<a href="whales.html">ここをクリックしてください</a>。</p>
+ +
+

: リンクの実装とベスト・プラクティスに関するさらなる情報を、Creating hyperlinks  という記事で知ることができます。また、いくつかの良い例と悪い例を、good-links.htmlbad-links.html で見ることもできます。

+
+ +

フォーム・ラベルも重要です。なぜなら、各フォーム入力欄に何を入力する必要があるのかについての手がかりを与えてくれるからです。以下のものは、十分に筋の通った例のように見えます。

+ +
名前を入れてください: <input type="text" id="name" name="name">
+ +

しかしこれは、障碍のあるユーザーにとって、それほど有用ではありません。このラベルを曖昧性なしにフォーム入力欄に結びつけ、そして、仮に入力欄が見えなくても、入力欄をどう埋めたら良いのかを明確にしてくれるものが、上記の例には何もありません。なんらかのスクリーンリーダーでこの例にアクセスした場合には、「テキストを編集する」のような感じの説明のみが与えられることもあるかもしれません。

+ +

以下のものは、ずっと良い例です。

+ +
<div>
+  <label for="name">名前を入れてください:</label>
+  <input type="text" id="name" name="name">
+</div>
+ +

このようなコードだと、ラベルが明確に入力欄と結びつけられることになります。説明は、(上記のような単なる「テキストを編集する」ではなくて) むしろ「名前を入れてください: テキストを編集する」といった感じのものになるでしょう。

+ +

+ +

追加のおまけとして、ほとんどのブラウザにおいて、ラベルをフォーム入力欄に結びつけることは、ラベルをクリックして当該フォーム要素を選択 / アクティブ化することが可能なことを意味します。このことにより、入力欄に対して、より大きなヒット領域を与えることになり、したがって、入力欄が選択しやすくなります。

+ +
+

: good-form.htmlbad-form.html で、いくつかの良いフォーム例と悪いフォーム例を見られます。

+
+ +

アクセシブルなデータテーブル

+ +

基本的なデータテーブルは、たとえば以下のように、とても簡素なマークアップで書けます。

+ +
<table>
+  <tr>
+    <td>Name</td>
+    <td>Age</td>
+    <td>Gender</td>
+  </tr>
+  <tr>
+    <td>Gabriel</td>
+    <td>13</td>
+    <td>Male</td>
+  </tr>
+  <tr>
+    <td>Elva</td>
+    <td>8</td>
+    <td>Female</td>
+  </tr>
+  <tr>
+    <td>Freida</td>
+    <td>5</td>
+    <td>Female</td>
+  </tr>
+</table>
+ +

しかしこれには問題があります。スクリーンリーダーのユーザーには、行または列をデータの集まりとしてまとめて関連づける手段が何もないのです。こうした関連づけを行うには、見出し行がどれなのか、見出し行は複数の行を統率しているのか、複数の列を統率しているのか、などといったことを知らねばなりません。こうしたことは、上記のテーブルでは、視覚的に行われる以外にありません (bad-table.html を参照して、その例をご自分で試してみてください)。

+ +

では、 パンクバンドのテーブルの例 を見てみましょう。ここでは、多少のアクセシビリティ支援が機能していることが分かりますね。

+ + + +
+

: アクセシブルなデータテーブルにまつわる更なる詳細は、HTML テーブルの発展的な機能とアクセシビリティ という記事を参照してください。

+
+ +

代替テキスト

+ +

テキストによるコンテンツは本質的にアクセシブルですが、マルチメディア・コンテンツについては必ずしも同じことが言えるわけではありません。画像 / 動画コンテンツは視覚障碍者には見えず、音声コンテンツは聴覚障碍者には聞こえません。動画と音声のコンテンツについては、アクセシブルなマルチメディア という記事で後に詳しく扱うことにしますが、本記事では、ごく普通の {{htmlelement("img")}} 要素についてのアクセシビリティを見てゆきましょう。

+ +

accessible-image.html という簡単な例を書き上げました。これは、4 枚の同じ画像を含んでいます。

+ +
<img src="dinosaur.png">
+
+<img src="dinosaur.png"
+     alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
+<!--
+[alt 属性の訳: 赤いティラノサウルス・レックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。]
+-->
+
+<img src="dinosaur.png"
+     alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."
+     title="The Mozilla red dinosaur">
+<!--
+[alt 属性の訳: 赤いティラノサウルス・レックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。]
+[title 属性の訳: Mozzila の赤い恐竜]
+-->
+
+<img src="dinosaur.png" aria-labelledby="dino-label">
+
+<p id="dino-label">The Mozilla red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.</p>
+<!--
+[p 要素の中身の訳: Mozilla の赤いティラノサウルス・レックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。]
+-->
+ +

1 枚目の画像は、スクリーンリーダーで見たときに、実際のところ大した手助けをユーザーに与えてはくれません。たとえば VoiceOver は、「/dinosaur.png, image」と読み上げます。なんらかの手助けを提供しようとしてファイル名を読み上げるわけです。この例では、ユーザーは、少なくともこれがある種の恐竜なのだと知ることでしょうが、機械で生成されたファイル名とともにファイルが (たとえばディジタルカメラから) アップロードされる場合もよくありますし、そうしたファイル名は画像の中身に対する文脈を何も与えてはくれないでしょう。

+ +
+

:  これこそが、画像の内部にテキストコンテンツを決して含めるべきではない理由です。スクリーンリーダーは、まったくそのテキストコンテンツにアクセスできません。それに、他の欠点もあります。すなわち、そのテキストコンテンツを選択することもコピー / ペーストすることもできません。画像の内部にテキストコンテンツを含めるなどということは、とにかくしないでください!

+
+ +

スクリーンリーダーは、2 枚目の画像に出くわすと、alt 属性を丸々読み上げます。つまり、「赤いティラノサウルス・レックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります」と読み上げます。

+ +

この例は、いわゆる alt テキストが万一使えない場合に備えて意味のあるファイル名を使うことだけでなく、可能な場合にはいつでも alt テキストを alt 属性において確実に提供しておくことの重要性を、際立たせるものです。alt 属性の中身は常に、画像の端的な描写と、画像が視覚的に伝えているものとを提供すべきであることに、注意してください。ここには、個人的な知識や追加的な説明を何も含めるべきではありません。なぜなら、以前にその画像に出くわしたことのない人にとって有益ではないからです。

+ +

考えるべきことの一つは、画像がコンテンツの内部で意味を持っているのか、あるいは、純粋に視覚的装飾のためのものであって意味は持たないのか、ということです。もし画像が装飾用であれば、その画像を CSS 背景画像としてページ内に含めるだけにする方が良いのです。

+ +
+

: 画像の実装とベスト・プラクティスについての更なる多くの情報については、Images in HTMLResponsive images をお読みください。

+
+ +

文脈のある追加的な情報をどうしても提示したい場合、その情報は、画像の周囲のテキストの中か、あるいは、上記のように title 属性の内部に入れるべきです。この場合、ほとんどのスクリーンリーダーは、alt テキストと、title 属性と、ファイル名とを読み上げるでしょう。さらに、マウスオーバーしたときには、ブラウザが title テキストをツールチップとして表示します。

+ +

+ +

4 番目の方法についてもざっと見ておきましょう。

+ +
<img src="dinosaur.png" aria-labelledby="dino-label">
+
+<p id="dino-label">The Mozilla red Tyrannosaurus ... </p>
+ +

この場合、alt 属性をまったく使っていません。その代わり、画像についての説明を通常のテキスト段落として提示し、その段落に id を与え、そして、その id を参照するための aria-labelledby 属性を用いました。こうすると、スクリーンリーダーに、その段落をその画像についての alt テキスト / ラベルとして使わせることになります。これは、複数の画像に対して同じテキストをラベルとして使いたい場合に、とりわけ有用です (こうしたことは、alt を使ってではできない事柄なのです)。

+ +
+

: aria-labelledbyWAI-ARIA 仕様の一部です。これのおかげで開発者は、必要な箇所においてスクリーンリーダーのアクセシビリティを高めるために、自分のマークアップに追加的な意味 (セマンティクス) を足すことができます。これがどのように機能するのかについての更なる情報を知るには、WAI-ARIA の基本 の記事をお読みください。

+
+ +

その他の代替テキストの仕組み

+ +

画像には、説明的テキストを提供するのに利用可能な別の仕組みもあります。たとえば、画像についての広範囲にわたる説明を含む別のウェブドキュメントを指すことを意図した、longdesc 属性があります。たとえば以下のようなものです。

+ +
<img src="dinosaur.png" longdesc="dino-info.html">
+ +

これは良い考えのように思えます。というのも、とりわけ、多くの情報が載っている大きな図表のようなインフォグラフィックを、代わりにアクセシブルなデータテーブル (前節を参照) として表現することがおそらくは可能でしょうから。しかし、longdesc は、スクリーンリーダーによっていつもサポートされているわけではありませんし、スクリーンリーダー以外のものを使っているユーザーにとっては、コンテンツがまったくアクセス不能です。まず間違いなく、画像と同じページに長い説明を含めるか、あるいは、通常のリンクを使って長い説明にリンクする方が、ずっと良いのです。

+ +

HTML5 は、{{htmlelement("figure")}} と {{htmlelement("figcaption")}} という二つの新規要素を含みます。これらは、なんらかの種類の図面 (任意のものであってよく、必ずしも画像とは限りません) を、図面キャプション (説明文) と結びつけることになっているものです。

+ +
<figure>
+  <img src="dinosaur.png" alt="Mozilla のティラノサウルス">
+  <figcaption>赤いティラノサウルス・レックス。人間のように直立する二足歩行の恐竜で、腕は小さく、頭部は大きくて多くの鋭い歯があります。</figcaption>
+</figure>
+ +

あいにく、ほとんどのスクリーンリーダーは、まだ、図面キャプションを図面と結びつけてはくれないようです。ですが、この要素構造は CSS でのスタイルづけにとって有益ですし、ソース内で画像の隣にその画像の説明を配置するための手段を与えてもくれます。

+ +

空の代替テキスト

+ +
<h3>
+  <img src="article-icon.png" alt="">
+  ティラノサウルス・レックス: 恐竜の王
+</h3>
+ +

画像がページのデザインに含まれるけれども、主目的は視覚的装飾である、といった場合もあるかもしれません。上記のコード例において、画像の alt 属性が空であることにお気づきでしょう。これは、スクリーンリーダーに画像を認識させるものですが、その画像を説明しようとさせるものではありません (説明する代わりに、スクリーンリーダーは、単に「画像」とか何とか言うでしょう)。

+ +

alt を含めないようにする代わりに空の alt を用いる理由は、alt が与えられていない場合には多くのスクリーンリーダーが画像の URL を丸々全部発声するからです。上記の例において画像は、その画像が結びつけられている見出しに対する視覚的装飾として機能しています。このような場合、および、画像が単に装飾にすぎず中身の価値がない場合には、画像に空の alt を入れるべきです。別の選択肢は、role="presentation" という ARIA role 属性を使うことです。こうすることによっても、スクリーンリーダーに代替テキスト (alt テキスト) を読み上げるのをやめさせることができます。

+ +
+

: もし可能なら、単なる修飾であるような画像を表示するのには CSS を使うべきです。

+
+ +

要約

+ +

 今や読者の皆さんは、ほとんどの場合にアクセシブルな HTML を書くことについて、熟知しているはずです。WAI-ARIA の基本 の記事も、この知識の抜けを埋めてくれるでしょうが、本記事でもその基本には気を配ってきました。次は、CSS と JavaScript を検討しましょう。そして、CSS と JavaScript の良い使い方やまずい使い方によって、アクセシビリティがどのような影響を受けるのかを検討しましょう。

+ +

{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}

+ +

 

+ +

このモジュール内

+ + + +

 

diff --git a/files/ja/learn/accessibility/index.html b/files/ja/learn/accessibility/index.html new file mode 100644 index 0000000000..eb71416a85 --- /dev/null +++ b/files/ja/learn/accessibility/index.html @@ -0,0 +1,63 @@ +--- +title: アクセシビリティ +slug: Learn/Accessibility +tags: + - ARIA + - Accessibility + - Articles + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - Learn + - Module + - アクセシビリティ + - ランディング + - 初心者 +translation_of: Learn/Accessibility +--- +
{{LearnSidebar}}
+ +

ウェブ開発者になりたい場合、HTML, CSS, JavaScript の学習は役立ちます。しかし知識は単に技術を使うよりも前に進める必要があります — それらを責任を持って使う必要があり、その結果ウェブサイトの聴衆を増やし、またそれを使わないことに縛らないことになります。これを達成するには、一般的な成功事例 (HTML, CSS, JavaScript のトピックに示されています) を積み上げ、クロスブラウザーテストを行って、最初からアクセシビリティを考慮しておきます。このモジュールでは後者を詳しく扱います。

+ +

前提知識

+ +

このモジュールの大半の理解には、少なくとも HTML, CSS, JavaScript の最初の 2 モジュールを通して読むのが良いでしょうし、 たぶんもっと良いのは、関連するテクノロジートピックを進めるにつれて、関連するアクセシビリティの部分を進めるのが良いでしょう。

+ +
+

メモ: 自分のファイルを作れない コンピューター/タブレット/その他の端末で作業する場合、コードの実例の大半を JSBinGlitch などのオンラインコーディングプログラム内で試すことができます。

+
+ +

ガイド

+ +
+
アクセシビリティとは?
+
この記事では実際アクセシビリティとは何かについてよく観察するモジュールから開始します — これには考慮が必要な人のグループや、いろいろな人がウェブとやり取りするのになぜ、どんなツールを使うのかや、アクセシビリティをウェブ開発の作業フローに取り組む方法が含まれます。
+
HTML: アクセシビリティの基礎
+
ウェブコンテンツをアクセシビリティ高くすることの多くの部分は、どんなときも正しい HTML要素を正しい目的で使うことです。 この記事ではアクセシビリティを最大化するためにどう HTML が使われるかの詳細を見ていきます。
+
CSS と JavaScript のアクセシビリティ成功事例
+
CSS と JavaScript も、適切に使うと、アクセシビリティの高いウェブ体験を可能にする力を持っていますが、誤用されると目立ってアクセシビリティを害することもあります。この記事では、複雑なコンテンツでもなるべくアクセシビリティ高める CSS と JavaScript のいくつかの成功事例をざっと見ます。
+
WAI-ARIA の基本
+
前の記事に続いて、複雑な UI に非セマンティックな HTML や動的な JavaScript-更新コンテンツを作ることは難しいかもしれません。WAI-ARIA は、そうした問題をブラウザーと補助技術が認識できるセマンティクスを追加することで補助し、ユーザーに何が起きているのかを知らせるのに使うテクノロジーです。ここではアクセシビリティを改善する基本レベルの使用方法を示します。
+
アクセシブルなマルチメディア
+
アクセシビリティの問題を起こす可能性がある他のカテゴリは、マルチメディアです。ビデオ、オーディオ、およびイメージのコンテンツには、補助技術とユーザーが理解できるような、適切な代替テキストを付与する必要があります。どのように表示されるべきか分かるように。
+
モバイルアクセシビリティ
+
モバイル端末でのウェブへのアクセスが増えるとともに、アクセシビリティのツールが本格的に提供されている iOS や Android のような一般的なプラットフォームが普及しています。これらのプラットフォームでのあなたのウェブコンテンツのアクセシビリティを考えることが重要です。モバイル特有のアクセシビリティについて検討しましょう。
+
+ +

評価

+ +
+
アクセシビリティのトラブルシューティング
+
このモジュールの評価では、分析と修正が必要な多くのアクセシビリティの問題があるシンプルなサイトを紹介します。
+
+ +

関連情報

+ + diff --git a/files/ja/learn/accessibility/mobile/index.html b/files/ja/learn/accessibility/mobile/index.html new file mode 100644 index 0000000000..24cad97ef9 --- /dev/null +++ b/files/ja/learn/accessibility/mobile/index.html @@ -0,0 +1,316 @@ +--- +title: モバイルのアクセシビリティ +slug: Learn/Accessibility/Mobile +tags: + - Accessibility + - コードスクリプト + - スクリーンリーダー + - タッチ + - モバイル + - レスポンシブ + - 初心者 + - 学習 + - 記事 +translation_of: Learn/Accessibility/Mobile +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Accessibility/Multimedia","Learn/Accessibility/Accessibility_troubleshooting", "Learn/Accessibility")}}
+ +

モバイルデバイスでのウェブアクセスは非常に人気があり、iOS や Android などの一般的なプラットフォームには本格的なアクセシビリティツールが備わっているため、これらのプラットフォームでのウェブコンテンツのアクセシビリティを考慮することが重要です。この記事では、モバイル固有のアクセシビリティについて検討します。

+ + + + + + + + + + + + +
前提知識基本的なコンピューターの知識、HTML、CSS、JavaScript の基本的な知識、前回までの記事の理解。
学習目標モバイルデバイスのアクセシビリティにどのような問題があるのか、またそれらを克服する方法を理解すること。
+ +

モバイルデバイスのアクセシビリティ

+ +

アクセシビリティの現状と、ウェブ標準全般のサポートは、現代のモバイルデバイスでは優れています。モバイルデバイスがデスクトップブラウザーとはまったく異なるウェブ技術を実行し、開発者がブラウザースニッフィングを使用してそれらを完全に別々のサイトで提供することを余儀なくされた時代は終わりました(ただし、かなりの数の企業が依然としてモバイルデバイスの使用を検出し、それらに別のモバイルドメインを提供しています)。

+ +

最近の一般的なモバイルデバイスは、「脂肪分たっぷり」のウェブサイトを扱うことができ、主なプラットフォームには視覚障害のあるユーザーがそれらをうまく使えるようにスクリーンリーダーが組み込まれています。最近のモバイルブラウザーは WAI-ARIA もよくサポートしています。

+ +

ウェブサイトをモバイルでアクセス可能かつ使用可能にするには、一般的な優れたウェブデザインとアクセシビリティのベストプラクティスに従う必要があるだけです。

+ +

モバイルに特別な配慮が必要な例外がいくつかあります。主なものは次のとおりです。

+ + + +

Android および iOS でのスクリーンリーダーテストの概要

+ +

最も一般的なモバイルプラットフォームは完全に機能的なスクリーンリーダーを持っています。これらはデスクトップのスクリーンリーダーとほとんど同じように機能しますが、キーの組み合わせではなくタッチジェスチャーを使用して主に操作される点が異なります。

+ +

主な 2 つを見てみましょう: Android の TalkBack と iOS の VoiceOver です。

+ +

Android TalkBack

+ +

TalkBack スクリーンリーダーは Android オペレーティングシステムに組み込まれています。

+ +

オンにするには、スマートフォンのモデルと Android バージョンを調べて、TalkBack メニューの場所を探します。これは Android のバージョンやスマートフォンのモデルによっても大きく違います。あるスマートフォンメーカー(Samusung など)では、最新の機種で TalkBack がなくて、代わりに独自のスクリーンリーダーを選んでいることもあります。

+ +

TalkBack メニューが見つかったら、スライダースイッチを押してオンにします。画面に表示される追加の指示に従います。

+ +

TalkBack がオンになっているとき、あなたの Android デバイスの基本的なコントロールは少し違います。例えば、

+ +
    +
  1.  アプリをシングルタップするとそれが選択され、デバイスはそのアプリが何かを読み上げます。
  2. +
  3. 左右にスワイプすると、アプリ間、またはコントロールバーにいる場合はボタンやコントロールの間を移動します。デバイスは各オプションを読み上げます。
  4. +
  5. どこでもダブルタップするとアプリが開いたり、オプションが選択されたりします。
  6. +
  7. また、「タッチで探索」することもできます — ドラッグ(指を画面に置いたまま移動)すると、デバイスは移動先のさまざまなアプリや項目を読み上げます。
  8. +
+ +

TalkBack をオフにしたい場合は、

+ +
    +
  1. 上記のジェスチャーを使用して [設定] アプリに移動します。
  2. +
  3. [ユーザー補助] > [TalkBack] に移動します。
  4. +
  5. スライダースイッチに移動してアクティブにすると、オフになります。
  6. +
+ +
+

: 連続した動きで上にスワイプしてから左にスワイプすると、いつでもホーム画面にアクセスできます。複数のホーム画面がある場合は、左右に 2本指でスワイプすることでそれらの間を移動できます。

+
+ +

TalkBack ジェスチャーのより完全なリストについては、TalkBack ジェスチャーを利用するを参照してください。

+ +

端末のロックを解除する

+ +

TalkBack がオンになっているとき、端末のロック解除は少し違います。

+ +

ロック画面の下から上に 2本指でスワイプすることができます。デバイスのロックを解除するためのパスコードまたはパターンを設定している場合は、関連する入力画面に移動して入力します。

+ +

画面の中央下部にある [ロック解除] ボタンをタッチで探索してから、ダブルタップすることもできます。

+ +

グローバルメニューとローカルメニュー

+ +

TalkBack を使用すると、デバイス上のどこに移動しても、グローバルおよびローカルのコンテキストメニューにアクセスできます。前者はデバイス全体に関するグローバルオプションを提供し、後者は現在のアプリや画面だけに関するオプションを提供します。

+ +

これらのメニューにアクセスするには、

+ +
    +
  1. すばやく下にスワイプしてから右にスワイプしてグローバルメニューにアクセスします。
  2. +
  3. すばやく上にスワイプしてから右にスワイプしてローカルメニューにアクセスします。
  4. +
  5. 左右にスワイプしてさまざまなオプションを切り替えます。
  6. +
  7. 必要なオプションを選択したら、ダブルタップしてそのオプションを選択します。
  8. +
+ +

グローバルおよびローカルのコンテキストメニューで使用可能なすべてのオプションの詳細については、グローバル コンテキストメニューとローカル コンテキスト メニューを使うを参照してください。

+ +

ウェブページのブラウジング

+ +

ウェブブラウザーでローカルコンテキストメニューを使用して、見出し、フォームコントロール、リンク、行単位の移動などウェブページを移動するためのオプションを見つけることができます。

+ +

例えば、TalkBack をオンにした場合、

+ +
    +
  1. ウェブブラウザーを開きます。
  2. +
  3. URL バーをアクティブにします。
  4. +
  5. Ebbc.co.uk のフロントページのように、見出しがたくさんあるウェブページを入力します。URL のテキストを入力するには、 +
      +
    • URL バーが得られるまで左右にスワイプしてから、ダブルタップして URL バーを選択します。
    • +
    • 目的の文字が得られるまで仮想キーボードに指を置いたまま動かしてから、指を離して入力します。これを各文字について繰り返します。
    • +
    • 終わったら、Enter キーを見つけて押します。
    • +
    +
  6. +
  7. 左右にスワイプすると、ページ上のさまざまな項目間を移動できます。
  8. +
  9. 連続した動きで上にスワイプしてから右にスワイプして、ローカルコンテキストメニューに入ります。
  10. +
  11. [見出しとランドマーク] オプションが見つかるまで右にスワイプします。
  12. +
  13. ダブルタップして選択します。これで、見出しと ARIA のランドマークの間を移動するために左右にスワイプすることができます。
  14. +
  15. デフォルトモードに戻るには、上にスワイプしてから右にスワイプしてローカルコンテキストメニューに再度入り、[デフォルト] を選択してからダブルタップしてアクティブにします。
  16. +
+ +

: より完全なドキュメントは Android で TalkBack を使ってみるをご覧ください。

+ +

iOS VoiceOver

+ +

VoiceOver のモバイル版は iOS オペレーティングシステムに組み込まれています。

+ +

それをオンにするには、あなたの設定アプリに行き、[一般] > [アクセシビリティ] > [VoiceOver] を選択してください。VoiceOver スライダを押して有効にします(このページには VoiceOver に関連する他の多数のオプションも表示されます)。

+ +
+

: 古い iOS 端末では VoiceOver メニューは 設定 > 一般 > アクセシビリティ > VoiceOverにあります。

+
+ +

VoiceOver が有効になると、iOS の基本的なコントロールジェスチャーは次のように少し違います。

+ +
    +
  1. シングルタップすると、タップした項目が選択されます。デバイスはあなたがタップした項目を読み上げるでしょう。
  2. +
  3. 左右にスワイプして項目間を移動したり、画面上で指をスライドさせてさまざまな項目間を移動したりして、画面上の項目を移動することもできます(必要な項目が見つかったら、指を離して選択できます)。
  4. +
  5. 選択した項目をアクティブにする(例えば、選択したアプリを開く)には、画面上のどこでもダブルタップします。
  6. +
  7. 3本指でスワイプしてページをスクロールします。
  8. +
  9. カメラアプリで写真を撮るなど、状況に応じたアクションを実行するには、2本指でタップします。
  10. +
+ +

もう一度オフにするには、上記のジェスチャを使用して [設定] > [一般] > [アクセシビリティ] > [VoiceOver] に戻り、[VoiceOver] スライダをオフに切り替えます。

+ +

端末のロック解除

+ +

端末のロックを解除するには、通常どおりホームボタンを押す(またはスワイプする)必要があります。パスコードが設定されている場合は、上で説明したようにスワイプ/スライドして各番号を選択し、次に正しい番号を見つけたらダブルタップして各番号を入力できます。

+ +

ローターを使用する

+ +

VoiceOver がオンになっているとき、ローターと呼ばれるナビゲーション機能を使えます。それは素早く多くの一般的で役に立つオプションから選ぶことを可能にします。それを使用するには、

+ +
    +
  1. ダイヤルを回すように、画面上で 2本の指をひねります。あなたがさらにひねるにつれて、各オプションを読み上げるでしょう。あなたは行ったり来たりしてオプションを切り替えることができます。
  2. +
  3. あなたが望むオプションを見つけたら、 +
      +
    • 指を離して選択します。
    • +
    • それが(音量や話す速度のような)値を反復できるオプションである場合は、選択した項目の値を増減するために上下にスワイプすることができます。
    • +
    +
  4. +
+ +

ローターで利用可能なオプションは状況依存型です — それらはどのアプリやビューにいるかによって異なります(例については下記を参照)。

+ +

ウェブページのブラウジング

+ +

VoiceOver を使ったウェブブラウジングを試してみましょう。

+ +
    +
  1. ウェブブラウザーを開きます。
  2. +
  3. URL バーをアクティブにします。
  4. +
  5. bbc.co.uk のフロントページのように、見出しがたくさんあるウェブページを入力します。URL のテキストを入力するには、 +
      +
    •  URL バーが得られるまで左右にスワイプしてダブルタップし、URL バーを選択します。
    • +
    • 各文字について、目的の文字が得られるまで仮想キーボードに指を置いたまま動かしてから、指を離して選択します。ダブルタップして入力します。
    • +
    • 終ったら、Enter キーを見つけて押します。
    • +
    +
  6. +
  7. 左右にスワイプすると、ページ上の項目間を移動できます。項目をダブルタップして選択することができます(例えば、リンクをたどる)。
  8. +
  9. デフォルトでは、選択されたローターオプションは話す速度です。現在は上下にスワイプして話す速度を上げ下げできます。
  10. +
  11. 今、ダイヤルのように 2本指で画面を回転させてローターを表示し、ローターのオプション間を移動します。利用可能なオプションの例をいくつか示します。 +
      +
    • 話す速度: 話す速度を変更します。
    • +
    • コンテナ: ページ上のさまざまな意味論的コンテナ間を移動します。
    • +
    • 見出し: ページ上の見出し間を移動します。
    • +
    • リンク: ページ上のリンク間を移動します。
    • +
    • フォームコントロール: ページ上のフォームコントロール間を移動します。
    • +
    • 言語: 利用可能な場合は、さまざまな翻訳間を移動します。
    • +
    +
  12. +
  13. 見出しを選択します。これで、上下にスワイプしてページ上の見出し間を移動できます。
  14. +
+ +

注: 利用可能な VoiceOver ジェスチャおよび iOS でのアクセシビリティテストに関するその他のヒントを網羅した詳細なリファレンスについては、VoiceOver を使用してデバイスのアクセシビリティをテストする(英語)を参照してください。

+ +

制御機構

+ +

CSS および JavaScript のアクセシビリティの記事では、特定の種類の制御機構に固有のイベントの概念を調べました(マウスに特有のイベントを参照)。要約すると、他の制御機構は関連する機能をアクティブにできないため、これらはアクセシビリティの問題を引き起こします。

+ +

例えば、click イベントはアクセシビリティの点で優れています — 関連付けられているイベントハンドラは、ハンドラが設定されている要素をクリックするか、タブ移動して Enter / Return キーを押すか、タッチスクリーンデバイスでタップすることで起動できます。simple-button-example.html の例を試してみてください(ライブで動いているのを見る)。

+ +

あるいは、mousedownmouseup のようなマウス固有のイベントは問題を引き起こします — それらのイベントハンドラはマウス以外の制御を使って呼び出すことはできません。

+ +

キーボードまたはタッチで、simple-box-drag.html の例を制御しようとすると、問題が発生します(ライブで例を見る)。これは、次のようなコードを使用しているために発生します。

+ +
div.onmousedown = function() {
+  initialBoxX = div.offsetLeft;
+  initialBoxY = div.offsetTop;
+  movePanel();
+}
+
+document.onmouseup = stopMove;
+ +

他の形式の制御を有効にするには、異なるが同等のイベントを使用する必要があります — 例えば、タッチイベントはタッチスクリーンデバイスで機能します。

+ +
div.ontouchstart = function(e) {
+  initialBoxX = div.offsetLeft;
+  initialBoxY = div.offsetTop;
+  positionHandler(e);
+  movePanel();
+}
+
+panel.ontouchend = stopMove;
+ +

マウスイベントとタッチイベントを一緒に使用する方法を示す簡単な例を示しました — multi-control-box-drag.html を参照してください(この例もライブで見てください)。

+ +

: ゲーム制御機構の実装では、さまざまな制御機構を実装する方法を示す完全に機能する例も見ることができます。

+ +

レスポンシブデザイン

+ +

レスポンシブデザインは、画面のサイズや解像度などの要因に応じて、レイアウトやその他のアプリの機能を動的に変更することです。だから、さまざまなデバイスタイプのユーザーにとって使用可能でアクセス可能です。

+ +

特に、モバイルに関して対処する必要がある最も一般的な問題は次のとおりです。

+ + + +

: レスポンシブデザインのテクニックについては、MDN の他の場所で説明されているため、ここでは詳しく説明しません(上記のリンクを参照)。

+ +

特定のモバイルに関する考慮事項

+ +

モバイルでサイトにアクセスしやすくするために考慮すべき他の重要な問題があります。ここにその一部を列挙しましたが、私たちがそれらを考えるときにはさらに追加します。

+ +

ズームを無効にしない

+ +

ビューポートを使用すると、ズームを無効にすることができます。常にリサイズ可能にして、{{htmlelement("head")}} で端末の幅にあわせるにはこうします:

+ +
<meta name="viewport" content="width=device-width; user-scalable=yes">
+ +

なるべくuser-scalable=no とはセットしないでください — 多くの人があなたのウェブサイトのコンテンツを見るためにズームに頼るので、この機能を奪うことは本当に悪い考えです。ズーミングによって UI が壊れる場合があります。そのような場合、絶対にズームを無効にする必要があると感じる場合は、UI を壊さないようにテキストサイズを大きくするためのコントロールのような、他の同等の機能を提供するべきです。

+ +

メニューにアクセスしやすくする

+ +

モバイルデバイスでは画面が非常に狭いため、メディアクエリやその他の技術を使用して、ナビゲーションメニューをディスプレイ上部の小さなアイコンに縮小するのがとても一般的です — これは一般的に「3本の水平線」アイコンで表され、デザインパターンでは「ハンバーガーメニュー」と呼ばれています — サイトがモバイルで表示されるときに必要です。

+ +

そのようなメニューを実装するときは、上記の制御機構で説明したように、それを明らかにするためのコントロールは適切な制御機構(通常はモバイル用タッチ)でアクセスできること確認する必要があります。また、メニューの操作中に混乱しないように、メニューにアクセスしている間はページの残りの部分が邪魔にならないように移動するか、何らかの方法で非表示にします。

+ +

良いハンバーガーメニューの例(ドイツ語)を参照してください。

+ +

ユーザー入力

+ +

モバイルデバイスでは、データを入力することは、デスクトップコンピューター上の同等の経験よりもユーザーにとってより面倒なことが多いです。タッチスクリーンの仮想キーボードや小型のモバイル物理キーボードよりも、デスクトップやラップトップのキーボードを使用してテキストをフォーム入力に入力する方が便利です。

+ +

このため、必要なタイピングの量を最小限に抑えることを試みる価値があります。例として、通常のテキスト入力を使用して毎回ユーザーに役職を記入させるのではなく、最も一般的な選択肢を含む <select> メニューを提供できます(データ入力の一貫性を保つのにも役立ちます)。そして、それ以外の値を入力するテキストフィールドを表示する「その他」選択肢を提供できます。common-job-types.html で、このアイデアの簡単な例を実際に見ることができます(一般的な仕事の例をライブで見る)。

+ +

モバイルプラットフォームでの日付などの HTML5 フォームの入力タイプを使用することも考慮する価値があります。例えば、Android と iOS の両方で、デバイスエクスペリエンスに適した使用可能なウィジェットが表示されます。いくつかの例については html5-form-examples.html を参照してください(HTML5 フォームの例をライブで見る) - これらをモバイルデバイスでロードして操作してみてください。例えば、

+ + + +

デスクトップとは別の解決策を提供したい場合は、機能検出を使用して、モバイルデバイスに常に別のマークアップを提供できます。さまざまな入力タイプの検出に関する生の情報については入力タイプ(英語)を参照してください。また、より多くの情報については機能検出の記事をチェックしてください。

+ +

まとめ

+ +

この記事では、モバイルのアクセシビリティ固有の一般的な問題とその解決方法について詳しく説明しました。また、アクセシビリティテストを支援するために、最も一般的なスクリーンリーダーの使い方を紹介しました。

+ +

関連情報

+ + + +
{{PreviousMenuNext("Learn/Accessibility/Multimedia","Learn/Accessibility/Accessibility_troubleshooting", "Learn/Accessibility")}}
+ +
+

このモジュール内の文書

+ + +
diff --git a/files/ja/learn/accessibility/multimedia/index.html b/files/ja/learn/accessibility/multimedia/index.html new file mode 100644 index 0000000000..e79aa9a6e9 --- /dev/null +++ b/files/ja/learn/accessibility/multimedia/index.html @@ -0,0 +1,371 @@ +--- +title: アクセシブルマルチメディア +slug: Learn/Accessibility/Multimedia +tags: + - Accessibility + - Article + - Audio + - Beginner + - CodingScripting + - HTML + - Images + - JavaScript + - Learn + - Multimedia + - Video + - captions + - subtitles + - text tracks +translation_of: Learn/Accessibility/Multimedia +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Accessibility/WAI-ARIA_basics","Learn/Accessibility/Mobile", "Learn/Accessibility")}}
+ +

アクセシビリティの問題を引き起こす他のカテゴリーは、マルチメディアでです。ビデオ、オーディオ、画像といったコンテンツは、支援技術 (assistive technologies) とユーザーが理解可能となる適切な代替テキストを必要とします。この記事ではその方法を説明します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、HTML 、CSS 、JavaScript に対する基本的な理解、 前回の記事 の理解
学習目標:マルチメディアが引き起こすアクセシビリティの問題、およびその解決方法を理解すること
+ +

マルチメディアとアクセシビリティ

+ +

このモジュールまで、様々なコンテンツに対してそのアクセシビリティを保証するために何が必要かを見てきました。シンプルな文章から始まって、データテーブル、画像、フォーム要素やボタンといったネイティブのコントロール、より複雑なマークアップ構造 (WAI-ARIA 属性) などです。

+ +

一方こちらの記事は、アクセシビリティの保証が難しい別のマルチメディアのコンテンツ群について扱っています。画像、ビデオ、{{htmlelement("canvas")}} 要素、Flash 動画などは、スクリーンリーダーによる理解やキーボードによるナビゲーションが容易ではないため、私たちが手を差し伸べる必要があります。

+ +

ですが絶望はしないでください。ここではマルチメディアをアクセシブルにするために利用できる技術について紹介し、あなたの手助けをします。

+ +

シンプルな画像

+ +

私達は既に HTML: アクセシビリティの基礎 で HTML 画像のシンプルな代替テキストについてカバーしました — 詳細を確認するために、そこに戻っても良いです。簡単に言うと、ビジュアルコンテンツとなり得るものは、スクリーンリーダーがユーザーのために読み上げることができるよう、代替テキストが利用可能であることを保証するべきです。

+ +

例えば:

+ +
<img src="dinosaur.png"
+     alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
+
+ +

アクセシブルなオーディオとビデオコントロール

+ +

ウェブベースのオーディオ/ビデオのコントロールを実装するのは問題にはならないはずですよね?調べてみましょう。

+ +

ネイティブ HTML5 コントロールの問題

+ +

HTML5 の video と audio インスタンスは、ビルトインのコントロールと一緒に提供されており、何も設定せずにメディアの制御を行うことができます。例えば (native-controls.html ソースコード実際の動作を参照):

+ +
<audio controls>
+  <source src="viper.mp3" type="audio/mp3">
+  <source src="viper.ogg" type="audio/ogg">
+  <p>Your browser doesn't support HTML5 audio. Here is a <a href="viper.mp3">link to the audio</a> instead.</p>
+</audio>
+
+<br>
+
+<video controls>
+  <source src="rabbit320.mp4" type="video/mp4">
+  <source src="rabbit320.webm" type="video/webm">
+  <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
+</video>
+ +

control 属性は、あなたがメディアプレイヤーに対して期待する再生/一時停止ボタンやシークバーといった基本的なコントロールを提供します。Firefox と Chrome では次のように表示されます。

+ +

Screenshot of Video Controls in Firefox

+ +

Screenshot of Video Controls in Chrome

+ +

しかし、これらのコントロールには問題があります:

+ + + +

これを改善するために、私たちは自分たちのカスタムコントロールを作成することができます。どのようにするのか見てみましょう。

+ +

カスタム audio/video コントロール

+ +

HTML5 の video と audio は HTML メディア要素という API を提供しています。これは、あなたが定義したボタンや他のコントロールにカスタム機能をマップすることを可能にします。

+ +

上の video を例として、カスタムコントロールを追加してみましょう。

+ +

基本のセットアップ

+ +

はじめに、custom-controls-start.html、 custom-controls.css, rabbit320.mp4、そして rabbit320.webm のコピーを取得し、あなたのハードドライブのディレクトリーに保存します

+ +

main.js というファイルを新規作成し、同じディレクトリーに保存します。

+ +

最初に、ビデオプレイヤーの HTML を見てみましょう。HTML の中は次のようになっています:

+ +
<section class="player">
+  <video controls>
+    <source src="rabbit320.mp4" type="video/mp4">
+    <source src="rabbit320.webm" type="video/webm">
+    <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
+  </video>
+
+  <div class="controls">
+    <button class="playpause">Play</button>
+    <button class="stop">Stop</button>
+    <button class="rwd">Rwd</button>
+    <button class="fwd">Fwd</button>
+    <div class="time">00:00</div>
+  </div>
+</section>
+ +

JavaScript の基本セットアップ

+ +

私たちは video の下にいくつかの簡単なボタンを挿入しました。もちろん、このままではこれらのコントロールは何もしません。機能を加えるためには JavaScript を使います。

+ +

まずはそれぞれのコントロールの設定を保持しておく必要があります。JavaScript ファイルの先頭に次のコードを追加してください:

+ +
const playPauseBtn = document.querySelector('.playpause');
+const stopBtn = document.querySelector('.stop');
+const wdBtn = document.querySelector('.rwd');
+const fwdBtn = document.querySelector('.fwd');
+const timeLabel = document.querySelector('.time');
+ +

次に、video/audio プレイヤー自身の参照を取得する必要があります。次の行を先ほどのコードの下に加えてください:

+ +
const player = document.querySelector('video');
+ +

これは {{domxref("HTMLMediaElement")}} オブジェクトへの参照を保持します。このオブジェクトは、私たちのボタンに機能を紐づけるために使用可能ないくつかの便利なプロパティやメソッドを持っています。 

+ +

私たちのボタンの機能を作る前に、カスタムコンロールの邪魔にならないようネイティブコントロールを削除しましょう。JavaScript の下に次のコードを追加してください:

+ +
player.removeAttribute('controls');
+ +

最初から controls 属性を含めないようにするのではなく、わざわざこのようにするのには理由があります。もし JavaScript コードが何らかの理由で失敗しても、ユーザーは利用可能な何かしらのコントロールを使うことができるのです。

+ +

ボタンを紐つける

+ +

最初に、再生/一時停止ボタンをセットアップしましょう。次のように、再生と一時停止をシンプルな条件によって切り替えることで、この機能を実現できます。これをあなたのコードの下に追加しましょう:

+ +
playPauseBtn.onclick = function() {
+  if(player.paused) {
+    player.play();
+    playPauseBtn.textContent = 'Pause';
+  } else {
+    player.pause();
+    playPauseBtn.textContent = 'Play';
+  }
+};
+ +

次に、ストップボタンを制御する次のコードを下に追加しましょう:

+ +
stopBtn.onclick = function() {
+  player.pause();
+  player.currentTime = 0;
+  playPauseBtn.textContent = 'Play';
+};
+ +

{{domxref("HTMLMediaElement")}} には stop() 関数がありません。そこで pause() 関数を使用し、同時に currentTime に 0 を設定します。

+ +

続いて、巻き戻しと早送りボタンです。次のブロックをあなたのコードの下に追加してください:

+ +
rwdBtn.onclick = function() {
+  player.currentTime -= 3;
+};
+
+fwdBtn.onclick = function() {
+  player.currentTime += 3;
+  if(player.currentTime >= player.duration || player.paused) {
+    player.pause();
+    player.currentTime = 0;
+    playPauseBtn.textContent = 'Play';
+  }
+};
+ +

これらはとてもシンプルで、クリックされる度に currentTime 単に 3 秒を足すか引くだけです。実際のビデオプレイヤーでは、あなたはもっと手の込んだものを作りたいでしょう。

+ +

早送りボタンが押されたとき、  currentTime がメディアのトータルの duration よりも大きいか、そしてメディアが再生されていないかをチェックするという点についても気をつけてください。もしいずれかの条件が満たされているなら、ビデオが再生されていない時に早送りしようとしてもおかしくならないよう、単純にビデオを停止するか、ビデオの最後まで飛ばします。

+ +

最後に、再生時間を表示するために次の内容をコードの最後に追加します:

+ +
player.ontimeupdate = function() {
+  let minutes = Math.floor(player.currentTime / 60);
+  let seconds = Math.floor(player.currentTime - minutes * 60);
+  let minuteValue;
+  let secondValue;
+
+  if (minutes<10) {
+    minuteValue = "0" + minutes;
+  } else {
+    minuteValue = minutes;
+  }
+
+  if (seconds<10) {
+    secondValue = "0" + seconds;
+  } else {
+    secondValue = seconds;
+  }
+
+  mediaTime = minuteValue + ":" + secondValue;
+  timeLabel.textContent = mediaTime;
+};
+ +

時間が更新される度に (1秒に一度) 、この関数を実行します。これは秒として渡された currentTime の値 (秒で与えられる) から分と秒の数を算定するもので、もし分か秒の値が 10 以下であれば先頭に 0 を追加し、表示用の値を生成して時間ラベルに追加します。 

+ +

参考記事

+ +

ここでは、video/audio プレイヤーに対してどのようにカスタムしたプレイヤー機能を加えるかという基本的なアイデアが得られます。video/audio プレイヤーに対して、古いブラウザーでの Flash のフォールバックも含めて、より複雑な機能を加えるには、以下のリンク先を参照してください:

+ + + +

さらに私たちは、あなたがどのようにしてオブジェクト指向システムを作ることができるかを見せるために高度な例も作りました。これは、ページ内のすべての video と audio プレイヤーを見つけ (どれだけ存在していたとしても)、私たちのカスタムコントロールを追加するものです。custom-controls-oojs を見てください (ソースコードも見てください) 。

+ +

オーディオトランスクリプト(Audio transcripts)

+ +

聴覚障害の方にオーディオコンテンツを提供する場合、トランスクリプトのテキストを必ず用意する必要があります。これらは同じページの中に何らかの形で含んでも良いですし、リンクされた別ページに用意することもできます。

+ +

トランスクリプトを実際に作成する際は、次の選択肢があります。

+ + + +

人生の多くのものがそうであるように、あなたは支払った分相応のものを手に入れます。つまり、サービスが異なれば、トランスクリプト作成に要する時間と正確さが異なるということです。文字起こしをするために信頼できる会社や AI サービスにお金を払えば、正確なトランスクリプトを早く入手できるでしょう。料金を払いたくないのであれば、遅く、質の低いものになりやすいです。

+ +

オーディオリソースを公開するがトランスクリプトは後で提供する、という約束は良いものではありません。そのような約束は大抵守られず、ユーザーとの間にある信頼を損なってしまいます。もしオーディオが対面ミーティングやライブスピーチのようなものであるならば、それらが行われている間にノートを取り、オーディオと共に公開して、後からまとめ上げるということはできるでしょう。

+ +

トランスクリプト例

+ +

もしあなたが自動サービスを使用しているならば、おそらくツールが提供しているユーザーインターフェイスを使用する必要があるでしょう。例えば、Wait, ARIA Roles Have Categories?  を見て、 3点メニュー (. . .) > Show Transcript を選択してください。トランスクリプトは別のパネルに表れるでしょう。

+ +

オーディオとそのトランスクリプトを表示するユーザーインターフェイスを自身で作成する場合、あなたのが考える形で作ることができますが、表示/非表示が可能なパネルを含むと良いかもしれません。私たちの audio-transcript-ui の例を見てください。 (ソースコード も見てください).

+ +

オーディオの説明

+ +

オーディオに伴った映像がある場合、追加のコンテンツを描写するためにオーディオの説明を提供する必要があるでしょう。

+ +

多くの場合これはビデオの形を取り、この章の次のセクションで説明されるテクニックを使用してキャプションを埋め込むことができます。

+ +

しかし、いくつかのエッジケースもあります。例えば、スプレッドシートやグラフの資料を使用したミーティングの録音オーディオがあるかもしれません。その場合、それらの資料がオーディオとトランスクリプトとともに提供されていることを確認するべきであり、特にトランスクリプトの中でそれらの資料に言及されている箇所をリンクとすることが大事です。これは聴覚障害の方だけでなく、すべてのユーザーの助けになります。

+ +
+

: オーディオトランスクリプトは、一般的に様々なユーザーグループを助けます。聴覚障害の人へオーディオに含まれたコンテンツにアクセスを提供するように、オーディオをダウンロードすることが困難な狭い帯域のユーザーのことを考えて見ましょう。パブやバーのような騒音の多い環境で、雑音のためにオーディオを聞くことが難しいユーザーのことも考えて見ましょう。

+
+ +

ビデオテキストトラック

+ +

聴覚障害者、視覚障害者、そして他のユーザー (狭い帯域のユーザーや、ビデオで使用される言語を話さないユーザー) にとってビデオをアクセシブルにするために、ビデオコンテンツにテキストトラックを含める必要があります。

+ +
+

: テキストトラックは障害者だけでなく他のユーザーにとっても便利になる可能性があります。例えば、うるさい環境 (スポーツ中継を流している混雑したバーなど) にいるためにオーディオが聞こえないユーザーや、他の人を邪魔したくない静かな場所 (図書館など) にいるユーザーなどです。

+
+ +

これは新しいコンセプトではありません — テレビ放送では、かなり長い間クローズドキャプションを提供しています:

+ +

Frame from an old-timey cartoon with closed captioning "Good work, Goldie. Keep it up!"

+ +

一方で、多くの国では英語の映画を自国の母語の字幕とともに提供していて、DVD では他の言語の字幕も利用可能となっています。

+ +

An English film with German subtitles "Emo, warum erkennst du nicht die Schonheit dieses Ortes?"

+ +

テキストトラックには、目的に応じた様々な種類のものがあります。あなたが接する主な種類は、次のものです:

+ + + +

HTML5 ビデオテキストトラックの実装

+ +

HTML5 のビデオで表示されるテキストトラックは、WebVTT で記述される必要があります。これは、テキストの文字列とメタデータを含むテキストフォーマットであり、テキストが表示されるべき時間や、スタイル、ポジションといった情報まで含みます。これらの文字列はキュー (cues) と呼ばれます。

+ +

典型的な WebVTT ファイルは、次のようなものです:

+ +
WEBVTT
+
+1
+00:00:22.230 --> 00:00:24.606
+This is the first subtitle.
+
+2
+00:00:30.739 --> 00:00:34.074
+This is the second.
+
+  ...
+ +

HTML のメディア再生と共に表示させるためには、次のことをする必要があります:

+ + + +

例を見てみましょう:

+ +
<video controls>
+    <source src="example.mp4" type="video/mp4">
+    <source src="example.webm" type="video/webm">
+    <track kind="subtitles" src="subtitles_en.vtt" srclang="en">
+</video>
+ +

これは、字幕が表示されたビデオとなり、次のようになります:

+ +

Video player with standard controls such as play, stop, volume, and captions on and off. The video playing shows a scene of a man holding a spear-like weapon, and a caption reads "Esta hoja tiene pasado oscuro."

+ +

詳細は Adding captions and subtitles to HTML5 video を読んでください。あなたは、GitHub で GIan Devlin によって作られたをこの記事と併せて見ることができます。(source ソースコード も見てください) この例では JavaScript を使用して、ユーザーが異なる言語の字幕を選択できるようになっています。字幕を表示するためには、"CC" ボタンをクリックして英語、ドイツ語、スペイン後のオプションを選択する必要があります。

+ +
+

: テキストトラックは {{glossary("SEO")}} でも役に立ちます。検索エンジンはテキストによって更新されるためです。検索エンジンは、テキストトラックによってビデオの途中に直接リンクすることさえできます。

+
+ +

その他のマルチメディアコンテンツ

+ +

上のセクションでは、あなたがウェブページに載せたいかもしれないすべての種類のマルチメディアコンテンツをカバーしていません。また、ゲーム、アニメーション、スライドショー、埋め込まれたビデオ、そして他の利用可能なテクノロジーを利用して作られたコンテンツを扱う必要があるかもしれません。例えば:

+ + + +

そのようなコンテンツには、アクセシビリティの懸念事項とケースバイケースで対応する必要があります。いくつかのケースでは、これはそれほど悪いことではありません。例えば:

+ + + +

しかし、他のマルチメディアはアクセシブルにすることがそう簡単ではありません。例えば、没入型 3D ゲームやバーチャルリアリティアプリを扱っている場合、そのような体験に対して代替テキストを提供することは非常に困難であるし、盲目のユーザーはそのようなアプリのターゲットに当てはまらないと考えるかもしれません。

+ +

しかしそのようなアプリでも、視力や色覚に問題を抱えるユーザーにとって認識できるよう、カラーコントラストや表示の明瞭さが十分であるかどうか、そしてキーボードからアクセス可能であるかを確かめることはできます。アクセシビリティは、100% を常に目指すというよりは、可能な限り行うものであるということを覚えておいてください。100% は大抵不可能なのです。

+ +

まとめ

+ +

このチャプターでは、マルチメディアにおけるアクセシビリティの関心ごとの要約をいくつかの実践的なソリューションと共に提供しました。

+ +

{{PreviousMenuNext("Learn/Accessibility/WAI-ARIA_basics","Learn/Accessibility/Mobile", "Learn/Accessibility")}}

+ +

このモジュール内の文書

+ + + + diff --git a/files/ja/learn/accessibility/wai-aria_basics/index.html b/files/ja/learn/accessibility/wai-aria_basics/index.html new file mode 100644 index 0000000000..778b3ed1fe --- /dev/null +++ b/files/ja/learn/accessibility/wai-aria_basics/index.html @@ -0,0 +1,434 @@ +--- +title: WAI-ARIAの基本 +slug: Learn/Accessibility/WAI-ARIA_basics +tags: + - ARIA + - Accessibility + - Article + - Beginner + - CodingScripting + - Guide + - HTML + - JavaScript + - Learn + - WAI-ARIA + - semantics + - アクセシビリティ + - セマンティクス + - 初心者 + - 学習 +translation_of: Learn/Accessibility/WAI-ARIA_basics +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Accessibility/CSS_and_JavaScript","Learn/Accessibility/Multimedia", "Learn/Accessibility")}}
+ +

前回の記事に続いて言えることですが、意味論的ではない HTML や JavaScript によって更新される動的なコンテンツを含むような、複雑な UI コントロールの作成は難しくなることがあります。 WAI-ARIA は、ブラウザーや支援技術が認識できるさらなる意味論を追加することによってそのような問題に対処し、ユーザーの理解を助ける技術です。 ここでは、アクセシビリティを向上させるための基本的な使い方を説明します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、 HTML 、 CSS 、 JavaScript に対する基本的な理解、 前回までの記事に対する理解
学習目標:WAI-ARIA、および、アクセシビリティを向上させるために必要に応じて有用な追加の意味論を提供する方法について知識を得ること
+ +

WAI-ARIA って何?

+ +

まずは、WAI-ARIA とは何か、そして何ができるのかという点から始めましょう。

+ +

全く新しい問題

+ +

ウェブアプリがより複雑で動的なものになると、新しいアクセシビリティの機能と問題が明らかになってきます。

+ +

例えば、 HTML5 は普遍的なページの機能を定義するためにいくつもの意味論的要素を取り入れました({{htmlelement("nav")}} 、 {{htmlelement("footer")}} 等)。 これらが利用可能になる以前は、開発者は  <div class="nav"> のように単に {{htmlelement("div")}} を ID や class と共に使っていましたが、メインナビゲーションのようなページ内の機能をプログラムで識別する簡単な方法が無いために問題がありました。

+ +

初期の解決方法は、ナビゲーションへとリンクさせるため、次のようにページ上部に1つ以上の隠しリンク(もしくは他の何か)を追加することでした。

+ +
<a href="#hidden" class="hidden">Skip to navigation</a>
+ +

しかしこれは簡潔な方法ではない上に、スクリーンリーダーがページの先頭から読み込む場合にのみ利用できるものでした。

+ +

他の例としては、アプリが日付選択のための日付ピッカーや値選択のためのスライダーなどの複雑なコントロールを使いだしたケースがあります。 HTML5 は、そのようなコントロールを表す特別な入力タイプを提供しています。

+ +
<input type="date">
+<input type="range">
+ +

これらはブラウザー間で十分にサポートされておらず、またスタイル付けすることが非常に困難であるため、ウェブサイトのデザインに合わせる上で不便となります。 結果として、開発者は多くの場合 JavaScript ライブラリを利用して複数のネストされた {{htmlelement("div")}} でそのようなコントロールを生成したり、クラス名を持った表要素に対して CSS によるスタイル付けと JavaScript によるコントロールを行ったりします。

+ +

この場合の問題は、見た目上は動作するものの、スクリーンリーダーはそれらが何なのか全く理解できず、ユーザーには意味を成さないごちゃごちゃの要素であるとしか教えられないという点にあります。

+ +

WAI-ARIA の導入

+ +

WAI-ARIA は W3C によって定められた仕様で、要素に適用できる追加の意味論を提供する一連の HTML 属性を定義しており、それが欠けているどのような場所でもアクセシビリティを向上させます。 この仕様では、主に次の3つの機能があります。

+ + + +

WAI-ARIA 属性の重要な点は、ブラウザーのアクセシビリティ API(スクリーンリーダーはここから情報を取得する)によって提供される情報を除いて、それらはウェブページに何の影響も与えないという点です。 WAI-ARIA はウェブページの構造や DOM に影響を与えませんが、 CSS の要素選択で利用することが可能です。

+ +
+

: WAI-ARIA の仕様で、ARIA ロールの使用方法と追加情報へのリンクを含む便利なリストを確認することができます。 ロールの定義(英語)を見てください。

+ +

この仕様では、プロパティとステートの追加情報を含んだリストも確認することができます。 ステートとプロパティの定義(すべての aria-* 属性)(英語)を見てください。

+
+ +

WAI-ARIA はどこでサポートされていますか?

+ +

この質問に答えるのは簡単ではありません。 次の理由より、どこで、WAI-ARIA のどの機能がサポートされているのかを記述する決定的なリソースを見つけることが難しいためです。

+ +
    +
  1. WAI-ARIA には大量の機能がある。
  2. +
  3. 検討しなければいけないオペレーティングシステム、ブラウザー、スクリーンリーダーの組み合わせが大量にある。
  4. +
+ +

最後の点は重要です。 そもそもスクリーンリーダーを使用するためには、オペレーティングシステムが所定のアクセシビリティ API を持つブラウザーを動作させる必要があり、それはスクリーンリーダーが動作するために必要となる情報を提供しなければいけません。 ほとんどの人気の OS は、スクリーンリーダーが動作可能である1つか2つの所定のブラウザーを持っています。 Paciello Group は、この件に関してほぼ最新のデータを投稿しています — ラフガイド: ブラウザ、オペレーティングシステム、スクリーンリーダーのサポート(英語)を見てください。

+ +

次に、ブラウザーが問題となっている ARIA の機能をサポートしているのか、および API を通してそれらを公開しているのかという点を気にする必要があります。 しかし、スクリーンリーダーがそれらの情報を認識し、ユーザーに有益なやり方で伝えているのかという点もまた気にしなければいけません。

+ +
    +
  1. ブラウザーのサポート状況は概ね良いです。 本記事の執筆時点で、 caniuse.com は全体のブラウザーの WAI-ARIA のサポート状況は 88% だとしています。
  2. +
  3. スクリーンリーダーの ARIA のサポート状況はそこまでではありませんが、多くの一般的なスクリーンリーダーはそれに近いものになってきています。 Powermapper による WAI-ARIA のスクリーンリーダーの互換性(英語)の記事で、サポート状況を確認することができます。
  4. +
+ +

この記事では、全ての WAI-ARIA の機能と詳細についてカバーするわけではありません。 代わりに、あなたが知るべき最も重要な WAI-ARIA の機能についてカバーします。 もしサポートの詳細について何も記述してしない場合は、その機能が十分にサポートされていると想定してください。 この例外がある場合は、明確に記述します。 

+ +
+

: JavaScript ライブラリには WAI-ARIA をサポートしているものがありますが、それはライブラリが複雑なフォームコントロールのような UI を生成した場合に、アクセシビリティを向上させるための ARIA 属性を追加することを意味します。 迅速な UI 開発のためにサードパーティーの JavaScript ライブラリを探しているのであれば、その決断を下す際、UI のアクセシビリティのサポートを重要な要素として必ず考慮すべきです。 良い例としては、 jQuery UI(jQuery UI について: ディープアクセシビリティサポート(英語)を見てください)、 ExtJS 、 Dojo/Dijit があります。

+
+ +

いつ WAI-ARIA を使うべき?

+ +

私達は WAI-ARIA が作られるに至ったいくつかの問題について最初の方で話しましたが、基本的には WAI-ARIA が有用となる4つの主な場面があります。

+ +
    +
  1. 道しるべ/ランドマーク(Signpost/Landmark): ARIA の role 属性の値は、HTML 要素の意味論(例えば {{htmlelement("nav")}})を再現するランドマークとして振る舞ったり、 search 、 tabgroup 、 tab 、 listbox のようにHTML5 の意味論の範囲外となる道しるべ(signpost)を異なる機能エリアに提供することができます。
  2. +
  3. 動的なコンテンツの更新: スクリーンリーダーは、絶えず更新されるコンテンツが得意ではない傾向があります。 ARIA の aria-live を使うことで、 XMLHttpRequest や DOM API を通してコンテンツが更新された場合に、スクリーンリーダーのユーザーに対してそれを伝えることができます。
  4. +
  5. キーボードのアクセシビリティの向上: キーボードのアクセシビリティを最初から持つ HTML 要素がありますが、 JavaScript を使ってそれ以外の要素に同じようなインタラクションをさせる場合、スクリーンリーダーにとって困難が生じます。 こうしなければならない場合、 WAI-ARIA は他の要素に対してフォーカスを得る手段を提供しています(tabindex の使用)。
  6. +
  7. 意味論的ではないコントロールのアクセシビリティ: ネストした一連の <div> が CSS/JavaScript と共に複雑な UI 機能を構成していたり、ネイティブのコントロールが JavaScript によって大きく強化/変更されている場合、アクセシビリティの提供は困難になります。 そこに意味論や手がかりが無ければ、スクリーンリーダーのユーザーはその機能が何をするのか判断するのが難しくなるでしょう。 このような状況では、 button 、 listbox 、または tabgroup といったロールの組み合わせ、もしくは aria-required や aria-posinset などのプロパティにより機能の手がかりを提供することで、 ARIA は足りないものを補うことができます。
  8. +
+ +

一点忘れてはいけないのが、 WAI-ARIA は必要な場合のみ使用するという点です。 理想的には、スクリーンリーダーのユーザーの理解に必要となる意味論の提供は、常に ネイティブの HTML 機能  を使用して行うべきです。 しかし、コードの制御が限定されていたり、 HTML 要素への実装が容易ではない複雑なものを作っているなどの理由で、これが困難となるケースがあります。 そのような場合、 WAI-ARIA はアクセシビリティを向上させる上で価値のあるツールとなります。

+ +

もう一度言いますが、必要な時だけ使ってください!

+ +
+

: 実際のさまざまなユーザーによってあなたのサイトをテストすることも忘れないでください — 障害のないユーザー、スクリーンリーダーを使用するユーザー、キーボードナビゲーションを使用するユーザーなどです。 どれだけうまく動作するかという点で、彼らはあなたよりもうまく観察してくれるでしょう。 

+
+ +

実際的な WAI-ARIA の実装

+ +

次のセクションでは、実際の例と共に、より詳細な4つのエリアを見てみます。 続行する前に、これから見る例をテストできるように、スクリーンリーダーのテスト環境を用意してください。 

+ +

詳細は スクリーンリーダーのテスト を確認してください。

+ +

道しるべ/ランドマーク(Signpost/Landmark)

+ +

WAI-ARIA は role 属性(英語)をブラウザーに追加することで、必要に応じてあなたのサイトに付加的な意味論的価値を追加することができます。 これが有用となる最初の領域は、スクリーンリーダーのユーザーが共通のページ要素を見つけることができるようになる情報の提供です。 例を見てみましょう。私達の website-no-roles の例(実際の動作)は、次の構造を持っています。

+ +
<header>
+  <h1>...</h1>
+  <nav>
+    <ul>...</ul>
+    <form>
+      <!-- search form  -->
+    </form>
+  </nav>
+</header>
+
+<main>
+  <article>...</article>
+  <aside>...</aside>
+</main>
+
+<footer>...</footer>
+ +

もしあなたがモダンなブラウザーでスクリーンリーダーのテストをした場合、いくつかの有用な情報を手に入れるでしょう。 例えば、 VoiceOver は次の内容を読み上げます:

+ + + +

VoiceOver の Landmarks メニューを見ると(VoiceOver キー + U でアクセスし、矢印キーでメニューを選択する)、多くの要素が素早くアクセスできるように綺麗に並んでいることが確認できます。

+ +

+ +

しかし、これは改善することができます。 検索フォームはユーザーが見つけたいと考える重要なランドマークですが、ここでは Landmarks メニューの中に列挙されておらず、検索入力(<input type="search">)であるということ以上に目立つランドマークとしても扱われていません。 加えて、いくつかの古いブラウザー(特に IE8)は HTML5 要素の意味論を認識しません。

+ +

ARIA の機能を使用してこれを改善しましょう。 まず、 HTMLに対していくつかの role 属性を追加します。 私達のオリジナルファイルをコピーするか(index.html と style.css を参照)、 website-aria-roles の例(実際の動作)へ移動すると、次の構造を確認できます。

+ +
<header>
+  <h1>...</h1>
+  <nav role="navigation">
+    <ul>...</ul>
+    <form role="search">
+      <!-- search form  -->
+    </form>
+  </nav>
+</header>
+
+<main>
+  <article role="article">...</article>
+  <aside role="complementary">...</aside>
+</main>
+
+<footer>...</footer>
+ +

この例では、ボーナス機能も提供しています — {{htmlelement("input")}} は aria-label 属性が設定されていますが、これは {{htmlelement("label")}} 要素が含まれていない場合でもスクリーンリーダーによって読み上げられる説明ラベルを設定します。 こういうケースでは、この機能はとても便利です — このような検索フォームはよくあるものであり、簡単に識別できるので、見えるラベルを設定するとデザインを台無しにしてしまうのです。

+ +
<input type="search" name="q" placeholder="Search query" aria-label="Search through site content">
+ +

さて、この例を VoiceOver で見た時、次の改善を確認することができます。

+ + + +

さらに、このサイトは IE8 のような古いブラウザーを使用しているユーザーにとってもアクセス可能となる可能性が高いので、そのために ARIA ロールを含める価値もあります。 そして、もしあなたのサイトが何らかの理由により <div> のみで構成されているなら、必要な意味論を提供するために確実に ARIA ロールを含めるべきです!

+ +

改善された検索フォームは、 HTML5 で利用できる意味論以上に ARIA が可能とすることを見せてくれました。 あなたは以下の記事、特に {{anch("Accessibility of non-semantic controls","意味論的でないコントロールのアクセシビリティ")}} のセクションで、より多くの意味論や ARIA のプロパティ/属性が持つ力を見ることがでしょう。 まずは、 ARIA が動的コンテンツの更新をどのように助けるかを見てみましょう。

+ +

動的なコンテンツの更新

+ +

DOM に読み込まれたコンテンツ(本文の内容や、画像の代替テキストなど)はスクリーンリーダーを用いて容易にアクセスできます。 従って、テキストコンテンツで作られた伝統的で静的なウェブサイトを、視覚的ハンディキャップを持つ人々にとってアクセス可能にすることは容易です。

+ +

問題はモダンなウェブアプリが静的なテキストだけを使うことは少ないという点です。 それらは動的に更新されるコンテンツ、すなわち、XMLHttpRequestFetchDOM API などの機構を通してページ全体をリロードすることなく更新を行うコンテンツで構成されることが多いです。 このような箇所はしばしばライブリージョン(live region)と呼ばれます。

+ +

簡単な例を見てみましょう。 aria-no-live.html をご覧ください(もしくは 動作版をご覧ください)。 この例では、ランダムに引用文を表示する1つの箱があります。

+ +
<section>
+  <h1>Random quote</h1>
+  <blockquote>
+    <p></p>
+  </blockquote>
+</section>
+ +

JavaScript が XMLHttpRequest を通して JSON ファイルを読み込みます。 この JSON ファイルには、複数のランダムな引用文とその著者が含まれています。 読み込みの完了後に setInterval() ループを開始し、引用文の表示を10秒ごとに新しいものに切り替えます。

+ +
var intervalID = window.setInterval(showQuote, 10000);
+ +

これは正しく動作しますが、アクセシビリティとしてはよくありません。 コンテンツの更新がスクリーンリーダーに検知されないため、ユーザーは何が起こっているかを知ることができないからです。 これはつまらない例ですが、更新され続けるコンテンツを多く含む複雑な UI をあなたが作ることを想像してください(チャットルームや戦略ゲームの UI、動的に更新されるショッピングカートの表示など)。 ユーザーに更新を知らせる何かしらの手段がない限り、それがどんなに実用的なアプリであっても使いこなすことはできないでしょう。

+ +

幸いなことに WAI-ARIA はそのような通知を行う便利な機構を提供しています。 それが aria-live プロパティです。 このプロパティを要素に適用すると、スクリーンリーダーが更新されたコンテンツを読み上げてくれるようになります。 どのような緊急性をもってコンテンツを読み上げてくれるかは、次のように属性値によって変わります。

+ + + +

aria-no-live.html と quotes.json のコピーを作成し、<section> タグの内容を次のように更新してください。

+ +
<section aria-live="assertive">
+ +

これにより、コンテンツの更新があった際にスクリーンリーダーがその内容を読み上げてくれるようになります。

+ +
+

: file:// URL をもつページから XMLHttpRequest を呼び出そうとするとほとんどのブラウザーはセキュリティ例外を投げます。 例えば、(ダブルクリックなどにより)ファイルを直接ブラウザーで読み込んだ場合に file:// URLで開かれます。 動作させるためには、 ウェブサーバー(GitHub を利用するなど)やローカルウェブサーバー(Python の SimpleHTTPServer(英語)など)にファイルをアップロードする必要があります。

+
+ +

加えて、考慮すべきことがあります。 テキストの更新された部分だけを読み上げるべきかどうかです。 常に見出し全体を読み上げる方が、何を読み上げられているかをユーザーが認識できるという点で望ましいかもしれません。 その対象に aria-atomic プロパティを追加することで、このような動作を得ることができます。 手元の <section> タグを再度更新して、次のようにしてください。

+ +
<section aria-live="assertive" aria-atomic="true">
+ +

この aria-atomic="true" 属性が、更新された一部分だけではなく、要素全体のコンテンツを1つのまとまりとして読み上げるようスクリーンリーダーに伝えます。

+ +
+

: 完成した例は aria-live.html をご覧ください(もしくは動作版をご覧ください)。

+
+ +
+

: aria-relevant プロパティはライブリージョンが更新された際に何が読み上げられるかを制御するのに非常に役に立ちます。 例えば、追加や削除をされた内容だけを読み上げさせることもできます。

+
+ +

キーボードでのアクセシビリティの拡張

+ +

このモジュールの他の箇所でも何度か言及したように、アクセシビリティという観点での HTML がもつ重要な能力の1つが、キーボードでのアクセシビリティが組み込まれていることです。 キーボードから、ボタンやフォームコントロール、リンクなどの機能にアクセスできます。 一般的に、タブキーでコントロール間を移動したり、エンター/リターンキーでコントロールの選択や活性化をしたり、必要に応じたその他の制御(例えば、上下矢印キーでの <select> ボックス内のオプション間の移動)ができます。

+ +

しかし、時には(ボタンや他のタイプのコントロールとして)意味論的でない要素や正しい用途ではないフォーカス可能な要素を利用するコードを書かざるをえないこともあるでしょう。 あなたが引き継いだ作りの悪いコードを修正したり、そのようなコードを必要とする複雑なウィジェットを作ったりする場合があるかもしれません。

+ +

フォーカスできないコードをフォーカス可能にするために、WAI-ARIA では tabindex 属性を拡張して次のようにいくつかの値を加えています。

+ + + +

より詳細な議論や典型的な実装例については、HTML のアクセシビリティに関する記事 —  キーボード・アクセシビリティを呼び戻すように盛り込む をご覧ください。

+ +

意味論的でないコントロールのアクセシビリティ

+ +

このセクションの内容は前セクションの続きです。 多くの入れ子になった <div> 要素と CSS/JavaScript を利用して複雑な UI 機能を構築した場合、また、JavaScript で本来のコントロールの機能を拡張/改変した場合を考えてみましょう。 そのようなときには、キーボードでのアクセシビリティが損なわれるだけでなく、スクリーンリーダーのユーザーが各機能のふるまいを理解することは何らかの意味論や手がかりがない限り困難となってしまう。 そのような状況においても、ARIA はそこにあるべき意味論を補足する手助けができます。

+ +

フォーム検査とエラー警告

+ +

まず、CSS と JavaScript のアクセシビリティ の記事で最初に見たフォームの例を再検討しましょう(完全なまとめを再び見るには、ひかえめに保つこと をお読みください)。 フォームを送信しようとした際に検査エラーがあると現れるエラーメッセージ・ボックスにいくつかの ARIA 属性を含めたことを、そのセクションの末尾で示しておきました。

+ +
<div class="errors" role="alert" aria-relevant="all">
+  <ul>
+  </ul>
+</div>
+ + + +

ARIA を使用して、更に先へ踏み込むこともできるでしょうし、なんらかの検査の手助けを更に提供することもできるでしょう。 そもそもフィールドが必須かどうかを示すことや、年齢がどの範囲にあるべきかを示すこと、などはいかがでしょうか?

+ +
    +
  1. いまの時点で、form-validation.htmlvalidation.js のファイルのコピーをとり、それをローカル・ディレクトリに保存してください。
  2. +
  3. 両ファイルをテキストエディタで開き、コードがどのように動くのかを見てください。
  4. +
  5. まず始めに、<form> 開始タグのすぐ上に次のような段落を加えるとともに、フォームの <label> には、両方ともアスタリスクの印をつけてください。 これは、晴眼者ユーザー用に必須フィールドに印をつける通常の方法です。 +
    <p>Fields marked with an asterisk (*) are required.</p>
    +訳: <p>アスタリスク(*)が付いているフィールドは必須です。</p>
    +
  6. +
  7. これは視覚的に意味をなしますが、スクリーンリーダーのユーザーにとっては、理解するのがそれほど容易ではありません。 さいわい、WAI-ARIA には、フォーム入力欄を埋める必要があることをユーザーに伝えるべきだとスクリーンリーダーにヒントを与えるための、aria-required 属性があります。 <input>  要素を次のように更新してください。 +
    <input type="text" name="name" id="name" aria-required="true">
    +
    +<input type="number" name="age" id="age" aria-required="true">
    +
  8. +
  9. この例をここで保存してスクリーンリーダーでテストしてみれば、「Enter your name star, required, edit text(名前を入れてください 星、必須、テキストを編集)」のようなものを聞くことになるはずです。
  10. +
  11. 年齢の値がどうあるべきかについて、スクリーンリーダーのユーザーと晴眼者のユーザーに知らせるのも、有用かもしれません。 これはツールチップとして提示されることがよくあり、あるいは、フォームのフィールド内部のプレースホルダーとして提示されることも、多分あります。 最小値と最大値を指定するための aria-valuemin プロパティと aria-valuemax プロパティを、WAI-ARIA は確かに含んではいますが、これらのプロパティは、今のところそれほどちゃんとサポートされてはいないようです。 よりちゃんとサポートされている機能は、HTML5 の placeholder 属性です。 これは、何の値も入力されていないときに入力欄の中に表示されるメッセージを含むことができ、多くのスクリーンリーダーにより読み上げられます。 数値入力欄を次のように更新してください。 +
    <input type="number" name="age" id="age" placeholder="Enter 1 to 150" aria-required="true">
    +
  12. +
+ +
+

: この完成した例を、form-validation-updated.html においてライブ版で見られます。

+
+ +

また、古典的な {{htmlelement("label")}} 要素以上の、ある種の先進的なフォームのラベルづけ技法も、WAI-ARIA によって可能になります。 晴眼者のユーザーに対してラベルを可視にしたくない箇所にラベルを設けるために aria-label プロパティを使うことについては、すでに述べました(上記の {{anch("SignpostsLandmarks", "道しるべ/ランドマーク(Signpost/Landmark)")}} のセクションを参照)。 別のプロパティを使う別のラベルづけ技法も、いくつかあります。 例えば、非 <label> 要素をラベルとして指定したいとき、または、同じラベルで複数のフォーム入力欄にラベルづけをしたいときに aria-labelledby を使うとか、別の情報をフォーム入力欄に関連づけてその情報も同様に読み上げさせたいときに aria-describedby を使うとかいったものです。 より詳しくは、WebAIM の 高度なフォームのラベル付け(英語)の記事を参照してください。

+ +

フォーム要素の状態を示すための有用なプロパティやステートは、ほかにもたくさんあります。 例えば、フォーム・フィールドが無効化されていることを示すには、aria-disabled="true" が使えます。 多くのブラウザーは、無効化されたフォーム・フィールドを単に飛ばすだけでしょうし、無効化されたフォーム・フィールドは、スクリーンリーダーに読み上げられることすらないでしょう。 しかし、無効化されたフォーム・フィールドが認識される場合もあるでしょう。 ですから、無効化されている入力欄が実際に無効化されているのだ、とスクリーンリーダーに知らせるために、この(aria-disabled="true" という)属性を含めておくことは、良い考えです。

+ +

もし入力欄の無効化ステートが変化する可能性が高いなら、その変化が起きた時点と、その結果どうなったのかを示すことも、良い考えです。 例えば、form-validation-checkbox-disabled.html  のデモには、チェックされると他のフォーム入力欄への更なる情報の入力を可能とするようなチェックボックスがあります。 次のように隠しライブリージョンを設定してあります。

+ +
<p class="hidden-alert" aria-live="assertive"></p>
+ +

これは、絶対的位置指定を使って、視界からは隠してあります。 これがチェックされたり、これのチェックが外されたりすると、このチェックボックスのチェックの結果がどうなったのかをスクリーンリーダーのユーザーに伝えるために、aria-disabled ステートやいくつかの視覚的表示を更新するだけでなく、この隠しライブリージョン内部のテキストも更新します。

+ +
function toggleMusician(bool) {
+  var instruItem = formItems[formItems.length-1];
+  if(bool) {
+    instruItem.input.disabled = false;
+    instruItem.label.style.color = '#000';
+    instruItem.input.setAttribute('aria-disabled', 'false');
+    hiddenAlert.textContent = 'Instruments played field now enabled; use it to tell us what you play.';
+  } else {
+    instruItem.input.disabled = true;
+    instruItem.label.style.color = '#999';
+    instruItem.input.setAttribute('aria-disabled', 'true');
+    instruItem.input.removeAttribute('aria-label');
+    hiddenAlert.textContent = 'Instruments played field now disabled.';
+  }
+}
+ +

非意味論的なボタンをボタンとして説明する

+ +

この課程の中で既に二、三回、ボタンやリンクやフォーム要素に本来備わったアクセシビリティ(および、ボタンやリンクやフォーム要素の外見を模倣するために他の要素を使うことの背後に隠れた、アクセシビリティの問題)について述べました(HTML アクセシビリティの記事の UI コントロール と、上記の {{anch("Enhancing_keyboard_accessibility", "キーボードでのアクセシビリティの拡張")}} を参照)。
+ 基本的には、多くの場合、tabindex とほんの少しの JavaScript を使えば、それほど問題を生じずにキーボード・アクセシビリティを追加して呼び戻せます。

+ +

しかし、スクリーンリーダーについてはどうでしょうか?  スクリーンリーダーはそれでもまだ、そうした要素をボタンとは見なさないことでしょう。 もし fake-div-buttons.html の例をスクリーンリーダーで試してみれば、見せかけのボタンは「Click me!, group(クリックしてください!、グループ)」のような語句を使って報告されるでしょうし、それは明らかに混乱を招くものです。

+ +

WAI-ARIA ロールを用いてこれを修正できます。 fake-div-buttons.html のローカルコピーを作って、ボタンとしての <div> の各々に role="button" と追加してください。 例えば次のようにします。

+ +
<div data-message="This is from the first button" tabindex="0" role="button">Click me!</div>
+ +

今や、スクリーンリーダーを使ってこれを試してみれば、「Click me!, button(クリックしてください!、ボタン)」のような語句を使ってボタンを報告させることになるでしょう。 ずっと良くなりましたね。

+ +
+

: とはいえ、可能な箇所では正しい意味的要素を使うことの方が常に良いのだ、ということを忘れないようにしてください。 もしボタンを作りたいなら、そして {{htmlelement("button")}} 要素が使えるなら、{{htmlelement("button")}} 要素を使うべきです!

+
+ +

複雑なウィジェットを通じてユーザーを案内する

+ +

非意味論的な要素構造を、標準的な HTML で利用可能な UI 機能以上の一般的な UI 機能——例えば、combobox, slider, tabpanel, tree など——として指定できる、大変多くの他の ロール(英語)があります。 そうしたコントロールをどのようにすればアクセス可能にできるのかについて理解するために、Deque 大学のコード・ライブラリ(英語)で多くの有用な事例を見ることができます。

+ +

わたしたち自身の事例を検討しましょう。 単純で、絶対的位置指定をした、タブ付きのインターフェイス(CSS と JavaScript のアクセシビリティの記事の、ものごとを隠す を参照)へと戻りましょう。 これは、タブ付きの情報ボックスの例ソースコード を参照)の中に見つかります。

+ +

この例は、このままでもキーボード・アクセシビリティに関しては、うまく機能します。 幸いなことに、異なるタブ同士の間でのタブ移動が可能ですし、タブを選択して当該タブの中身を表示することもできます。 また、次の点でもかなりアクセス可能です。 すなわち、たとえ画面上で何が起きているのかが見えないとしても、コンテンツ全体にわたってスクロールすることはできますし、見出しを使って見通しを得ることもできます。 でも、そのコンテンツが何であるのかは、明らかではありません。 スクリーンリーダーは今のところ、そのコンテンツのことを、リンクのリストと、三つの見出しを備えた何らかのコンテンツである、と報告してきます。 スクリーンリーダーは、コンテンツ間にどういう関係があるのかについては、何も知らせてくれません。 コンテンツの構造に関する更なる手がかりをユーザーに与えることは、常に良いことです。

+ +

ものごとを改善するために、わたしたちは、aria-tabbed-info-box.html と呼ばれる、本例の新たなバージョンを作成しました(これがライブ版で動くところも参照)。 タブ付きのインターフェイスの構造を次のように更新しておきました。

+ +
<ul role="tablist">
+  <li class="active" role="tab" aria-selected="true" aria-setsize="3" aria-posinset="1" tabindex="0">Tab 1</li>
+  <li role="tab" aria-selected="false" aria-setsize="3" aria-posinset="2" tabindex="0">Tab 2</li>
+  <li role="tab" aria-selected="false" aria-setsize="3" aria-posinset="3" tabindex="0">Tab 3</li>
+</ul>
+<div class="panels">
+  <article class="active-panel" role="tabpanel" aria-hidden="false">
+    ...
+  </article>
+  <article role="tabpanel" aria-hidden="true">
+    ...
+  </article>
+  <article role="tabpanel" aria-hidden="true">
+    ...
+  </article>
+</div>
+ +
+

:  ここでの最も際立った変更点は、この例にもともと存在していたリンクを削除して、単にリスト項目をタブとして使ったことです。 このようにした理由は、スクリーンリーダーのユーザーにとっての物事の紛らわしさを減らせるからであり(これらのリンクは、実際にどこかへ連れて行ってくれるものではなく、ただ見かけを変化させるだけのものなのです)、また、セット機能における setsize/position が、よりうまく機能できるようになるからです。 setsize/position がリンク上に設定されている場合、ブラウザーは、「3 分の 1」「3 分の 2」などではなく、常に「1 分の 1」と報告し続けます。

+
+ +

新たな機能は次の通りです。

+ + + +

わたしたちの検査では、この新たな構造は、物事を全体的に改善するのに確かに役立ちました。 今や、タブはタブとして認識されます(例えば、スクリーンリーダーが「タブ」と話します)し、選択されたタブは、そのタブ名で読み上げられて「選択中」と示されますし、スクリーンリーダーは、どのタブ番号のところに今いるのかということも教えてくれます。 さらに、aria-hidden の設定(まさに隠されていないタブのみに、aria-hidden="false" と設定されている)のおかげで、隠されていないコンテンツのみが、ナビゲートして下ってゆける唯一のコンテンツとなっており、このことは、選択されたコンテンツを見つけやすくなったことを意味します。

+ +
+

: スクリーンリーダーに読み上げさせたくないと明示的に思うものが何かある場合、スクリーンリーダーに対して、aria-hidden="true"  属性を与えることができます。

+
+ +

まとめ

+ +

本記事は、WAI-ARIA で利用可能なすべてのものを取り扱ったとは、到底、言えません。 でも、WAI-ARIA の使い方を理解するのに十分な情報をお伝えしたはずです。 また、これから出会うであろう、WAI-ARIA を必要とするような最もよくあるパターンのうちのいくつかを知るのに十分な情報も、お伝えしたはずです。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/Accessibility/CSS_and_JavaScript","Learn/Accessibility/Multimedia", "Learn/Accessibility")}}

+ + + +

このモジュール内の文書

+ + diff --git a/files/ja/learn/accessibility/what_is_accessibility/index.html b/files/ja/learn/accessibility/what_is_accessibility/index.html new file mode 100644 index 0000000000..8f4efd327a --- /dev/null +++ b/files/ja/learn/accessibility/what_is_accessibility/index.html @@ -0,0 +1,233 @@ +--- +title: アクセシビリティとは? +slug: Learn/Accessibility/What_is_accessibility +tags: + - AT + - Accessibility + - Article + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Learn + - Tools + - Users + - assistive technology + - keyboard + - screan reader + - screenreader +translation_of: Learn/Accessibility/What_is_accessibility +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Accessibility/HTML", "Learn/Accessibility")}}
+ +

この記事では実際アクセシビリティとは何かについてよく観察するモジュールから開始します — これには考慮が必要な人のグループや、いろいろな人がウェブとやり取りするのになぜ、どんなツールを使うのかや、アクセシビリティをウェブ開発のワークフローに取り組む方法が含まれます。

+ + + + + + + + + + + + +
+

前提知識:

+
基本的なコンピューターの知識、HTML と CSS に関する基本的な理解
学習目標:アクセシビリティとは何か、そしてそれがウェブ開発者としてのあなたにどう関わってくるかを含め、アクセシビリティに詳しくなる
+ +

で、アクセシビリティって何?

+ +

アクセシビリティというのはあなたのウェブサイトを可能な限り多くの人に利用してもらうようにすることです。かつては我々はアクセシビリティのことをハンディキャップを持つ人々のためのものだと考えていましたが、現在はモバイルデバイスや遅いネットワークを利用している人々のためのものでもあると考えられています。

+ +

アクセシビリティを、能力や環境にかかわらず全員を同一に扱い、同じ機会を与えることと考えることもあります。車椅子に乗っているために物理的な建物から誰かを除外するのは正しくないのと同様に(昨今一般的に公的な建物では、車椅子のスロープやエレベーターを備えています)、視覚障碍があるためにウェブサイトから特定のユーザーを除外するのも正しくありません。我々はみんな異なっていて、しかしみんな人間であり、ゆえに同じ人権を持っています。

+ +

アクセシビリティは正しい行為です。アクセシブルなサイトを提供することは、いくつかの国では法律の一部でもあり、そうしなければサービスを利用したり、製品を買ったりすることなどができなかったであろう、いくつかの重要な市場を開拓することができます。

+ +

アクセシブルなサイトを構築するのは、すべての人の利益になります:

+ + + +

私たちが考える"不利な条件"とは?

+ +

障碍のある人は障碍のない人と同じくらい多様であり、よってその障碍も同じくらい多様です。ここでの重要な教訓は、あなたがコンピューターの向こうでウェブをどのように使うかを考え、他の人がどのように使っているかを学習し始めることです — あなたはユーザーとは違います。考慮すべき障碍の主な種類を、ウェブコンテンツにアクセスするために使う特別なツール(支援技術assistive technologyAT として知られるもの)とともに以下に説明します。

+ +
+

: 世界保健機構(WHO)の障碍と健康(英語)の報告によると、「10億人以上の人(世界人口の約15%)が何らかの障碍を持っています」し、「1億~1億9000万人の大人に目立った機能障碍があります」

+
+ +

視覚障碍者

+ +

視覚障碍者には全盲の人や、視覚が低レベルな人、色盲の人などが含まれます。これらの多くはスクリーン拡大鏡 (物理的な拡大鏡とソフトウェアズーム機能のいずれか — 大半のブラウザーと OS には今日ズーム機能があります) を使い、スクリーンリーダー、つまりデジタルテキストを読み上げるソフトウェアを使う人もいます。スクリーンリーダーの例はこれらです:

+ + + +

スクリーンリーダーに精通するのは良い考えです; スクリーンリーダーをセットアップして試してみて、その動作方法を理解するべきです。 クロスブラウザーテストのスクリーンリーダーのガイド を見ると詳しい使い方がわかります。下記の動画も、その体験がどのようなものかの簡単な例です。

+ +

{{EmbedYouTube("IK97XMibEws")}}

+ +

統計では、WHO は「世界中で 2億8500万人が視覚障碍者で、うち 3900万人が全盲で 2億4600万人がロービジョンです」と見積もっています(視覚障碍と盲目(英語)を参照)。これは単にサイトが適切にコーディングされていないために逃すユーザーとしては多くて重要です — 米国の人口とほぼ同じ大きさです。

+ +

聴覚障碍者

+ +

耳の障碍者や、ろう者とも知られて、このグループの人には聞こえにくい人と全く聞こえない人の両方がいます。聴覚障碍者は AT(聴覚、発声能力、発話能力、言語に障碍のある人のための補助装置(英語)を参照)を使いますが、コンピューターやウェブに特化した特別な AT はありません。

+ +

しかしながら、単純なテキストトランスクリプトから、動画と一緒に表示できるテキストトラック(すなわちキャプション)まで、彼らが音声コンテンツに代わって読むことができるテキストを提供するために留意すべき特定のテクニックがあります。後の記事で詳しく扱います。

+ +

聴覚障碍者もまた重要なユーザー基盤を代表しています — 「世界中で 4億6,600万人が日常生活に支障を来すほどの聴覚障害を持っています」と WHO はろうと聴覚障碍(英語)で報告しています。

+ +

運動障碍のある人

+ +

これらの人々は、(四肢の喪失や麻痺のような)純粋に肉体的な問題や、四肢の衰弱や制御不能につながる神経学的障碍や遺伝子疾患を伴う可能性がある、運動に関する障碍を持っています。マウスを使うのに必要な正確な手の動きが難しい人もいれば、もっと深刻な影響を受けて、コンピューターと対話するためにヘッドポインタ(英語)を使う必要があるところまで著しく麻痺している人もいます。

+ +

この種の障碍は、特定のトラウマや状態ではなく、老年期の結果であることもあります。それに、ハードウェアの制限から生じることもあります — 一部のユーザーはマウスを持っていないかもしれません。

+ +

これが通常ウェブ開発作業に影響するのは、コントロールがキーボードからアクセス可能であることという要件です — このモジュールの後の記事でキーボード・アクセシビリティを扱いますが、どのようにやるかを見るためにキーボードだけを使っていくつかのウェブサイトを試してみることは良い考えです。例えば、Tab キーを使ってウェブフォームのさまざまなコントロール間を移動できますか? キーボードコントロールの詳細については、クロスブラウザーテストのネイティブなキーボード・アクセシビリティを使うのセクションを参照してください。

+ +

統計では、有意な数の人が運動障碍を持っています。米国疾病管理予防センターの障碍と機能 (施設に入らない 18 歳以上の大人) (英語)の報告によると、米国では "肉体的な機能障碍のある大人の割合は、16.1%" です。

+ +

認知障碍者

+ +

認知障碍者とは最も広い範囲の障碍をいい、最も限定された能力をもつ知的障碍者からわれわれがみな加齢とともに考えたり記憶したりが困難になることまでがあります。この範囲には 鬱病(英語)や 統合失調症(英語)といった精神疾患のほか、ディスクレシア(英語)やADHD(注意欠陥多動性障碍)(英語)のような学習障害も含みます。

+ +

理解と集中の困難、自閉症スペクトラム(英語)の人々に、統合失調症(英語)を有する人々、および他の多くの障碍を指します。このような障碍は、記憶、問題解決、理解、注意などの問題により、日常生活の多くの部分に影響を及ぼします。重要なこととして、認知障碍の臨床的な定義が広がっていても、そうした障碍をもつ人には共通の機能不全があります。それにはコンテンツを理解し難いこと、タスクを完了する方法を記憶すること、一貫性のないウェブページレイアウトによって混乱することがあります。

+ +

認知障碍者へのアクセシビリティの良い基本事項は、次のものです:

+ + + +

注記

+ + + +

プロジェクトにアクセシビリティを実装する

+ +

よくあるアクセシビリティ神話は、アクセシビリティはプロジェクトに実装するための高価な「余分な追加」であるということです。この神話は、実際には次のいずれかの場合に当てはまります。

+ + + +

ただし、プロジェクトの開始時からアクセシビリティを検討している場合は、ほとんどのコンテンツをアクセス可能にするためのコストはごくわずかなはずです。

+ +

プロジェクトを計画するときは、他の重要な対象観客セグメント(対象とするデスクトップやモバイルのブラウザーなど)のテストと同様に、アクセシビリティのテストをテスト体制に組み入れます。早期に頻繁にテストし、理想的にはプログラムで検出可能な欠けている機能(画像の代替テキストの欠落、リンクテキストの不良のような — 要素の関係とコンテキストを参照)を検出するための自動テストの実行し、より複雑なサイト機能が障碍のあるユーザーのグループに対してどの程度うまく機能するかを確認するために、それらのグループでいくつかのテストを行います。例えば、

+ + + +

コンテンツをアクセス可能にするための作業が必要なコンテンツの潜在的な問題領域をメモしておくことができ、またそうすべきで、徹底的にテストしていることを確認し、解決策や代替案について考えます。次の記事で見るように、テキストコンテンツは簡単ですが、マルチメディアコンテンツや、最先端の 3D グラフィックはどうでしょうか?  あなたはプロジェクトの予算を見て、現実的にそのようなコンテンツをアクセス可能にするために利用可能などんな解決策があるかついて考えるべきです。あなたはマルチメディアコンテンツすべてを転記するために支払うことができます。これは高価になることがありますが、行うことができます。

+ +

現実的にもなりましょう。「100% のアクセシビリティ」は達成不可能な理想です — あなたは常にある種の最先端のケースに出くわすことになり、その結果特定のユーザーが特定のコンテンツを使いにくいと感じることになります — しかしできる限りはするべきです。WebGL を使用して作成した最先端の 3D 円グラフのグラフィックを含めることを計画している場合は、データのアクセス可能な代替表現としてデータ表を含めることができます。あるいは、表だけを含めて 3D 円グラフを取り除くことをお勧めします — 表には誰でもアクセスでき、コード作成が早く、CPU 使用率が低く、保守が簡単です。

+ +

これに反して、興味深い 3D アートを展示したギャラリーのウェブサイトで作業している場合、それが完全に視覚的な媒体であることを考えると、すべてのアートが視覚障碍者にとって完全にアクセス可能であることを期待するのは不合理でしょう。

+ +

あなたがアクセシビリティに関心があり、考えていることを示すために、あなたのサイトに、アクセシビリティに向けた方針と、サイトをアクセス可能にするためにどのようなステップを踏んだかを詳しく記載した、アクセシビリティに関する声明を発表してください。あなたのサイトにアクセシビリティの問題があると誰かが文句を言ってきたら、彼らと対話を始め、共感し、そして問題を解決するために合理的なステップを踏みます。

+ +
+

: よくあるアクセシビリティの問題を扱うの記事では、より詳細にテストするべきであるアクセシビリティの詳細について説明しています。

+
+ +

要約すると、

+ + + +

アクセシビリティのガイドラインと法律

+ +

アクセシビリティテストの基礎となる多数のチェックリストと一連のガイドラインがあります。これは、一見すると圧倒的に思われるかもしれません。アドバイスとしては、あなたが注意を払う必要がある基本的な分野に精通すること、そしてあなたにとって最も関連性のあるガイドラインの高いレベルの構造を理解することです。

+ + + +

そのため、WCAG は一連のガイドラインですが、あなたの国ではおそらくウェブアクセシビリティ、または少なくとも公的に利用可能なサービスのアクセシビリティ(ウェブサイト、テレビ、物理的な空間などを含む)を規制する法律があるでしょう。あなたの法律が何であるかを調べることは良い考えです。あなたのコンテンツがアクセス可能であることを確認しようと努力せずに、障碍を持つ人々が訴えた場合、法律な責任を負うこともあります。

+ +

これは深刻に思えますが、実際には、上で概説したように、アクセシビリティをウェブ開発の最優先事項として考慮する必要があります。疑問がある場合は、資格のある弁護士に相談してください。私たちは弁護士ではないので、これ以上のアドバイスは提供しません。

+ +

アクセシビリティの API 群

+ +

ウェブブラウザーは、支援技術(AT)に役立つ情報を公開する(基礎となる OS によって提供される)特別なアクセシビリティ API を利用します —  AT は大抵は意味論的情報を利用する傾向があるので、この情報にはスタイル情報や JavaScript のようなものを含みません。この情報は、アクセシビリティツリーと呼ばれる情報のツリーで構成されています。

+ +

次のように、OS が異なれば、利用可能なアクセシビリティ API も異なります。

+ + + +

ウェブアプリにおいて HTML 要素によって提供されるネイティブな意味論的情報が足りない場合は、あなたは WAI-ARIA の仕様(英語)の機能でそれを補うことができます。これにより、アクセシビリティツリーに意味論的情報が追加され、アクセシビリティが向上します。WAI-ARIA の基本の記事で WAI-ARIA についてもっと多くを学ぶことができます。

+ +

まとめ

+ +

この記事では高いレベルでアクセシビリティの概要を説明し、それが重要である理由と、ワークフローに取り込む方法を見てきました。サイトをアクセシブルにするための実装の詳細について学ぶことを渇望する人もいるでしょう。それでは次の記事では、HTML がアクセシビリティの良い基礎である理由を見ていきます。

+ +

{{NextMenu("Learn/Accessibility/HTML", "Learn/Accessibility")}}

+ +

このモジュール内の文書

+ + + + + +

関連情報

+ + diff --git a/files/ja/learn/common_questions/available_text_editors/index.html b/files/ja/learn/common_questions/available_text_editors/index.html new file mode 100644 index 0000000000..63f591f01a --- /dev/null +++ b/files/ja/learn/common_questions/available_text_editors/index.html @@ -0,0 +1,296 @@ +--- +title: どんなテキストエディタが利用可能ですか? +slug: Learn/Common_questions/Available_text_editors +translation_of: Learn/Common_questions/Available_text_editors +--- +
{{IncludeSubnav("/ja/Learn")}}
+ +
+

この記事では Web 開発用のテキストエディタをインストールする際に考慮すべき点をいくつか取り上げます。

+
+ + + + + + + + + + + + +
学習の前提:Web サイトを構築するために必要な様々なソフトウェアについて知っていること。
学習の目標Web 開発者としてのニーズに最適なテキストエディタを選択する方法を学びます。
+ +

概要

+ +

Web サイトは、ほとんどテキストファイルで構成されています。その開発を容易で快適なものにするため、最適なテキストエディタを選びましょう。

+ +

テキストエディタは、コンピュータサイエンスにとって基本的なものです(Web 開発はコンピュータサイエンスそのものですよね)。そのため、膨大な選択肢があります。理想を言えば、できるだけ多くのエディタを試して、ワークフローに適したものを見つけるのが良いです。とは言っても、取っ掛かりをつけるため、いくつかの指針をあげることにします。

+ +

まず以下の点を検討しましょう。

+ + + +

ここまでで価格に言及していないことに注目してください。明らかにそれも重要ですが、製品価格は、その品質や機能とはあまり関係ありません。使いやすいテキストエディタを無料で手に入れることも可能なのです。

+ +

人気のあるエディタの例を挙げてみましょう:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
エディタライセンス価格OSサポートドキュメント機能拡張
AtomMIT/BSD無料Windows, Mac, LinuxForumOnline ManualYes
BracketsMIT/BSD無料Windows, Mac, LinuxForum, IRCGitHub WikiYes
Codaクローズドソース$99MacTwitter, Forum, E-maileBookYes
EmacsGPL 3無料Windows, Mac, LinuxFAQ, Mailing list, News GroupOnline ManualYes
Espressoクローズドソース$75MacFAQ, E-mailNo end user doc,
+ but plug-in doc
Yes
GeditGPL無料Windows, Mac, LinuxMailing list, IRCOnline ManualYes
Komodo EditMPL無料Windows, Mac, LinuxForumOnline ManualYes
Notepad++GPL無料WindowsForumWikiYes
PSPadクローズドソース無料WindowsFAQ, ForumOnline HelpYes
Sublime Textクローズドソース$70Windows, Mac, LinuxForumOfficial, UnofficialYes
TextMateクローズドソース$50MacTwitter, IRC, Mailing list, E-mailOnline Manual, WikiYes
TextWranglerクローズドソース無料MacFAQ, ForumPDF ManualNo
VimSpecific open license無料Windows, Mac, LinuxMailing listOnline ManualYes
Visual Studio CodeOpen Source under MIT licence/ Specific licence for product無料Windows, Mac, LinuxFAQ     DocumentationYes
+ +

アクティブラーニング

+ +

現在利用可能なアクティブラーニングはありません。貢献を考えてください

+ +

詳しく見てみましょう

+ +

エディタを選択する基準

+ +

それでは、テキストエディタを選ぶとき何を考慮すべきでしょうか?

+ +

どの OS (オペレーティングシステム) を使用するか?

+ +

もちろんそれはあなたの選ぶことです。しかし、特定の OS でしか使えないエディタもあります。そのため、OSを切り替えて開発する場合には、選択肢が狭まります。システム上で実行できるのなら、どんなテキストエディタでも作業を行うことはできます。でも、クロスプラットフォームエディタを使用すると、OS 間の移行が容易になります。

+ +

最初に、あなたが使う OS を選びます。次に、検討中のエディタがその OS をサポートしているか確認してください。ほとんどのエディタは  WindowsやMacのサポート状況を、そのWeb サイトで公開しています。OSのバージョンが限定されている (Windows 7 以降のみをサポートし、Vista はサポートしないなど)場合もあります。Ubuntu を使うのなら、Ubuntu ソフトウェアセンター内を検索することをお勧めします。ただし、Linux/UNIX の世界には多様性があり、ディストリビューションが違うと動作も異なったり、パッケージ間の互換性がなかったりします。あまり流通していないテキストエディタに関心を抱いたりすると、自分でソースからコンパイルする羽目になるかもしれません (気の弱い人にはお勧めできません)。

+ +

どのような技術を扱うのか?

+ +

一般論を言えば、テキストエディタなら、どんなテキストファイルでも開くことができます。自分のメモ書き程度なら、それで十分です。しかし、Web開発を行い、{{Glossary("HTML")}}、{{Glossary("CSS")}}、あるいは{{Glossary("JavaScript")}}をで使ったりすると、ファイルはかなり大きくて複雑なものになります。 Webで扱う技術情報に基づいテキストエディタを選択して、作業を簡単にしましょう。多くのテキストエディタには次のようなサポート機能があります。

+ + + +

コードの着色はほとんどのテキストエディタがサポートしていますが、他の二つの機能はまだのものが多いのが現状です。使用する予定のテキストエディタが、 {{Glossary("HTML")}}、 {{Glossary("CSS")}}、それに {{Glossary("JavaScript")}}を着色できるか確認しておきましょう。

+ +

テキストエディタに、どのような基本機能を求めるか?

+ +

あなたのニーズと計画によりますが、以下の機能は多くの場合に有用です。I

+ + + +

テキストエディタの機能を拡張したいか?

+ +

拡張型のテキストエディタは、標準で組み込まれた機能こそ少ないが、必要に応じて機能を拡張することができます

+ +

あなたの開発に必要な機能が明確でなかったり、使いたい機能がエディタに組み込まれていないときは、拡張型のエディタを検討するのがいいです。良いとされているエディタは、プラグインできる機能を多数持っており、自分で必要なものを探してインストールできるものもあります。

+ +

多くの機能が必要だが、プラグインが多くなってエディタの動作速度が低下するようなら、統合開発環境(IDE: integrated development environment)を検討してみてください。IDEは、統一したインターフェースで多くのツールを使えるので、初心者には少々荷が重いかもしれません。そういう時は、機能を限定して使えばいいのです。有名なIDEの例を下に挙げておきます。

+ + + +

テキストエディタを使用している間、サポートやヘルプが必要か?

+ +

一般にソフトウエアを使うときには、ヘルプがあるかないかを知っておくことは重要です。テキストエディタの場合は、以下の二種類のサポートがあるか調べておくといいです。

+ +
    +
  1. ユーザー向けのコンテンツ(FAQ、マニュアル、オンラインヘルプなど)
  2. +
  3. 開発者や他のユーザーとのディスカッション(フォーラム、メール、チャットなど)
  4. +
+ +

使いかたを学ぶには、1.のコンテンツを読むのが有効です。インストールや使用上の問題を解決するには、他のユーザーの助けが役に立ちます。

+ +

テキストエディタの使い勝手は重要か?

+ +

たしかに、好みの問題かもしれません。いっぽうでは、表示色やボタンの位置など、UI(ユーザーインターフェース)のそこかしこをカスタマイズしたがる人もいます。変更可能な範囲はエディタごとに異なるので、導入前に調べておきましょう。色遣いを変えられるエディタは多くあります。しかし、カスタマイズしたいことがあまり多いようなら、統合開発環境を選んだ方が賢明です。

+ +

インストールとセットアップ

+ +

テキストエディタのインストールは、非常に分かりやすいのが普通です。その方法はプラットフォーム(OS)によって変わりますが、それほど難しいものではありません。:

+ + + +

新しいエディタをインストールしても、OSは既定エディタを変更しない限り、OSは前のエディタを使ってテキストファイルを開こうとします。ファイルをダブルクリックしたときに使う規定エディタを変更するには、以下のリンクにある説明を参照してください。

+ + + +

次のステップ

+ +

良いテキストエディタが見つかったら、基本的な作業環境(テストサーバー)の構築に着手しましょう。あるいは、最初のWebページを書いてみるのもいいでしょう。。

diff --git a/files/ja/learn/common_questions/checking_that_your_web_site_is_working_properly/index.html b/files/ja/learn/common_questions/checking_that_your_web_site_is_working_properly/index.html new file mode 100644 index 0000000000..4c3499402f --- /dev/null +++ b/files/ja/learn/common_questions/checking_that_your_web_site_is_working_properly/index.html @@ -0,0 +1,172 @@ +--- +title: Web サイトが正しく機能することをどうやって確認しますか? +slug: Learn/Common_questions/Checking_that_your_web_site_is_working_properly +tags: + - ガイド + - トラブルシューティング + - ドキュメント + - 初心者 +translation_of: Learn/Common_questions/Checking_that_your_web_site_is_working_properly +--- +
+

この記事では、Webサイトのさまざまなトラブルシューティングの手順と、これらの問題を解決するための基本的な操作について説明します。

+
+ + + + + + + + + + + + +
前提条件:Web サーバにファイルをアップロードする方法を知る必要があります。
目標:自身の Web サイトで実行できるいくつかの基本的な問題を診断して解決する方法を学びます。
+ +

自身の Web サイトをオンラインで公開しましたか? 素晴らしい! ただ、それは適切に動作しているでしょうか?

+ +

別の場所にある Web サーバ は、ローカル Web サーバとはまったく異なった動作をすることが多いため、オンラインになったら Web サイトをテストすることをお勧めします。画像が表示されない、ページが読み込まれない、または読み込みが遅くなるなど、多くの問題が発生するのに驚くかもしれません。ほとんどの場合、大したことではなく、簡単な間違いや Web ホスティング設定の問題です。

+ +

これらの問題を診断して解決する方法を見てみましょう。

+ +

アクティブラーニング

+ +

アクティブラーニングはまだありません。 貢献をご検討ください

+ +

より深く掘り下げる

+ +

ブラウザでテストする

+ +

Web サイトが正しく機能しているかどうかを知りたければ、まずブラウザを起動し、テストしたいページに移動します。

+ +

ええと、そのイメージはどこですか?

+ +

個人的な Web サイト http://demozilla.examplehostingprovider.net/ を見てみましょう。予想していた画像ではありません。

+ +

Oops, the ‘unicorn’ image is missing

+ +

Firefox のネットワークツール (ツールWeb 開発者ネットワーク) を開き、ページをリロードします。

+ +

The image has a 404 error

+ +

一番下に「404」という問題があります。「404」は「リソースが見つかりません」という意味です。そのため、画像が表示されませんでした。

+ +

HTTP ステータス

+ +

サーバは、リクエストを受信するたびにステータスメッセージで応答します。最も一般的なステータスは次のとおりです。

+ +
+
200: OK
+
求めているリソースが配信されました。
+
301: Moved permanently
+
リソースは新しい場所に移動しました。あなたのブラウザでこれをあまり見ないでしょう、しかし検索エンジンがインデックスを更新するのにこの情報をたくさん使うので "301" について知るのは良いことです。
+
304: Not modified
+
最後にファイルをリクエストしてからファイルが変更されていないため、ブラウザはキャッシュからバージョンを表示できるので、応答時間が短縮され、帯域幅がより効率的に使用されます。
+
403: Forbidden
+
そのリソースを表示することを許可されていません。通常それは設定ミス (例えばあなたのホスティングプロバイダがディレクトリへのアクセス権を与えるのを忘れた) と関係があります。
+
404: Not found
+
一目瞭然です。これを解決する方法を以下で説明します。
+
500: Internal server error
+
サーバで何か問題が発生しました。たとえば、サーバサイドの言語 ({{Glossary("PHP")}}、.Net など) が機能しなくなった、または Web サーバ自体に構成上の問題がある可能性があります。通常、ホスティングプロバイダのサポートチームに頼るのが最善です。
+
503: Service unavailable
+
通常、短期間のシステム過負荷が原因です。サーバに何らかの問題があります。しばらくしてからもう一度試してください。
+
+ +

初心者が私たちの (単純な) Web サイトをチェックするとき、私たちは200、304、403、そして404を最もよく扱うでしょう。

+ +

404 を修正する

+ +

では何が悪かったのでしょうか?

+ +

Le list of images in our project

+ +

一見したところ、私たちが求める画像は正しい場所にあるようです...しかしネットワークツールは「404」を報告しました。 HTML コードに unicorn_pic.png ではなく unicorn_pics.png という入力ミスをしたことがわかりました。画像の src 属性を変更して、コードエディタのタイプミスを修正します。

+ +

Deleting the ‘s’

+ +

保存してサーバにプッシュし、ブラウザでページをリロードします。

+ +

The image loads corectly in the browser

+ +

そこに行きます!{{Glossary("HTTP")}} ステータスをもう一度見てみましょう:

+ + + +

さて、エラーを修正し、途中でいくつかの HTTP ステータスを学習しました。

+ +

よくあるエラー

+ +

最もよく見かけるエラーはこれらです:

+ +

アドレスのタイプミス

+ +

http://demozilla.examplehostingprovider.net/ と入力したいのですが、入力が速すぎて「l」を忘れていました。

+ +

Address unreachable

+ +

アドレスが見つかりません。確かに。

+ +

404 エラー

+ +

多くの場合、エラーは単にタイプミスが原因ですが、リソースのアップロードを忘れたか、アップロード中にネットワーク接続が切断された可能性もあります。まずファイルパスの綴りと正確さを確認し、それでも問題が解決しない場合は、ファイルをもう一度アップロードしてください。おそらく問題は解決するでしょう。

+ +

JavaScript エラー

+ +

誰か (おそらくあなた) がそのページにスクリプトを追加する中で間違えました。これでページの読み込みが妨げられることはありませんが、問題が発生したと感じるでしょう。

+ +

コンソールを開き (ツールWeb 開発者Web コンソール)、ページをリロードします。

+ +

A Javascript error is shown in the Console

+ +

この例では、エラーが何かを (非常に明確に) 学び、それを修正することができます (別の一連の記事で JavaScript について説明します)。

+ +

その他の事項を確認する

+ +

Web サイトが正しく機能していることを確認する簡単な方法、および発生する可能性がある最も一般的なエラーとそれらの修正方法を示しました。ページがこれらの基準を満たしているかどうかをテストすることもできます。

+ +

パフォーマンスはどうですか?

+ +

ページの読み込みは十分速いですか? WebPagetest.org のようなリソースや YSlow のようなブラウザアドオンをしようすることで、いくつか興味深いことが分かります。

+ +

Yslow diagnostics

+ +

グレードは A から F までです。私たちのページはごくわずかで、ほとんどの基準を満たしています。しかし、{{Glossary("CDN")}} を使った方が良いでしょう。1つの画像だけを配信する場合はそれほど重要ではありませんが、広帯域幅の Web サイトで何千もの画像を配信する場合は重要になります。

+ +

サーバーは十分に応答しますか?

+ +

ping は指定したドメイン名をテストし、サーバが応答しているかどうかを知らせる便利なシェルツールです。

+ +
$ ping mozilla.org
+PING mozilla.org (63.245.215.20): 56 data bytes
+64 bytes from 63.245.215.20: icmp_seq=0 ttl=44 time=148.741 ms
+64 bytes from 63.245.215.20: icmp_seq=1 ttl=44 time=148.541 ms
+64 bytes from 63.245.215.20: icmp_seq=2 ttl=44 time=148.734 ms
+64 bytes from 63.245.215.20: icmp_seq=3 ttl=44 time=147.857 ms
+^C
+--- mozilla.org ping statistics ---
+4 packets transmitted, 4 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = 147.857/148.468/148.741/0.362 ms
+ +

便利なキーボードショートカット、すなわち Ctrl+C を覚えておいてください。Ctrl+C はランタイムに「割り込み」信号を送り、停止するように伝えます。ランタイムを停止しないと、ping は サーバに無期限に ping を実行します。

+ +

簡単なチェックリスト

+ + + +

次のステップ

+ +

おめでとうございます、Web サイトは誰もが訪れることができるようになっています。それは大きな成果です。これで、さまざまなテーマに深く掘り下げていくことができます。

+ + diff --git a/files/ja/learn/common_questions/common_web_layouts/index.html b/files/ja/learn/common_questions/common_web_layouts/index.html new file mode 100644 index 0000000000..88fc618791 --- /dev/null +++ b/files/ja/learn/common_questions/common_web_layouts/index.html @@ -0,0 +1,108 @@ +--- +title: 一般的な Web レイアウトには何が含まれていますか? +slug: Learn/Common_questions/Common_web_layouts +translation_of: Learn/Common_questions/Common_web_layouts +--- +
{{IncludeSubnav("/en-US/Learn")}}
+ +
+

When designing pages for your website, it's good to have an idea of the most common layouts.

+
+ + + + + + + + + + + + +
Prerequisites:Make sure you've already thought about what you want to accomplish with your web project.
Objective:Learn where to put things on your webpages, and how to put them there.
+ +

Summary

+ +

There's a reason we talk about web design. You start out with a blank page, and you can take it so many directions. And if you don't have much experience, starting out with a blank page might be a bit scary. We have over 25 years' experience and we'll give you some common rules of thumb to help you design your site.

+ +

Even now with the new focus on mobile Web, almost all mainstream webpages are built from these parts:

+ +
+
Header
+
Visible at the top of every page on the site. Contains information relevant to all pages (like site name or logo) and an easy-to-use navigation system.
+
Main content
+
The biggest region, containing content unique to the current page.
+
Stuff on the side
+
1) Information complementing the main content; 2) information shared among a subset of pages; 3) alternative navigation system. In fact, everything not absolutely required by the page's main content.
+
Footer
+
Visible at the bottom of every page on the site. Like the header, contains less prominent global information like legal notices or contact info.
+
+ +

These elements are quite common in all form factors, but they can be laid out different ways. Here are some examples (1 represents header, 2 footer; A main content; B1, B2 things on the side):

+ +

1-column layout. Especially important for mobile browsers so you don't clutter the small screen up.

+ +

Example of a 1 column layout: Main on top and asides stacked beneath it.

+ +

2-column layout. Often used to target tablets, since they have medium-size screens.

+ +

 Example of a basic 2 column layout: One aside on the left column, and main on the right column. Example of a basic 2 column layout: One aside on the right column, and main on the left column.

+ +

3-column layouts. Only suitable for desktops with big screens. (Even many desktop-users prefer viewing things in small windows rather than full-screen.)

+ +

Example of a basic 3 column layout: Aside on the left and right column, Main on the middle column. Another example of a 3 column layout: Aside side by side on the left, Main on the right column. Another example of a 3 column layout: Aside side by side on the right, Main on the left column.

+ +

The real fun begins when you start mixing them all together:

+ +

Example of mixed layout: Main on top and asides beneath it side by side. Example of a mixed layout: Main on the left column and asides stack on top of each other on the right column Example of a mixed layout: one aside on the left column and main in the right column with a aside beneath main. Example of a mixed layout: Main on the left of the first row and one aside on the right of that same row, a second aside convering the whole second row.

+ +

These are just examples and you're quite free to lay things out as you want. You may notice that, while the content can move around on the screen, we always keep the header (1) on top and the footer (2) at the bottom. Also, the main content (A) matters most, so give it most of the space.

+ +

These are rules of thumb you can draw on. There are complex designs and exceptions, of course. In other articles we'll discuss how to design responsive sites (sites that change depending on the screen size) and sites whose layouts vary between pages. For now, it's best to keep your layout consistent throughout your site.

+ +

Active learning

+ +

There is no active learning available yet. Please, consider contributing.

+ +

Deeper dive

+ +

Let's study some more concrete examples taken from well-known websites.

+ +

One-column layout

+ +

Invision application. A typical one-column layout providing all the information linearly on one page.

+ +

Example of a 1 column layout in the wild        1 column layout with header, main content, a stack of aside contents and a footer

+ +

Quite straightforward. Just remember, many people will still browse your site from desktops, so make your content usable/readable there as well.

+ +

Two-column layout.

+ +

Abduzeedo, a simple blog layout. Blogs usually have two columns, a fat one for the main content and a thin one for stuff on the side (like widgets, secondary navigation levels, and ads).

+ +

Example of a 2 column layout for a blog        A 2 column layout with the main content on the left column

+ +

In this example, look at the image (B1) right underneath the header. It's related to the main content, but the main content makes sense without it, so you could think of the image either as main content or as side content. It doesn't really matter. What does matter is, if you put something right under the header, it should either be main content or directly related to the main content.

+ +

It's a trap

+ +

MICA. This is a bit trickier. It looks like a three-column layout...

+ +

Example of a false 3 columns layout        It looks like a 3 columns layout but actually, the aside content is floating around.

+ +

...but it's not. B1 and B2 float around the main content. Remember that word "float"--it will ring a bell when you start learning about {{Glossary("CSS")}}.

+ +

Why would you think it's a three-column layout? Because the image on the top-right is L-shaped, because B1 looks like a column supporting the shifted main content, and because the "M" and "I" of the MICA logo create a vertical line of force.

+ +

This is a good example of a classic layout supporting some design creativity. Simple layouts are easier to implement, but allow yourself room to express your creativity in this area.

+ +

A much trickier layout

+ +

The Opera de Paris.

+ +

An example of a tricky layout.        This is a 2 column layout but the header is overlaping the main content.

+ +

Basically a two-column layout, but you'll notice many tweaks here and there that visually break up the layout. Especially, the header overlaps the image of the main content. The way the curve of the header's menu ties in with the curve at the bottom of the image, the header and main content look like one thing even though they're technically completely different. The Opera example looks more complex than the MICA example, but it's actually easier to implement (all right, "easy" is a relative concept).

+ +

As you see, you can craft stunning websites even with just basic layouts. Have a look at your own favorite websites and ask yourself, where's the header, the footer, the main content, and the side content? That will inspire you for your own design and give you good hints for which designs work and which ones don't.

diff --git a/files/ja/learn/common_questions/design_for_all_types_of_users/index.html b/files/ja/learn/common_questions/design_for_all_types_of_users/index.html new file mode 100644 index 0000000000..7c3da5fc1e --- /dev/null +++ b/files/ja/learn/common_questions/design_for_all_types_of_users/index.html @@ -0,0 +1,219 @@ +--- +title: どのようにすべてのタイプのユーザーを対象に設計できますか? +slug: Learn/Common_questions/Design_for_all_types_of_users +translation_of: Learn/Common_questions/Design_for_all_types_of_users +--- +
{{IncludeSubnav("/ja/Learn")}}
+ +
+

この記事ではあらゆる種類のユーザーのための Web サイトを設計する基本的なヒントを紹介します。

+
+ + + + + + + + + + + + +
前提条件あなたはすでにアクセシビリティとは何か?を読んでいますか?,ここではアクセシビリティについて詳細にカバーしていませんので
目的ユニバーサルデザインとは、障害や技術的制約にかかわらず、すべての人のためのデザインを意味します。 この記事では、ユニバーサルデザインの最も重要なクイックウィンを紹介します。
+ +

概要

+ +

ウェブサイトを構築する際に考えなければならない課題のトップの一つがユニバーサルデザインです。障害、技術的な制約、文化、場所などに関わらず、すべてのユーザーが包含されるものです。

+ +

アクティブラーニング

+ +

まだ、アクティブラーニングがありません。 Please, consider contributing.

+ +

深く掘っていく

+ +

カラーコントラスト

+ +

テキストの読みやすさを維持するためにバックグラウンドカラーと一緒にテキストカラーとのコントラストを良くしなければなりません。視覚的に障害をもつ人々や路上でスマートフォンを使っている人々などを助けるために余計にやさしくしなければなりません。

+ +

{{Glossary("W3C")}}は前景と背景の間の明るさの比のアルゴリズムの計算をして良いカラーの混合を定義しました。計算はかなり複雑なように見えますが、私たち自身の仕事で信頼できるツールにできました。 

+ +

Pacielloグループカラーコントラストアナライザーをダウンロードしてインストールしてみましょう。

+ +
+

注意: あなたはオンライン上でコントラストチェッカーを選択的にウェブ用のカラーコントラストチェッカーのようなものをいくつか見つけることができるでしょう。カラーの値を画面上で見つけ出すのでローカルのカラーチェッカーを私たちはお薦めします。

+
+ +

例えば、どのようにカラーコントラストアナライザーを使えばいいのかこのページでカラーテストを行ってみましょう。

+ +

Colour contrast on this page: excellent!

+ +

テキストと背景明るさの比は 8.30:1 でそれは最小の標準を超えていて (4.5:1) 、視覚障害のある多くの人でもこのページを読めるようにすべきである。

+ +

フォントサイズ

+ +

ウェブサイトにおけるフォントサイズの相関位置と絶対位置のどちらも指定することができます。

+ +

絶対単位

+ +

絶対単位は比例を計算しません。しかし、サイズをストーンに設定して参照します。そうなので、話すために、そして、ピクセルで示すことが最も多いです。例えばCSSはこのように宣言されています。 

+ +
body { font-size:16px; }
+ +

… あなたがブラウザに言うと何かが起こるかもしれません。フォントサイズは16ピクセルにしなければなりません。モダンブラウザでは100%ズームと要素を設定した時にあなたが要求した16ピクセルのふりをすることによってこのルールを得ているかもしれません。

+ +

もう何年間もインターネットエクスプローラーはインターネットエクスプローラー8になるあたりまで断固として16ピクセルは16ピクセルとして表示をしてきました。この場合では拡大することはなく、そしてそれはまだ周りにあることによってそのようにふるまわねばなりません。 

+ +

相関単位

+ +

比例単位と呼ばれているものも、相関単位は親要素に関連して計算されます。相関単位はアクセシビリティに親しみのあるもので、なぜならそれらは、ユーザーシステム上に設定され尊重されるものだからです。 

+ +

相関単位は em 、% や rem:で表現されます。

+ +
+
Percent-based sizes: %
+
Thisこの単位は以前の要素で表現されたフォントサイズN%で示すように指示します。 もし、親がない場合、デフォルトのフォントサイズ計算による基本的なサイズがブラウザで考えられます。 (たいてい16ピクセルに同等になります。)
+
Em-based sizes: em
+
This unit is calculated the same way as percents, except that you compute in portions of 1 and not portions of 100. It is said that "em" is the width of a capital “M” in the alphabet (roughly speaking, an “M” fits into a square).
+
Rem-based sizes: rem
+
This unit is proportional to the root element's font size and is expressed as portions of 1, like em.
+
+ +

Suppose we wanted a base font size of 16px and an h1 (main heading) at the equivalent of 32px, yet if within the h1 we find a span with the subheading class, it too must be rendered at the default font size (usually 16px).

+ +

Here is the HTML we're using:

+ +
<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Font size experiment</title>
+</head>
+<body>
+
+    <h1>This is our main heading
+        <span class="subheading">This is our subheading</span>
+    </h1>
+
+</body>
+</html>
+ +

A percent-based CSS will look like this:

+ +
body { font-size:100%; } /* 100% of the browser's base font size, so in most cases this will render as 16 pixels */
+h1 { font-size:200%; } /* twice the size of the body, thus 32 pixels */
+span.subheading { font-size:50%; } /* half the size of the h1, thus 16 pixels to come back to the original size */
+
+ +

The same problem expressed with ems:

+ +
body { font-size:1em; } /* 1em = 100% of the browser's base font size, so in most cases this will render as 16 pixels */
+h1 { font-size:2em; } /* twice the size of the body, thus 32 pixels */
+span.subheading { font-size:0.5em; } /* half the size of the h1, thus 16 pixels to come back to the original size */
+ +

As you can see, the math quickly gets daunting when you have to keep track of the parent, the parent's parent, the parent's parent's parent, and so on. (Most designs are done in pixel-based software, so the math has to be done by the person coding the CSS).

+ +

Enter rem. This unit is relative to the root element's size and not to any other parent. The CSS can be rewritten thus:

+ +
body { font-size:1em; } /* 1em = 100% of the browser's base font size, so in most cases this will render as 16 pixels */
+h1 { font-size:2rem; } /* twice the size of the body, thus 32 pixels */
+span.subheading { font-size:1rem; } /* original size */
+ +

Easier, isn't it? This works as of Internet Explorer 9 and in every other current browser, so please feel free to use this unit.

+ +
+

Note: You may notice Opera Mini does not support font sizing in rem. It will end up setting its own font size, so don't bother feeding it font units.

+
+ +

Why would I want to use proportional units?

+ +

Because you don't know when a browser is going to come around and refuse to zoom up text whose size is expressed in pixels. Also, check your website's statistics: you may receive visits from older browsers.

+ +

We would advise the following:

+ + + +
+

Note: Your mileage may vary. If you have to cater to older browsers, you'll have to use ems and do a bit more math.

+
+ +

Line width

+ +

There is a longstanding debate about line length on the web, but here's the story. Back when we had newspapers, printers realized that the reader's eyes would have trouble going from one line to the next if the lines were too long. The solution? Columns.

+ +

Of course the problem doesn't go away when we switch to the Web. The reader's eyes act like a shuttle going from line to line. To make it easier on people's eyes, limit line width to around 60 or 70 characters.

+ +

To achieve this, you can specify a size for your text's container. Let's consider this HTML:

+ +
<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Font size experiment</title>
+</head>
+<body>
+
+<div class="container">
+    <h1>This is our main heading
+        <span class="subheading">This is our subheading</span>
+    </h1>
+
+    <p>[lengthly text that spans many lines]</p>
+</div>
+
+</body>
+</html>
+ +

We have a div with class container. We can style the div either to set its width (using the width property) or its maximum width so that it never gets too large (using the max-width property). If you want an elastic/responsive website, and you don't know what the browser's default width is, you can use the max-width property to allow up to 70 characters per line and no more:

+ +
div.container { max-width:70em; }
+ +

Alternative content for images, audio, and video

+ +

Websites often include stuff besides plain text.

+ +

Images

+ +

Images can be either decorative or informative, but there's no guarantee that your users can see them. For example,

+ + + +
+
Decorative images
+
They're just for decoration and don't convey any real information. They could most often be replaced by a background image. Make sure they feature an empty alt attribute: <img src="deco.gif" alt=""> so they don't clog up the text.
+
Informative images
+
They are used to convey information, hence their name. They can, for instance, feature a graph, or show a person's gesture, or any other information. At minimum, you must provide a relevant alt attribute.
+
+ +

If the image can be described succinctly, you can provide an alt attribute and nothing more. If the image cannot be described succinctly, you will have to either provide the same content in another form in the same page (e.g., complement a pie chart with a table providing the same data), or resort to a longdesc attribute. This attribute's value is a URL pointing towards a resource explicitly describing in detail the image's content.

+ +
+

Note: the use and even the existence of longdesc has been debated for quite some time. Please refer to the W3C's Image Description Extension (longdesc) for the full explanation and thorough examples.

+
+ +

Audio/video

+ +

You must also provide alternatives to multimedia content.

+ +
+
Subtitling/close-captioning
+
You should include captions in your video to cater to visitors who can't hear the audio. Some users have hearing challenges, lack functioning speakers, or work in a noisy environment (like on the train).
+
Transcript
+
Subtitles only work if somebody watches the video. Many users don't have time, or lack the proper plugin or codec. Additionally, search engines rely mainly on text to index your contents. For all these reasons, please provide a text transcript of the video/audio file.
+
+ +

Image compression

+ +

Some users may choose to display images, but still have limited bandwidth available, especially in developing countries and on mobile devices. If you want a successful website, please compress your images. There are various tools to help you, either online or local:

+ + diff --git a/files/ja/learn/common_questions/how_does_the_internet_work/index.html b/files/ja/learn/common_questions/how_does_the_internet_work/index.html new file mode 100644 index 0000000000..73899c4026 --- /dev/null +++ b/files/ja/learn/common_questions/how_does_the_internet_work/index.html @@ -0,0 +1,99 @@ +--- +title: インターネットはどのように動くのか +slug: Learn/Common_questions/How_does_the_Internet_work +tags: + - WebMechanics + - チュートリアル + - 初心者 +translation_of: Learn/Common_questions/How_does_the_Internet_work +--- +
{{LearnSidebar}}
+ +
+

この記事はインターネットの仕組みとどのように動いているかを説明します。

+
+ + + + + + + + + + + + +
前提条件:ありませんが、最初にプロジェクトの目標を設定することの記事を先に読むことをおすすめします。
目的:Web の技術インフラストラクチャの基礎と、インターネットと Web の違いについて学びます。
+ +

概要

+ +

インターネットは Web のバックボーンであり、Web を可能にする技術基盤です。最も基本的なインターネットは、すべてが一元的に通信を行う大規模なコンピュータネットワークです。

+ +

インターネットの歴史はやや曖昧です。1960年代に米軍の資金援助を受けて始まった調査プロジェクトに始まり、多くの大学と民間企業の支援を受けて1980年代に公共インフラへと発展しました。インターネットを支える様々なテクノロジーは時間の経過とともに進化してきましたが、大きくは変わっていません。インターネットは、コンピュータを一元的に接続し、何が起きても接続を維持する方法を見つけます。

+ +

アクティブ・ラーニング

+ + + +

より深く

+ +

単純なネットワーク

+ +

2つのコンピューターが通信を必要とする時、物理的に (通常はイーサネットケーブル) や無線 (WiFiBluetooth など) で接続する必要があります。現在のすべてのコンピュータでは通信を維持することができます。

+ +
+

注記 : 残りの記事では物理ケーブルのみ説明を行いますが、無線ネットワークでも同じように動きます。

+
+ +

Two computers linked together

+ +

このようなネットワークでは2つのコンピューターという制限はありません。あなたの望むように多くのコンピューターに接続することができます。しかしそれはすぐに複雑になります。例えば 10 台のコンピューターに接続しようとした場合、45 本のケーブルとそれぞれのコンピューターに 9 つのプラグ差込口が必要になります。

+ +

Ten computers all together

+ +

この問題を解決するために、それぞれのコンピュータがルーターと呼ばれる特別な小さなコンピュータにつなぎます。このルータは一つの仕事だけを行います:電車の信号機のように、特定のコンピュータから送信されたメッセージが正しい宛先コンピュータに到着することを確認します。 コンピュータ B に メッセージを送信するには、コンピュータ A がメッセージをルータに送信し、メッセージをコンピュータ B に転送し、コンピュータ C にメッセージが配信されないようにする必要があります。

+ +

一度ルーターをシステムに追加すると、ネットワークに繋がる 10 個のコンピュータは 10 個のケーブルが必要です。またそれぞれのコンピューターに一つのプラグ差込口が必要でルーターには 10 個のプラグ差込口が必要です。

+ +

Ten computers with a router

+ +

ネットワークのネットワーク

+ +

ここまでは順調ですね。しかし何百、何千、何十億ものコンピュータを接続する場合はどうですか?もちろん、1台のルーターではそれほど規模を拡大することはできませんが、注意深く読んだ場合、ルーターは他のコンピュータと同じようにコンピュータと呼ばれており、2台のルーターを接続するのに問題はないのでしょうか?何も問題はありません。では、繋いでみましょう。

+ +

Two routers linked together

+ +

コンピュータをルータに、そしてルータをルータに接続することで、無限に拡張することができます。

+ +

Routers linked to routers

+ +

このようなネットワークは、私たちがインターネットと呼ぶものに非常に近いものですが、何かが欠けています。私たちは自分自身の目的のためにそのネットワークを構築しました。一方で他のネットワークもあります:あなたの友人、あなたの隣人、誰もが自分のコンピュータのネットワークを持つことができます。しかし、あなたの家と世界の間にケーブルを設置することは実際には可能ではありません。どうすればよいでしょうか? 想像してください。あなたの家には電力や電話などといったもののケーブルが接続されています。電話のインフラはすでに世界中の誰かとあなたの家を接続していますので、私たちが欲しい完璧なワイヤーです。 私たちのネットワークを電話インフラに接続するには、モデムと呼ばれる特別な機器が必要です。 このモデムは、私たちのネットワークからの情報を、電話インフラストラクチャによって管理可能な情報に変換します。また、逆もしかりです

+ +

A router linked to a modem

+ +

電話のインフラに接続します。次のステップは、私たちのネットワークから接続できるネットワークにメッセージを送信することです。そのために、ネットワークをインターネットサービスプロバイダ (Internet Service Provider:以下 ISP ) に接続します。ISP は、すべてをリンクする特別なルーターを管理する会社で、他のISPのルータにもアクセスできます。 したがって、私たちのネットワークからのメッセージは、ISP ネットワークのネットワークを通して宛先のネットワークに運ばれます。インターネットは、このネットワーク全体のインフラで構成されています。

+ +

Full Internet stack

+ +

コンピューターを探す

+ +

もしコンピューターにメッセージを送りたい場合、どれかを特定する必要があります。 したがって、ネットワークにリンクしたコンピュータは、自身を識別するための固有のアドレスがあり、これは「IPアドレス」(IP はインターネットプロトコルを意味します) と呼ばれます。これは、ドットで区切られた一連の4つの数字からなるアドレスです (例 : 192.168.2.10)。

+ +

それはコンピュータにとって完璧ですが、このようなアドレスを人間が覚えることは難しいです。そこで簡単にするために、ドメイン名と呼ばれる人間がわかりやすい名前で IP アドレスを置き換えることができます。例えばgoogle.com はトップの IP アドレス173.194.121.32で使用されるドメイン名です。ドメイン名を使用することは、インターネット経由でコンピュータにアクセスする最も簡単な方法です。

+ +

Show how a domain name can alias an IP address

+ +

インターネットとウェブ

+ +

ご存知のとおり、Web ブラウザで Web を閲覧する場合、通常はドメイン名を使用して Web サイトにアクセスします。これはインターネットとウェブが同じであることを意味するのでしょうか?実はそれほど単純な話ではありません。私たちが見てきたように、インターネットは何十億ものコンピュータをすべて接続できる技術インフラです。これらのコンピュータの中には、一部のコンピュータ (Web サーバーと呼ばれる) が Web ブラウザに分かりやすいメッセージを送信することができます。インターネットはインフラですが、Web はインフラの上に構築されたサービスです。 電子メールや {{Glossary("IRC")}} など、インターネット上に構築されたいくつかのサービスがあります。

+ +

次のステップ

+ + diff --git a/files/ja/learn/common_questions/how_much_does_it_cost/index.html b/files/ja/learn/common_questions/how_much_does_it_cost/index.html new file mode 100644 index 0000000000..d931cb0900 --- /dev/null +++ b/files/ja/learn/common_questions/how_much_does_it_cost/index.html @@ -0,0 +1,155 @@ +--- +title: Web で何かをするためにどのくらいコストがかかりますか? +slug: Learn/Common_questions/How_much_does_it_cost +translation_of: Learn/Common_questions/How_much_does_it_cost +--- +
+

Web に参加することは、見かけほど容易ではありません。この記事では、あなたがどのくらい費用をかける必要があるのか、そしてその理由について説明します。

+
+ + + + + + + + + + + + +
学習の前提:どのソフトウェアが必要かWeb ページ、Web サイトなどの違いドメイン名とは何かを理解しているべきです。
学習の目標:Web サイトを作成するための完全なプロセスを確認し、各ステップにかかる費用を確認します。
+ +

要約

+ +

Web サイトを立ち上げるとき、費用は何も掛からないかもしれませんし、青天井かもしれません。 この記事では、費用の有無にかかわらず、どのように準備し、またどれだけ費用がかかるかについて議論します。

+ +

ソフトウェア

+ +

テキストエディタ

+ +

Windows のメモ帳、Linux の Gedit、Mac の TextEdit などのテキストエディタを使った経験はおありでしょう。色分けしたり、文法をチェックしたり、コードの構築を手助けしたりするエディタを選択すれば、コードを書くのが楽になります。

+ +

無料のエディタは多くあります。たとえば、AtomBracketsBluefishTextWranglerEclipseNetbeansなどです。またSublime Textのように好きなだけ試用できるが、料金を支払ったほうが良いものもあります。なかには、PhpStorm,のように、購入ライセンスによって、価格が数百円から2万円の間になるものもあります。Microsoft Visual Studioは数万円から数十万円しますが、Visual Studio Expressは個人やオープンソースプロジェクトでは無料で使えます。 有料ソフトウエアには、無料の試用期間を設けているものもあります。

+ +

最初に何種類かのエディタを試して、用途に合うのはどれか調べるといいでしょう。T {{Glossary("HTML")}}や{{Glossary("CSS")}}、それに{{Glossary("Javascript")}}で簡単なコードを書くのであれば、単純なエディタをお勧めします。

+ +

テキストエディタの品質と使いやすさは、あまり価格と連動しません。実際に使ってみて、目的に合うか調べるようにしてください。例えばSublime Textは安価ですが、多くの無料プラグインがあり、拡張性が高いエディタです。

+ +

画像エディタ

+ +

あなたが使用しているシステムには、単純な画像編集ソフトまたはビューアーが搭載されているでしょう。WindowsではPaint、UbuntuではEye of Gnome、MacではPreviewです。これらのプログラムは比較的制限されているので、レイヤー、エフェクト、およびグループ化を追加するなどのために高機能なエディタが、すぐに必要になります。

+ +

編集ソフトは無料 (GIMP, Paint.NET)、やや高価 (PaintShop Pro, less than $100)、または数百ドル (Adobe Photoshop)のものもあります。

+ +

これらは似たような機能を持っているので、どれを使用しても構いません。この中には様々な機能を網羅しているソフトもありますが、すべての機能を使う日は決して来ないでしょう。 ある時点で他の設計者とプロジェクトを交換する必要がある場合は、彼らがどのツールを使用しているかを調べる必要があります。 編集ソフトは完成したプロジェクトを標準のファイル形式にエクスポートできますが、各編集ソフトは進行中のプロジェクトを独自の特別な形式で保存します。 インターネット上のほとんどの画像は著作権で保護されているので、使用する前にファイルのライセンスを確認することをお勧めします。 Pixabay のようなサイトは、CC0ライセンスの下で画像提供を行なっているので、商用利用のための変更・編集を加えても公開することができます。

+ +

メディアエディタ

+ +

If you want to include video or audio into your website, you can either embed online services (for example YouTube, Vimeo, or Dailymotion), or include your own videos (see below for bandwidth costs).

+ +

For audio files, you can find free software (Audacity, Wavosaur), or paying up to a few hundred dollars (Sony Sound Forge, Adobe Audition). Likewise, video-editing software can be free (PiTiVi, OpenShot for Linux, iMovie for Mac), less than $100 (Adobe Premiere Elements), or several hundred dollars (Adobe Premiere Pro, Avid Media Composer, Final Cut Pro). The software you received with your digital camera may cover all your needs.

+ +

パブリッシングツール

+ +

You also need a way to upload files: from your hard drive to a distant web server. To do that you should use a publishing tool such as an (S)FTP client, RSync, or Git/GitHub.

+ +

Each operating system includes an (S)FTP client, as part of its file manager. Windows Explorer, Nautilus (a common Linux file manager), and the Mac Finder all include this functionality. However, people often choose dedicated (S)FTP clients to display local or remote directories side-by-side and store server passwords.

+ +

If you want to install an (S)FTP client, there are several reliable and free options: for example, FileZilla for all platforms, WinSCP for Windows, Cyberduck for Mac or Windows, and more.

+ +

Because FTP is inherently insecure, you should make sure to use SFTP — the secure, encrypted version of FTP that most hosting sites you'll deal with these days will offer by default — or another secure solution like Rsync over SSH.

+ +

ブラウザ

+ +

あなたはすでにブラウザを持っているか、無料でそれを手に入れることができます。必要に応じて、ここから Firefox または Google Chrome をダウンロードしてください。

+ +

Web アクセス

+ +

コンピュータ / モデム

+ +

You need a computer. Costs can vary tremendously, depending on your budget, and where you live. To publish a barebones website, you only need a basic computer capable of launching an editor, and a Web browser, so the entry level can be quite low.

+ +

Of course, you'll need a more serious computer if you want to produce complicated designs, touch up photos, or produce audio and video files.

+ +

You need to upload content to a remote server (see Hosting below), so you need a modem. Your {{Glossary("ISP")}} can rent Internet connectivity to you for a few dollars per month, though your budget might vary, depending on your location.

+ +

ISP access

+ +

Make sure that you have sufficient {{Glossary("Bandwidth", "bandwidth")}}:

+ + + +

Hosting

+ +

Understanding bandwidth

+ +

Hosting providers charge you according to how much {{Glossary("Bandwidth", "bandwidth")}} your website consumes. This depends on how many people, and Web crawling robots, access your content during a given time, and how much server space your content takes up. This is why people usually store their videos on dedicated services such as Youtube, Dailymotion, and Vimeo. For example, your provider may have a plan that includes up to several thousand visitors per day, for “reasonable” bandwidth usage. Be careful, however as this is defined differently from one hosting provider to another. As a rule of thumb, recognize that reliable, paid, personal hosting can cost around ten to fifteen dollars per month.

+ +
+

Note that there is no such thing as “unlimited” bandwidth. If you consume a huge amount of bandwidth, expect to pay a huge amount of money.

+
+ +

Domain names

+ +

Your domain name has to be purchased through a domain name provider (a registrar). Your hosting provider may also be a registrar (1&1, Gandi for instance are at the same time registrars and hosting providers). The domain name usually costs $5-15 per year. This cost varies depending on:

+ + + +

Do-it-yourself hosting vs. “packaged” hosting

+ +

When you want to publish a website, you could do everything by yourself: set up a database (if needed), Content Management System, or {{Glossary("CMS")}} (like Wordpress, Dotclear, spip, etc.), upload pre-made or your own templates.

+ +

You could use your hosting provider's environment, for roughly ten to fifteen dollars per month, or subscribe directly to a dedicated hosting service with pre-packaged CMSs (e.g., Wordpress, Tumblr, Blogger). For the latter, you won't have to pay anything, but you may have less control over templating and other options.

+ +

Free hosting vs. paid hosting

+ +

You might ask, why should I pay for my hosting when there are so many free services?

+ + + +

It is better to go for paid hosting rather than relying on free hosting, as it is possible to move your files easily and uptime is guaranteed by most paid sites. Most hosting providers give you a huge discount to start with.

+ +

Some people opt for a mixed approach. For example, their main blog on a paid host with a full domain name, and spontaneous, less strategic, content on a free host service.

+ +

Professional website agencies and hosting

+ +

If you desire a professional website, you will likely ask a web agency to do it for you.
+
+ Here, costs depend on multiple factors, such as:

+ + + +

...and for hosting:

+ + + +

Depending on how you answer these questions, your site could cost thousands to hundreds of thousands of dollars.

+ +

Next steps

+ +

Now that you understand what kind of money your website may cost you, it's time to start designing that website and setting up your work environment.

+ + diff --git a/files/ja/learn/common_questions/html_features_for_accessibility/index.html b/files/ja/learn/common_questions/html_features_for_accessibility/index.html new file mode 100644 index 0000000000..4139cf51e8 --- /dev/null +++ b/files/ja/learn/common_questions/html_features_for_accessibility/index.html @@ -0,0 +1,55 @@ +--- +title: アクセシビリティをよくする HTML の機能にはどんなものがある? +slug: Learn/Common_questions/HTML_features_for_accessibility +tags: + - Accessibility + - Beginner + - HTML + - Learn + - NeedsContent +translation_of: Learn/Common_questions/HTML_features_for_accessibility +--- +

{{draft}}

+ +

以下のコンテンツは、さまざまな障害を持つ人々にとってウェブページをよりアクセシブルにするために使用できる HTML の特定の機能について説明しています。

+ +

タブ移動

+ +

ポインティングデバイスを使用しない、または使用できないユーザーは、リンクを Tab で移動できます。なので、リンクは論理的なタブ移動の順序になっている必要があります。tabindex 属性を使用すると、この順序を定義できます。HTML が線形である場合(そうあるべきなのですが)、論理的なタブ移動の順序は自動的に正しい位置に配置されるはずです。

+ +
<ul>
+  <li><a href="here.html" tabindex="1">Here</a></li>
+  <li><a href="there.html" tabindex="3">There</a></li>
+  <li><a href="anywhere.html" tabindex="2">Anywhere</a></li>
+</ul>
+ +

この例(これは純粋にデモンストレーションとして使用されています - こうはしないでください)では、タブは "Here" から "Anywhere" 、"There" の順にジャンプします。

+ + + +

自己記述的ではないリンクがある場合、またはリンク先がより詳細に説明されていることでメリットが得られる場合は、title 属性を使用してリンクに情報を追加できます。

+ +
<p>I'm really bad at writing link text. <a href="inept.html" title="Why I'm rubbish at writing link text: An explanation and an apology.">Click here</a> to find out more.</p>
+ +

アクセスキー

+ +

アクセスキーを使用すると、キーボードショートカットをリンクに割り当てることができ、ナビゲーションが簡単になります。通常、ユーザーが Alt キーまたは Ctrl キーを押しながらアクセスキーを押すとフォーカスが移動します。正確なキーの組み合わせはプラットフォームによって変わります。

+ +
<a href="somepage.html" accesskey="s">Some page</a>
+ + + +

タブ移動を補助するために、ユーザーがあなたのウェブページの大きな塊を飛び越えることを可能にするリンクを提供することができます。たとえば、ユーザーが多すぎるナビゲーションリンクを飛び越えて、すべてのリンクを巡回するのではなくページのメインコンテンツを読むことができるようにしたい場合があります。

+ +
<header>
+  <h1>The Heading</h1>
+  <a href="#content">Skip to content</a>
+</header>
+
+<nav>
+  <!-- navigation stuff -->
+</nav>
+
+<section id="content">
+  <!--your content -->
+</section>
diff --git a/files/ja/learn/common_questions/index.html b/files/ja/learn/common_questions/index.html new file mode 100644 index 0000000000..d9990bb91e --- /dev/null +++ b/files/ja/learn/common_questions/index.html @@ -0,0 +1,136 @@ +--- +title: よくある質問 +slug: Learn/Common_questions +tags: + - CodingScripting + - Infrastructure + - Learn + - Web + - WebMechanics +translation_of: Learn/Common_questions +--- +
{{LearnSidebar}}
+ +

学習エリアのこのセクションでは、浮かんでくるかもしれないけれども、学習ルートの本筋 (例 HTMLCSS 学習記事) には必要でもない、よくある質問への回答を載せるために作りました。この記事は単独でこれだけを読んでも理解できるものになっています。

+ +

ウェブはどのように動いているのか

+ +

このセクションでは、ウェブのメカニズムについてのウェブのエコシステムや動作に関係する質問に答えます。

+ +
+
+

インターネットはどうやって動いているの?

+
+
+ +
+
インターネットは、ウェブの骨組みで、ウェブを可能としている技術的なインフラです。ごく簡単に言うと、インターネットとは、おたがいに通信しあうたくさんのコンピューターが繋がってできた巨大なネットワークです。この記事では、おおまなにインターネットがどのように動いているのかを説明します。
+
+

ウェブページ、ウェブサイト、ウェブサーバー、検索エンジン、これらは何が違うの?

+
+
この記事では、ウェブページ、ウェブサイト、ウェブサーバー、検索エンジンなどの、ウェブに関係するいろいろな考えについて話します。これらの用語は、ウェブに馴染みのない人にとって、よく混同されたり間違って使われる元になっています。それぞれの意味を発見していきましょう!
+
+ +
+
この記事では、ハイパーリンクがどのようなもので、なぜ大切なのかを説明しています。
+
+

URL って何?

+
+
{{Glossary("Hypertext")}} と {{Glossary("HTTP")}} では、URL とはインターネットのキーとなる考えです。URL は {{Glossary("Browser","ブラウザー")}} が利用する仕組みで、ウェブ上にあるあらゆるリソースを手に入れるために使われます。
+
+

ドメイン名って何?

+
+
ドメイン名は、インターネットのインフラにとって大切なパーツの一つです。インターネット上のウェブサーバーのために、人が読みやすいアドレスを使えるようにしてくれます。
+
+

ウェブサーバーって何?

+
+
「ウェブサーバー」という言葉は、ウェブ上でクライアントにウェブサイトを送信するハードウェアまたはソフトウェアを指します。ときにはその両方を指します。この記事では、ウェブサーバーがどのように動いていて、どうして大切なのかを説明しています。
+
+ +

ツールとセットアップ

+ +

ウェブサイトを作るためのツールやソフトウェアに関係する質問です。

+ +
+
+

ウェブサイトを作るにはどんなソフトウェアが必要?

+
+
この記事では、ウェブサイトの編集、アップロード、閲覧に、それぞれどのようなソフトウェアコンポーネントが必要になるか説明します。
+
+

ウェブ上で何かをするのにどれくらいお金がかかるの?

+
+
ウェブサイトを立ち上げる場合、いっさいお金をかけずにすむこともあれば、高額な費用がかかることもあります。この記事では、ウェブ開発で使用するツールやサービスにどれくらい費用がかかるか、お金をかけた場合、かけなかった場合に、それぞれどのようなことができるか、を説明します。
+
+

どんなテキストエディタが必要?

+
+
この記事では、ウェブ開発で使用するテキストエディタを選択、インストールするときに、考慮すべき点について取り上げます。
+
+

ブラウザーの開発者ツールとは何?

+
+
すべてのブラウザーには、HTML、CSS、その他のウェブ用コードをデバッグするための開発者ツールが用意されています。この記事では、お使いのブラウザーの開発者ツールの基本機能の使い方について説明します。
+
+

ウェブサイトが意図したとおりに動作しないとき、どうすればいい?

+
+
あなたが開発してオンラインに公開したウェブサイト、本当に意図したとおりに動作していますか? この記事では、基本的なトラブルシューティングの手順について説明します。
+
+

ローカル環境にテスト用サーバーを用意するには、どうすればいい?

+
+
この記事では、使用中のマシンにローカルテスト用のサーバーを準備し、使用する方法について説明します。
+
+

ウェブサーバーにファイルをアップロードするにはどうすればいい?

+
+
+ +
+
ウェブサイトをオンラインで公開して、別のコンピューターからアクセスできるようにするには、FTP ツールがよく使用されます。この記事では、FTP ツールを使ってウェブサイトを公開する方法を説明します。
+
+

GitHub ページを使うにはどうすればいい?

+
+
この記事では、GitHub の GitHub ページ (gh-pages) 機能を使ってコンテンツを公開する方法を説明します。
+
+

Google App Engine を使ってウェブサイトを公開するにはどうすればいい?

+
+
作成したウェブサイトを配置する場所をお探しですか? この記事では、Google App Engine を使ってウェブサイトを公開する (ホスティングする) 手順を説明します。
+
+

ウェブサイトのデバッグ/パフォーマンス向上に役立つツールにはどのようなものがある?

+
+
リンク先では、FireFox の開発者ツールを使って、ウェブサイトのデバッグ、パフォーマンス向上を行うための記事が一覧にまとめられています。これらの記事では、メモリーの使用状況、JavaScript の呼び出しツリー、レンダリングされた DOM ノードの数、その他について確認する方法などが紹介されています。
+
+ +

デザインとアクセシビリティ

+ +

このセクションでは、ページのデザイン、ページ構成、アクセシビリティについての質問などを取り上げています。

+ +

ウェブサイトの設計では何から始めればいい?

+ +
+
この記事では、すべてのプロジェクトにおいてきわめて重要な第一歩、「そのプロジェクトで何を実現したいのか」を定義する方法を説明します。
+
+

よくあるウェブページのレイアウトには何が含まれてる?

+
+
ウェブサイトを設計するとき、まずは一般的なレイアウトについて知っておくとよいでしょう。この記事では、よくあるウェブレイアウトについていくつか取り上げ、どのような要素で構成されているかを見ていきます。
+
+

アクセシビリティって何?

+
+
この記事では、ウェブアクセシビリティの基本的な概念について紹介します。
+
+

どんなユーザーでも使えるようにデザインするにはどうすればいい?

+
+
この記事では、どのようなユーザーでも利用できるウェブサイトを作成するための基本的なテクニックを説明します。これには、手軽にアクセシビリティを実現する方法や、その他の情報などが含まれます。
+
+

アクセシビリティをよくする HTML の機能にはどんなものがある?

+
+
この記事では、さまざまな障害をもつユーザーがよりウェブサイトを利用しやすいよう使用される、各種の HTML の機能について説明します。
+
+ +

HTML、CSS、JavaScript の質問

+ +

HTML/CSS のよくある問題の解決方法については、次の記事を読んでみてください。

+ + diff --git a/files/ja/learn/common_questions/pages_sites_servers_and_search_engines/index.html b/files/ja/learn/common_questions/pages_sites_servers_and_search_engines/index.html new file mode 100644 index 0000000000..34646a106f --- /dev/null +++ b/files/ja/learn/common_questions/pages_sites_servers_and_search_engines/index.html @@ -0,0 +1,120 @@ +--- +title: ウェブページ、ウェブサイト、ウェブサーバー、検索エンジンの違いは? +slug: Learn/Common_questions/Pages_sites_servers_and_search_engines +tags: + - NeedsActiveLearning + - WebMechanics + - 初心者 +translation_of: Learn/Common_questions/Pages_sites_servers_and_search_engines +--- +
+

この記事では、ウェブページ、ウェブサイト、ウェブサーバー、検索エンジンなどのウェブに関係する色々な概念に関して解説します。これらの用語はウェブの初心者を混乱させたり、間違って使われたりしています。それぞれの意味を学びましょう。

+
+ + + + + + + + + + + + +
前提条件:インターネットはどのように動くのかを知っておく必要があります。
目的:ウェブページ、ウェブサイト、ウェブサーバー、検索エンジンの違いを説明できるようになること。
+ +

要約

+ +

あらゆる分野の知識と同様に、ウェブにも多くの専門用語があります。すべてを一気に押し付けるつもりはありませんのでご心配なく (興味をお持ちなら用語集があります)。しかし、最初に理解しておく必要がある基本的な用語がいくつかあり、これは読む際に常に聞く表現です。これらは互いに関連するものの、異なる役割を持つため、混同しやすいものです。実際、ニュースやその他の場所でこれらの用語が誤って使用されているのを時々見かけるので、これらをまとめて理解しましょう。

+ +

これらの用語と技術の詳細に関して詳しく説明しますが、これらを簡単に定義することが良いスタートるになるでしょう。

+ +
+
ウェブページ
+
Firefox や Google Chrome、Opera、Microsoft Internet Explorer、Edge、Apple の Safari などのウェブブラウザーで表示可能な文書です。これらはよく単に「ページ」とも呼ばれることもあります。
+
ウェブサイト
+
グループ化され、通常はさまざまな方法で一緒に接続されたウェブページの集まりです。よく「ウェブサイト」または単に「サイト」と呼ばれます。
+
ウェブサーバー
+
インターネット上でウェブサイトをホスティングするコンピューターです。
+
検索エンジン
+
他のウェブページを見つけるのに役立つウェブサービスで、 Google、Bing、Yahoo、DuckDuckGo などがあります。検索エンジンは通常、ウェブブラウザーから (例えば、Firefox、Chrome などのアドレスバーで直接検索エンジンによる検索を実行することができる)、またはウェブページ (例えば bing.comduckduckgo.com) を介してアクセスされます。
+
+ +

公共図書館に簡単に例えてみましょう。図書館に行ったときに一般的に行うことは次の通りです。

+ +
    +
  1. 検索インデックスを探して、読みたい書籍のタイトルを探します。
  2. +
  3. その書籍のカタログ番号をメモします。
  4. +
  5. 書籍が収蔵されている特定の書架へ行き、カタログ番号を見つけて、本を入手します。
  6. +
+ +

ウェブサーバーと図書館を比較してみましょう。

+ + + +

アクティブラーニング

+ +

利用可能なアクティブラーニングはまだありません。ぜひ協力をご検討ください

+ +

より深い追求

+ +

それでは、それらの 4 つの用語がどのように関連しているのか、なぜそれらが互いに混同されているのかについて詳しく調べてみましょう。

+ +

ウェブページ

+ +

ウェブページは{{Glossary("browser","ブラウザー")}}で表示することができる簡単な文書です。文書は {{Glossary("HTML")}} 言語で書かれています (他の記事で詳しく説明しています)。ウェブページには、次のような様々な種類のリソースを埋め込むことができます。

+ + + +
+

メモ: ブラウザーは {{Glossary("PDF")}} ファイルや画像などのような他の文書も表示することができますが、ウェブページという用語は、特に HTML 文書を指します。それ以外の場合、単に文書 (またはドキュメント) という用語を使用します。

+
+ +

ウェブ上で利用可能なすべてのウェブページには、固有のアドレスを使用して到達することができます。ページにアクセスするには、そのアドレスをブラウザーのアドレスバーに入力するだけです。

+ +

ブラウザーのアドレスバーにあるウェブページのアドレスの例

+ +

ウェブサイト

+ +

ウェブサイトはリンクされたウェブページ (および関連するリソース) の集合で、固有のドメイン名を共有しています。指定されたウェブサイトの各ウェブページは明示的なリンク — 多くの場合はクリック可能なテキストの部分の形 — を提供しており、ユーザーがウェブサイトのあるページから他のページに移動することができます。

+ +

ウェブサイトにアクセスするために、ブラウザーのアドレスバーにドメイン名を入力すると、ブラウザーはウェブサイトのメインウェブページ、またはホームページ (略して「ホーム」と呼ばれる) を表示します。

+ +

ブラウザーのアドレスバーにあるウェブサイトのドメイン名の例

+ +

ウェブページウェブサイトは、特に1枚だけのウェブページを含むウェブサイトである場合に混同しやすくなります。このようなウェブサイトは単一ページのウェブサイトと呼ばれることがあります。

+ +

ウェブサーバー

+ +

ウェブサーバーは、1つ以上のウェブサイトをホスティングするコンピューターです。「ホスティング」はすべてのウェブページや補助的なファイルをコンピューター上で利用できるようにするという意味です。ウェブサーバーは、任意のユーザーのリクエストに応じて、ホスティング中のウェブサイトから任意のウェブページをユーザーのブラウザーに送信します。

+ +

ウェブサイトウェブサーバーを混同しないようにしてください。例えば、誰かが「私のウェブサイトから応答がありません」と言うのを聞いた場合、実際にはウェブサーバーが応答していないのであり、その結果としてウェブサイトが利用できないのです。もっと重要なことは、ウェブサーバーは複数のウェブサイトをホスティングすることができるため、ウェブサーバーという言葉はウェブサイトを特定するために使用することはできず、大きな混乱を招く可能性があります。先に挙げた例で、「私のウェブサイトから応答がありません」と言った場合、そのウェブサーバー上のウェブサイトがすべて利用できないことになります。

+ +

検索エンジン

+ +

検索エンジンはよくウェブに関する誤解のもとになります。検索エンジンは特殊な種類のウェブサイトで、ユーザーが他のウェブサイトを見つけるのを助けるものです。

+ +

Google, Bing, Yandex, DuckDuckGo など、たくさんあります。一般的なものもあれば、特定のトピックについて専門化されたものもあります。好きなものを使いましょう。

+ +

多くのウェブの初心者は、検索エンジンとブラウザーを混同しています。明確にしましょう。ブラウザーはソフトウェアの一つで、ウェブページを受け取り表示するものです。検索エンジンはウェブサイトであり、人々が他のウェブサイトからウェブページを探すのを手助けします。この混乱は、ブラウザーを起動したとき、ブラウザーが検索エンジンのホームページを表示しているために発生します。これは、ブラウザーで最初にやりたいことが表示させるウェブページであることが明らかであるため、よく分かります。インフラ (ブラウザーなど) とサービス (検索エンジンなど) を混同しないでください。この区別はかなり役立ちますが、専門家によっては曖昧に話すこともあるので、心配しないでください。

+ +

こちらは、 Firefox のインスタンスが既定のスタートアップページとして Google 検索ボックスを表示している様子です。

+ +

Example of Firefox nightly displaying a custom Google page as default

+ +

次の段階

+ + diff --git a/files/ja/learn/common_questions/set_up_a_local_testing_server/index.html b/files/ja/learn/common_questions/set_up_a_local_testing_server/index.html new file mode 100644 index 0000000000..fc0c346dfd --- /dev/null +++ b/files/ja/learn/common_questions/set_up_a_local_testing_server/index.html @@ -0,0 +1,110 @@ +--- +title: ローカルのテストサーバーはどのようにセットアップしますか? +slug: Learn/Common_questions/set_up_a_local_testing_server +tags: + - Express + - Flask + - Node + - PHP + - Python + - django + - lamp + - サーバ + - サーバーサイド + - 初心者 + - 学習 +translation_of: Learn/Common_questions/set_up_a_local_testing_server +--- +
+

この記事では、マシン上に簡単なローカルテストサーバを設定する方法と、その使い方の基本について説明します。

+
+ + + + + + + + + + + + +
前提条件:最初にインターネットの仕組みWeb サーバについて知っておく必要があります。
目的:ローカルのテストサーバを設定する方法を学習します。
+ +

ローカルファイルとリモートファイル

+ +

ほとんどの学習領域では、ブラウザでサンプルを直接開くだけで済みます。HTML ファイルをダブルクリックするか、ブラウザウィンドウにドラッグ & ドロップするか、ファイル > 開く...を選択して HTML ファイルを選択するなどです。これを達成する方法はたくさんあります。

+ +

Web アドレスのパスが file:// で始まり、その後にローカルハードドライブのファイルへのパスが続く場合、ローカルファイルが使用されています。対照的に、GitHub でホストされている例 (または他のリモートサーバの例) を見ると、Web アドレスは http:// または https:// で始まっており、ファイルが HTTP 経由で受信されたことを示します。

+ +

ローカルファイルのテストに関する問題

+ +

一部のサンプルはローカルファイルとして開くと実行されません。これにはさまざまな理由があります。最も可能性が高いのは、

+ + + +

シンプルなローカル HTTP サーバの実行

+ +

非同期リクエストの問題を回避するには、ローカル Web サーバを介して実行することによって、そのようなサンプルをテストする必要があります。私たちの目的のためにこれを行う最も簡単な方法の1つは、Python の SimpleHTTPServer モジュールを使うことです。

+ +

これをするためには:

+ +
    +
  1. +

    Python をインストールします。Linux または Mac OS X を使用している場合は、既にシステム上で使用可能になっているはずです。Windows ユーザの方は、Python ホームページからインストーラを入手し、インストーラの指示に従ってインストールすることができます:

    + +
      +
    • python.org に進みます
    • +
    • ダウンロードセクションの下で、Python "3.xxx" のリンクをクリックします
    • +
    • ページ下部の Windows x86 実行可能インストーラを選択してダウンロードします
    • +
    • ダウンロードしたら、それを実行します
    • +
    • インストーラの最初のページで、"Add Python 3.xxx to PATH" チェックボックスをオンにします
    • +
    • [インストール]をクリックし、インストールが完了したら[閉じる]をクリックします
    • +
    +
  2. +
  3. +

    コマンドプロンプト (Windows)/ターミナル (OS X/Linux) を開きます。Python がインストールされていることを確認するには、次のコマンドを入力します

    + +
    python -V
    +
  4. +
  5. +

    これによりバージョン番号が返されます。OK の場合は、cd コマンドを使用してサンプルが入っているディレクトリに移動します

    + +
    # include the directory name to enter it, for example
    +cd Desktop
    +# use two dots to jump up one directory level if you need to
    +cd ..
    +
  6. +
  7. +

    ディレクトリの中でサーバを起動するコマンドを入力します

    + +
    # If Python version returned above is 3.X
    +python -m http.server
    +# If Python version returned above is 2.X
    +python -m SimpleHTTPServer
    +
  8. +
  9. +

    デフォルトでは、これはローカル Web サーバ上のディレクトリの内容を 8000 番ポート上で実行します。このサーバにアクセスするには、Web ブラウザで localhost:8000 のURL に移動します。ここにディレクトリの内容が表示されるので、実行する HTML ファイルをクリックします

    +
  10. +
+ +
+

メモ: すでに 8000 番ポートで何かが稼働している場合は、server コマンドを実行して別のポート番号を選択することができます。例えば python3 -m http.server 7800 (Python 3.x) または python -m SimpleHTTPServer 7800 (Python 2.x) です。これで localhost:7800 でコンテンツにアクセスできます。

+
+ +

サーバサイドの言語をローカルで実行する

+ +

Python の SimpleHTTPServer (python 2.0) http.server (python 3.0) モジュールは便利ですが、Python、PHP、JavaScript などの言語で書かれたコードの実行方法はわかりません。これを処理するには、必要なことがあります。必要なのは、実行しようとしているサーバサイドの言語に依存します。いくつかの例があります:

+ + + +
$ cd path/to/your/php/code
+$ php -S localhost:8000
diff --git a/files/ja/learn/common_questions/thinking_before_coding/index.html b/files/ja/learn/common_questions/thinking_before_coding/index.html new file mode 100644 index 0000000000..ec555fe4c4 --- /dev/null +++ b/files/ja/learn/common_questions/thinking_before_coding/index.html @@ -0,0 +1,177 @@ +--- +title: どのように Web サイトのデザインを始めるのか? +slug: Learn/Common_questions/Thinking_before_coding +tags: + - Beginner + - Composing + - NeedsActiveLearning + - needsSchema + - 初心者 +translation_of: Learn/Common_questions/Thinking_before_coding +--- +

この記事では、すべてのプロジェクトの重要な第一歩として、そのプロジェクトで達成したいことを定義します。

+ + + + + + + + + + + + +
前提条件なし
目的目標を定義してウェブプロジェクトの方向性を明らかにする方法を学びます。
+ +

概要

+ +

ウェブプロジェクトを開始するとき、多くの人が技術面に焦点を当てます。もちろん、作るものの技術に精通していなければなりませんが、本当に重要なことは何を達成したいかということです。そう、それは明らかなことのようですが、あまりにも多くのプロジェクトが技術的ノウハウがないためではなく、目標とビジョンがないために失敗します。

+ +

あなたがアイデアを得てそれをウェブサイトにしたいときには、何かをする前に答えるべきいくつかの質問があります:

+ + + +

これらはすべてプロジェクトのアイデア化と呼ばれ、初心者であれ、経験豊富な開発者であれ、目標を達成するための最初のステップです。

+ +

アクティブラーニング

+ +

アクティブラーニングはまだありません。Please, consider contributing.

+ +

より深いダイビング

+ +

プロジェクトは技術的側面から始まることはありません。ミュージシャンは、最初にプレイしたいことのアイデアがない限り、決して音楽を作ってはいけません。これは画家、作家、ウェブ開発者にとっても同じことです。テクニックは 2番目に来ます。

+ +

技術は明らかに重要です。ミュージシャンは楽器をマスターする必要があります。しかし、良いミュージシャンは、アイデアなしに良い音楽を生み出すことはできません。したがって、コードやツールなどの技術的な側面に飛び込む前に最初のステップに戻り、実行したいことを詳細に決定する必要があります。

+ +

はじめに友人と 1時間ディスカッションするのは良いことですが、不十分です。自分のアイデアを具現化するためにどのような道をたどらなければならないかを明確に把握するためには、座ってアイデアを体系化する必要があります。これを行うには、紙とペンと、少なくとも次の質問に答えるための時間が必要です。

+ +
+

メモ: プロジェクトのアイデア化を実行するための方法は無数にあります。ここにそれらすべてを提示することはできません (一冊の本では不十分です)。ここでは、プロフェッショナルがプロジェクトの理念プロジェクト計画、およびプロジェクト管理と呼ぶものを処理する簡単な方法を紹介します。

+
+ +

本当にしたいことは何ですか?

+ +

他のすべてを動かすので、これは答えるべき最も重要な問いです。到達したいすべての目標を列挙してください。お金を稼ぐための商品の販売、政治的意見の表明、新しい友達の会合、ミュージシャンとのギグ、猫の写真の収集など、それは何でもかまいません。

+ +

あなたがミュージシャンだとしましょう。あなたは次のことができます:

+ + + +

そのようなリストを取得したら優先順位を付ける必要があります。目標を最も重要なものからそうでないものに順番に並べます。

+ +
    +
  1. 新しいガールフレンド/ボーイフレンドを探す
  2. +
  3. 人々にあなたの音楽を聞いてもらう
  4. +
  5. あなたの音楽について話す
  6. +
  7. 他のミュージシャンに会う
  8. +
  9. グッズを売る
  10. +
  11. ビデオを通して音楽を教える
  12. +
  13. あなたの猫の写真を公開する
  14. +
+ +

このシンプルなエクササイズ−−目標を作成し、並び替えること−−は意思決定をするうえでの助けになります。(これらの機能を実装し、これらのサービスを使用して、これらのデザインを作成しますか?)

+ +

これで、優先順位付けされた目標リストが作成されたので、次の質問に移りましょう。

+ +

ウェブサイトを使ってどのように目標を達成する?

+ +

あなたは目標のリストを持っており、それらの目標を達成するためにウェブサイトが必要だと感じます。本気ですか?

+ +

例を振り返りましょう。音楽に関連する 5 つの目標があります。私生活に関連した1つの目標 (あなたの重要な他者を見つけること)、そして全く無関係の猫の写真です。これらすべての目標をカバーするために単一のウェブサイトを構築することは合理的ですか?それも必要ですか?結局のところ、既存のウェブサービスのスコアは、新しいウェブサイトを構築せずにあなたを目標に導くかもしれません。

+ +

ガール/ボーイフレンドを見つけることは、まったく新しいサイトを構築するのではなく、既存のリソースを使用することが理にかなっている主要なケースです。どうして?なぜなら、実際にガール/ボーイフレンドを探すよりも、ウェブサイトの構築と保守に多くの時間を費やすからです。私たちの目標は最も重要なものなので、ゼロから始めるのではなく、既存のツールを活用することに力を注ぐべきです。繰り返しになりますが、写真を紹介するためにすでにたくさんのウェブサ ービスが用意されているので、新しいサイトを構築するだけの価値はありません。

+ +

他の 5 つの目標はすべて音楽に関連しています。もちろん、これらの目標に対応できるウェブサービスは数多くありますが、この場合は専用のウェブサイトを構築することが理にかなっています。このようなウェブサイトは、私たちが 1 つの場所 (目標 3,5、および 6 に適しています) に公開し、私たちと公共の間の交流を促進する (目標2 と 4 に良い) すべてのものを集約する最良の方法です。一言で言えば、これらの目標はすべて同じトピックを中心にしているため、すべてを 1 か所にまとめて目標を達成し、フォロワーが私たちとつながるのを助けます。

+ +

ウェブサイトはどのように私の目標を達成するのに役立ちますか?それに答えることによって、あなたの目標に到達し、無駄な労力から自分自身を救う最良の方法を見つけることができます。

+ +

目標を達成するために何をどのような順序で実行する必要がありますか?

+ +

あなたが達成したいことが分かったら、今度はその目標を実行可能なステップに変えてください。副題として、あなたの目標は必ずしも石で設定されているわけではありません。プロジェクトの中でも、予期せぬ障害物が横切ったり、心が変わったりしても、時間の経過と共に進化します。

+ +

長い説明をするのではなく、この表の例に戻ってみましょう。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
目標すべきこと
人々にあなたの音楽を聞いてもらう +
    +
  1. 音楽を録音する
  2. +
  3. オンラインで使用可能なオーディオファイルをいくつか準備します (既存のウェブサービスでこれを行うことができますか?)
  4. +
  5. あなたのウェブサイトのどこかであなたの音楽に他の人がアクセスできるようにする
  6. +
+
あなたの音楽について話す +
    +
  1. ディスカッションを始めるためにいくつかの記事を書く
  2. +
  3. 記事の外観を定義する
  4. +
  5. それらの記事をウェブサイトに公開する(これを行う方法は?)
  6. +
+
他のミュージシャンに会う +
    +
  1. 他の人があなたに連絡する方法を提供します (E メール?Facebook?電話?手紙?)
  2. +
  3. 人々があなたのウェブサイトからそれらの連絡先チャンネルをどのように見つけるかを定義する
  4. +
+
グッズを売る +
    +
  1. グッズを作る
  2. +
  3. グッズを保管する
  4. +
  5. 配送を処理する方法を見つける
  6. +
  7. 支払いを処理する方法を見つける
  8. +
  9. あなたのサイトに人々が注文するためのメカニズムを作ります
  10. +
+
ビデオを通して音楽を教える +
    +
  1. ビデオレッスンを録画する
  2. +
  3. オンラインで表示可能なビデオファイルを準備します (これも既存のウェブサービスで可能ですか?)
  4. +
  5. あなたのウェブサイトのどこかであなたのビデオに他の人がアクセスできるようにする
  6. +
+
+ +

気づくべき 2 つのことがあります。第1 に、これらのアイテムの一部はウェブ関連 (例えば音楽を録音し、記事を書く) ではありません。これらのオフライン活動は、プロジェクトのウェブ側よりも重要な役割を果たすことがよくあります。たとえば、販売では、人々が注文するウェブサイトを構築するよりも、供給、支払い、出荷を処理する方がはるかに重要で時間がかかります。

+ +

第2 に、実行可能なステップを設定することで、答える必要がある新しい質問につながります。通常、当初考えていたよりも多くの疑問が出てきます。(例えば、これをすべて自分で行う方法を学ぶべきか、誰かにそれをさせるか、サードパーティサービスを使用するように頼んでください)。

+ +

結論

+ +

ご覧のとおり、「ウェブサイトを作ってみたい」というシンプルなアイデアでも、考えれば考えるほど ToDo リストが長くなっていきます。嘆きたくなるでしょうが、パニックになる必要はありません。すべての質問に答える必要も、リストの項目の全てを行う必要もありません。大切なことは、あなたは何がしたくて、どのように到達するかというビジョンを持てるかどうかなのです。クリアなビジョンを頭に入れたら、それをいつ、どのように行うかを決める事が必要です。 簡単にはできないような大きなタスクは、実行可能な小さなステップに分割しましょう。小さなステップを一つずつこなすことで、ついには大きな成果を達成することができるでしょう。

+ +

この記事から、ウェブサイトを作成するための大まかな計画を立てることができるはずです。次の記事は、インターネットの仕組みです。

diff --git a/files/ja/learn/common_questions/upload_files_to_a_web_server/index.html b/files/ja/learn/common_questions/upload_files_to_a_web_server/index.html new file mode 100644 index 0000000000..92c533f108 --- /dev/null +++ b/files/ja/learn/common_questions/upload_files_to_a_web_server/index.html @@ -0,0 +1,177 @@ +--- +title: どのようにファイルを Web サーバにアップロードしますか? +slug: Learn/Common_questions/Upload_files_to_a_web_server +tags: + - FTP + - GitHub + - WebMechanics + - rsync + - sftp + - アップロード + - ホスティング + - 初心者 +translation_of: Learn/Common_questions/Upload_files_to_a_web_server +--- +
+

この記事ではファイル転送ツールを使用してオンラインでサイトを公開する方法を説明します。

+
+ + + + + + + + + + + + +
学習の前提Web サーバが何であるかドメイン名の仕組みを知っていなければなりません。また、基本的な環境の設定方法簡単な Web ページの作成方法も理解しておく必要があります。
学習の目的FTP を使用してファイルをサーバにプッシュする方法を学びます。
+ +

概要

+ +

シンプルな Web ページを作成している場合 (例として HTML の基本を参照)、Web サーバ上にオンラインで転送したいと思うかもしれません。この記事では SFTP クライアント、RSync、GitHub などの選択肢をとおして、その方法を説明します。

+ +

SFTP

+ +

 SFTP クライアントには、いくつもの選択肢があります。ここのデモは FileZilla を使うことにします。 Windows、macOS、Linux で使え、無料だからです。FileZilla をインストールするには、FileZilla ダウンロードページに移動し、大きなダウンロードボタンをクリックしてから、通常の方法でインストーラファイルからインストールします。

+ +
+

メモ: もちろん他にもたくさんのオプションがあります。詳細についてはパブリッシングツールを参照してください。

+
+ +

FileZilla アプリケーションを開きます。次のようなものが表示されます。

+ +

+ +

ログイン

+ +

この例では、ホスティングプロバイダ (私たちの HTTP Web サーバをホストするサービス) は架空の会社 "Example Hosting Provider" であり、URL は次のようになります:mypersonalwebsite.examplehostingprovider.net

+ +

私たちはアカウントを開設し、その情報を受け取ったばかりです:

+ +
+

Example Hosting Provider でアカウントを開設しましたことをお祝いします。

+ +

アカウント: demozilla

+ +

あなたのWebサイトは demozilla.examplehostingprovider.net で表示されます。

+ +

このアカウントに公開するには、SFTP を使用して次の資格情報で接続してください:

+ + +
+ +

最初に http://demozilla.examplehostingprovider.net/ を見てみましょう。見ての通り、まだそこには何もありません:

+ +

Our demozilla personal website, seen in a browser: it's empty

+ +
+

メモ: ホスティングプロバイダによっては、最初にあなたの Web アドレスに行ったときに、「このWebサイトは[ホスティングサービス]によってホストされています。」というようなページが表示されます。

+
+ +

SFTP クライアントを遠隔のサーバに接続するには、次の手順を実行します。

+ +
    +
  1. メインメニューから ファイル > サイトマネージャ と選択します
  2. +
  3. [サイトマネージャ] ウィンドウで、[新規サイト] ボタンをクリックし、提供されたスペースにサイト名を demozilla として入力します
  4. +
  5. ホスティングプロバイダから提供された SFTP サーバのホストを Host: フィールドに入力します
  6. +
  7. [ログオンの種類] ドロップダウンで [標準] を選択し、提供されたユーザ名とパスワードを該当するフィールドに入力します
  8. +
  9. 正しいポートおよびその他の情報を入力します
  10. +
+ +

ウィンドウは次のようになります:

+ +

+ +

次に Connect を押して SFTP サーバに接続します。

+ +

注意: ホスティングプロバイダがホスティングスペースへの SFTP (セキュア FTP) 接続を提供していることを確認してください。FTP は本質的に安全ではないため、使用しないでください。

+ +

こちらとあちら:ローカルビューとリモートビュー

+ +

一度接続すると、画面は次のようになります (私たちはあなた自身のアイデアを伝えるために例を挙げています)。

+ +

+ +

あなたが見ているものを調べてみましょう:

+ + + +

サーバへのアップロード

+ +

私たちのホスト命令の例では、「Web 上に公開するには、ファイルを Public/htdocs ディレクトリに入れてください」となっています。右ペインの指定されたディレクトリに移動する必要があります。このディレクトリは実質的にあなたの Web サイトのルートで、index.html ファイルやその他のアセットがどこに行くかを示します。

+ +

ファイルを置く正しいリモートディレクトリが見つかったら、サーバにファイルをアップロードしますが、それにはファイルを左ペインから右ペインにドラッグ & ドロップする必要があります。

+ +

本当にオンラインですか?

+ +

これまでのところとても良いですが、ファイルは本当にオンラインですか? ブラウザでWebサイト (例えば http://demozilla.examplehostingprovider.net/) に戻って再確認することができます。

+ +

Here we go: our website is live!

+ +

そしてやりました! Web サイトは動いています!

+ +

Rsync

+ +

{{Glossary("Rsync")}} はローカルからリモートへのファイル同期ツールで、ほとんどの Unix ベースのシステム (macOS や Linux など) で一般的に利用可能ですが、Windows 版も存在します。

+ +

デフォルトではコマンドラインで使用されるため、SFTP よりも高度なツールと見なされています。基本的なコマンドはこんな感じです:

+ +
rsync [-options] SOURCE user@x.x.x.x:DESTINATION
+ + + +

あなたはホスティングプロバイダからそのような詳細を得る必要があるでしょう。

+ +

詳細およびその他の例については、 How to Use Rsync to Copy/Sync Files Between Servers を参照してください。

+ +

もちろん、FTP の時と同じように安全な接続のもとで使用することをお勧めします。Rsync の場合は -e オプションを使用して、SSH を介した接続を確立するための SSH 詳細を指定します。例えば:

+ +
rsync [-options] -e "ssh [SSH DETAILS GO HERE]" SOURCE user@x.x.x.x:DESTINATION
+ +

必要なものの詳細については、How To Copy Files With Rsync Over SSH を参照してください。

+ +

Rsync GUI ツール

+ +

他のコマンドラインツールと同様に、コマンドラインの使用に慣れていない人向けに Rsync 用の GUI ツールもあります。Acrosync はそのようなツールの1つで、Windows と macOS で利用可能です。

+ +

繰り返しになりますが、ホスティングプロバイダから接続認証情報を取得する必要がありますが、この方法でそれらを入力するための GUI が得られます。

+ + + +

GitHub

+ +

GitHub では、GitHub pages (gh-pages) を介して Web サイトを公開することができます。

+ +

これの使い方の基本については、Web 入門Web サイトの公開の記事で説明しているので、ここでは繰り返しません。

+ +

ただし、GitHub で Web サイトをホストすることはできますが、カスタムドメインを使用することもできます。詳しいガイドは Using a custom domain with GitHub Pages をご覧ください。

+ + + +

ファイルをアップロードするその他の方法

+ +

FTP プロトコルは、Web サイトを公開するためのよく知られた方法の1つですが、唯一の方法ではありません。 他にもいくつかのやり方があります。

+ + diff --git a/files/ja/learn/common_questions/using_github_pages/index.html b/files/ja/learn/common_questions/using_github_pages/index.html new file mode 100644 index 0000000000..2e68d87607 --- /dev/null +++ b/files/ja/learn/common_questions/using_github_pages/index.html @@ -0,0 +1,108 @@ +--- +title: GitHub Pagesを使うには? +slug: Learn/Common_questions/Using_Github_pages +tags: + - Beginner + - GitHub + - Guide + - Web + - gh-pages + - git + - publish +translation_of: Learn/Common_questions/Using_Github_pages +--- +

GitHub は "ソーシャル・コーディング" のサイトです。Git バージョン管理システムのストレージに対して、ソースコードリポジトリーのアップロードを許可します。その後、コードプロジェクトで共同作業を行うことができます。また、システムはオープンソースに自動設定されています。つまり、世界中の誰もが GitHub コードを検索・使用また、そこから学習しコードを改善することができます。他の人のコードでもそれが可能です!この記事は Github の gh-pages 機能を使って、公開コンテンツに関する基本的なガイドを提供します。

+ +

公開コンテンツ

+ +

GitHub は非常に重要で役に立つコミュニティの一つで、Git / GitHub は非常に人気のあるバージョン管理システムです。現在、ほとんどのハイテク企業がワークフローでそれを使用しています。GitHub は GitHub ページと呼ばれる非常に便利な機能を持っています。これはあなたがウェブ上にライブでウェブサイトのコードを公開することを可能にします。

+ +

Github の基本設定

+ +
    +
  1. 初めに、システムに Git をインストールしてください。これは GitHub が動作する基盤となるバージョン管理システムのソフトウェアです。
  2. +
  3. 次に、GitHub アカウントサインアップします。それは単純かつ簡単です。
  4. +
  5. サインアップしたら、ユーザー名とパスワードを使って github.com  にログインします。
  6. +
+ +

ソースコードのアップロード準備

+ +

Github リポジトリーに好きなコードを保存できますが、GitHub ページ機能を最大限に活用するには、コードを典型的なウェブサイトとして構成する必要があります。主なエントリーポイントは、index.html という HTML ファイルです。

+ +

次に進む前に、自身のコードディレクトリーを Git リポジトリとして初期化する必要があります。このために、以下のことを実行してください:

+ +
    +
  1. コマンドラインで test-site のディレクトリー (またはウェブサイトを含むディレクトリーと呼んだもの) を指定します。これには、cd コマンドを使用します (つまり、「ディレクトリーの変更」)。ウェブサイトをデスクトップの test-site というディレクトリーに配置した場合は、次のように入力します: + +
    cd Desktop/test-site
    +
  2. +
  3. コマンドラインが、あなたのウェブサイトディレクトリーの中を指しているとき、ディレクトリーを git リポジトリにそのまま変えるように git ツールに指示する、次のコマンドを入力してください: +
    git init
    +
  4. +
+ +

コマンドラインインターフェイスの余談

+ +

Github にコードをアップロードする最良の方法は、コマンドラインを使用することです。これは、ユーザーインターフェイス内をクリックするのではなく、ファイルを作成・プログラム実行のような動作のためのコマンドを入力するウィンドウです。それは次のようなものです:

+ +

+ +
+

補足: コマンドラインに不安がある場合は、Git グラフィカルユーザーインターフェイスを使用して、同じ作業を行うことも検討できます。

+
+ +

すべてのオペレーティングシステムには、コマンドラインツールが付属しています:

+ + + +

これには最初は、少し戸惑うかもしれませんが、心配しないでください — すぐに基本のコツをつかむでしょう。上記のようにコマンドを入力して、Enter キーを押すことで、端末で動作するようにコンピューターに指示します。

+ +

ソースコードのリポジトリの作成

+ +
    +
  1. 次に、ファイルを保存するための新しいリポジトリーを作成する必要があります。GitHub ホームページの右上にあるプラス (+) をクリックしてから、新しいリポジトリー を選択します。
  2. +
  3. このページの リポジトリー名ボックス に、ソースコードのリポジトリー名 (例: my-repository) を入力します。
  4. +
  5. また、説明を入力することで、リポジトリーに何を格納しようとしているのかを記述します。画面は次のようなものです:
    +
  6. +
  7. Create repository をクリックします。これにより、次のページに移動します:
    +
  8. +
+ +

GitHub へのファイル格納

+ +
    +
  1. 現在のページで、あなたはセクションに興味を持っています... または、コマンドラインから既存のリポジトリーをプッシュします。このセクションに 2 行のコードがリストされているはずです。最初の行全体をコピーしてコマンドラインに貼り付け、Enter キーを押します。コマンドは次のようなものです: + +
    git remote add origin https://github.com/chrisdavidmills/my-repository.git
    +
  2. +
  3. 次に、以下の 2 つのコマンドを入力し、それぞれの後に Enter キーを押します。これらは GitHub にアップロードするためのコードを用意し、Git にこれらのファイルを管理するように依頼します。 +
    git add --all
    +git commit -m 'adding my files to my repository'
    +
  4. +
  5. 最後に、表示されている 2 つのコマンドの内、2 番目のコマンドを端末に入力する「または、コマンドラインセクションから既存のリポジトリーをプッシュして」、コードを GitHub にプッシュします: +
    git push -u origin master
    +
  6. +
  7. ここで、リポジトリーの gh-pages ブランチを作成する必要があります。現在のページを更新すると、以下のようなリポジトリページが表示されます。Branch: master というボタンを押し、テキスト入力に gh-pages と入力してから Create branch: gh-pages という青いボタンを押す必要があります。これにより、gh-pages という特別な場所に公開されている、特別なコードブランチが作成されます。URL は、username.github.io/my-repository-name の形式を取ります。したがって、この例の場合、URL は https://chrisdavidmills.github.io/my-repository になります。表示されているページは index.html ページです。
    +
  8. +
  9. 新しいブラウザータブで、GitHub Pages のウェブアドレスに移動すると、サイトがオンラインなります!友人にそれを電子メールで送って、あなたの習熟を披露してください。
  10. +
+ +
+

: 困った場合は、GitHub Pages ホームページも大いに役立ちます。

+
+ +

GitHub の詳細

+ +

テストサイトにさらに変更を加えて、GitHub にアップロードしたい場合は、以前と同じようにファイルに変更を加えるだけです。それから、以下のコマンドを入力して (それぞれ Enter キーを押して) GitHub にそれらの変更をプッシュする必要があります:

+ +
git add --all
+git commit -m 'another commit'
+git push
+ +

another commit をより適切なメッセージに置換して、今行った変更を説明できます。

+ +

私たちは、Git の表面を引っ掻いてみたにすぎません。詳細については、GitHub ヘルプサイト から始めてください。

diff --git a/files/ja/learn/common_questions/what_are_browser_developer_tools/index.html b/files/ja/learn/common_questions/what_are_browser_developer_tools/index.html new file mode 100644 index 0000000000..4e3fe1667b --- /dev/null +++ b/files/ja/learn/common_questions/what_are_browser_developer_tools/index.html @@ -0,0 +1,182 @@ +--- +title: ブラウザー開発者ツールとは? +slug: Learn/Common_questions/What_are_browser_developer_tools +tags: + - Beginner + - Browser + - CSS + - CodingScripting + - Dev Tools + - HTML + - JavaScript + - Learn +translation_of: Learn/Common_questions/What_are_browser_developer_tools +--- +
{{IncludeSubnav("/ja/Learn")}}
+ +
+

近頃のブラウザにはパワフルな開発者ツールが入っています。開発者ツールでは、現在の HTML や CSS、JavaScript の状態を検証したり、ページがどういったアセットにアクセスし、どれだけ時間がかかったかといった多様なことができます。この記事ではブラウザの開発者ツールの使い方について説明します。

+
+ +
+

: 下のサンプルを実行していく前に、Web入門の記事の中で作りあげる、初心者向けウェブサイトの例を開いてください。後ほどこれを使って説明します。

+
+ +

ブラウザ開発者ツールの開き方

+ +

開発者ツールはブラウザのサブウィンドウの中にいます。大体こんな感じに...。

+ +

+ +

どのように開くのでしょうか?これには 3 つの方法があります。

+ + + +

+ +

インスペクタ: DOM の内容が見られる CSS エディター

+ +

開発者ツールはたいてい最初にインスペクタが開きます。インスペクタの見た目は下に示すスクリーンショットのような感じです。このツールは実行時/表示時に HTML の状態がどのようになっているか見せてくれます。また、CSS がどのようにページ内の要素に適用されているかも見られます。そして、HTML と CSS をその場で簡単に編集し、ブラウザのビューポートに表示されている結果に反映することができます。

+ +

+ +

もしインスペクタが表示されていない場合、

+ + + +

DOM インスペクタについて詳しく知る

+ +

まずは、DOM インスペクタ上の HTML の要素を右クリックして、コンテキストメニューを見てみましょう。メニューの表示はブラウザによって異なりますが、重要な機能はほぼ同じです。

+ +

+ + + +

それでは表示されている DOM を編集してみましょう。要素をダブルクリックしたり、右クリックして、HTML として編集を選んでみましょう。いろいろと変更してみても問題ありませんが、保存ができませんのでご注意を。

+ +

CSS エディターについて詳しく知る

+ +

最初は CSS エディターは現在選択中の要素に適用されている CSS ルールを表示しています。

+ +

+ +

以下の機能は特に便利です。

+ + + +

CSS ビューアーの一番上にいくつかのタブメニューがあることに気づいたでしょうか。

+ + + +

もっと知りたいときは...

+ +

各ブラウザのインスペクタの詳細については以下をご覧ください。

+ + + +

The JavaScript console

+ +

The JavaScript console is an incredibly useful tool for debugging JavaScript that isn't working as expected. It allows you to run lines of JavaScript against the page currently loaded in the browser, and reports the errors encountered as the browser tries to execute your code. To access the console in any browser:

+ +

If the developer tools are already open, click or press the Console tab.

+ +

If not, Firefox allows you to open the console directly using Ctrl + Shift + K or using the menu command: Menu ➤ Web Developer ➤ Web Console, or Tools ➤ Web Developer ➤ Web Console. On other browser, open the developer tools and then click the Console tab.

+ +

This will give you a window like the following:

+ +

+ +

To see what happens, try entering the following snippets of code into the console one by one (and then pressing Enter):

+ +
    +
  1. +
    alert('hello!');
    +
  2. +
  3. +
    document.querySelector('html').style.backgroundColor = 'purple';
    +
  4. +
  5. +
    var myImage = document.createElement('img');
    +myImage.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png');
    +document.querySelector('h1').appendChild(myImage);
    +
  6. +
+ +

Now try entering the following incorrect versions of the code and see what you get.

+ +
    +
  1. +
    alert('hello!);
    +
  2. +
  3. +
    document.cheeseSelector('html').style.backgroundColor = 'purple';
    +
  4. +
  5. +
    var myImage = document.createElement('img');
    +myBanana.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png');
    +document.querySelector('h1').appendChild(myImage);
    +
  6. +
+ +

You'll start to see the kind of errors that the browser returns. Often these errors are fairly cryptic, but it should be pretty simple to figure these problems out!

+ +

Find out more

+ +

Find more out about the JavaScript console in different browsers:

+ + + +

あわせて参照

+ + diff --git a/files/ja/learn/common_questions/what_are_hyperlinks/index.html b/files/ja/learn/common_questions/what_are_hyperlinks/index.html new file mode 100644 index 0000000000..97b37bfe75 --- /dev/null +++ b/files/ja/learn/common_questions/what_are_hyperlinks/index.html @@ -0,0 +1,95 @@ +--- +title: ハイパーリンクとは? +slug: Learn/Common_questions/What_are_hyperlinks +tags: + - Beginner + - Infrastructure + - Navigation +translation_of: Learn/Common_questions/What_are_hyperlinks +--- +
+

この記事では、ハイパーリンクとは何か、なぜ重要なのかを詳しく説明します。

+
+ + + + + + + + + + + + +
前提条件:インターネットの仕組みを理解し、Web ページ、Web サイト、Web サーバ、検索エンジンの違いに精通している必要があります。
目的:Web 上のリンクとその重要性について学びます。
+ +

概要

+ +

ハイパーリンクは通常リンクと呼ばれ、Web の背後にある基本概念です。リンクとは何かを説明するために、Web アーキテクチャの基本に戻る必要があります。

+ +

Web の発明者でもあるティム・バーナーズ・リーは、1989年に Web を支える3つの柱について語りました。

+ +
    +
  1. {{Glossary("URL")}}、Web 文書を追跡するアドレスシステム
  2. +
  3. {{Glossary("HTTP")}}、URL が与えられたときに文書を見つけるための転送プロトコル
  4. +
  5. {{Glossary("HTML")}}、埋め込みハイパーリンクを可能にする文書フォーマット
  6. +
+ +

3つの柱からわかるように、Web 上のすべてのものはドキュメントとそのアクセス方法を中心に展開されています。Web の当初の目的は、テキスト文書に簡単にアクセスし、読み込み、そしてナビゲートする方法を提供することでした。それ以来、Web は画像、ビデオ、およびバイナリデータへのアクセスを提供するように進化しましたが、これらの改善によって3つの柱が変わることはほとんどありませんでした。

+ +

Web が登場する前は、ドキュメントにアクセスして別のドキュメントに移動することは非常に困難でした。人が読めるので、URL はすでに物事を簡単にしますが、文書にアクセスする都度長い URL を入力するのは困難です。これがハイパーリンクがすべてに革命をもたらしたところです。リンクは任意のテキスト文字列を URL と関連付けることができるため、ユーザはリンクをアクティブにすることで対象の文書にすぐにアクセスできます。

+ +

下線が引かれ、青いテキストで囲まれていることで、リンクは周囲のテキストから際立っています。リンクをタップまたはクリックしてアクティブにするか、キーボードを使用している場合は、リンクがフォーカスされるまでTabキーを押してEnterキーまたはスペースバーを押します。

+ +

Example of a basic display and effect of a link in a web page

+ +

リンクは、Web をとても便利で成功させた画期的なものです。この記事の残りの部分では、さまざまな種類のリンクと、それらが現代の Web デザインにとって重要であることについて説明します。

+ +

より深いダイブ

+ +

すでに述べたように、リンクは URL に関連付けられたテキスト文字列です。リンクを使用すると、ある文書から別の文書に簡単に移動できます。とは言っても、考慮すべきいくつかのニュアンスがあります。

+ +

リンクの種類

+ +
+
内部リンク
+
両方ともあなたの Web サイトに属している 2 つの Web ページ間のリンクは、内部リンクと呼ばれます。内部リンクがなければ、Web サイトのようなものはありません (もちろん、1ページの Web サイトでもない限りはですが)。
+
外部リンク
+
あなたの Web ページから他の誰かの Web ページへのリンク。Web は Web ページのネットワークであるため、外部リンクがなければ Web はありません。あなたの Web ページを通して利用可能なコンテンツ以外の情報を提供するには外部リンクを使用してください。
+
被リンク
+
他の人の Web ページからあなたのサイトへのリンク。外部リンクの反対です。誰かがあなたのサイトにリンクしたときにあなたはリンクバックする必要はないことに注意してください。
+
+ +

Web サイトを構築するときは、内部リンクに集中してください。これらのリンクを使用すると、サイトが使用可能になります。リンク数が多すぎることと少なすぎることの間でバランスの取れたものを見つけてください。別の記事で Web サイトナビゲーションの設計について説明しますが、原則として、新しい Web ページを追加するときは必ず、他のページの少なくとも1つがその新しいページにリンクしていることを確認してください。一方、サイトに10ページを超えるページがある場合は、他のすべてのページからすべてのページにリンクするのは非生産的です。

+ +

始めて間もないうちは、それほど外部と入ってくるリンクについて心配する必要はありません。しかし検索エンジンにサイトを見つけさせたいならそれらは非常に重要です。(詳細については下記を参照してください)。

+ +

アンカー

+ +

ほとんどのリンクは2つの Web ページを結び付けています。 アンカーは1つの文書の2つのセクションを一緒に結びます。 アンカーを指すリンクをたどると、ブラウザは新しい文書をロードするのではなく、現在の文書の別の部分にジャンプします。ただし、他のリンクと同じ方法でアンカーを作成して使用します。

+ +

Example of a basic display and effect of an anchor in a web page

+ +

リンクと検索エンジン

+ +

リンクはユーザにとっても検索エンジンにとっても重要です。 検索エンジンは、Web ページをクロールするたびに、その Web ページで利用可能なリンクをたどって Web サイトにインデックスを付けます。検索エンジンは、リンクをたどって Web サイトのさまざまなページを見つけるだけでなく、リンクの表示テキストを使用して、どの検索クエリが対象のWebページにアクセスするのに適しているかを判断します。

+ +

リンクは、検索エンジンがサイトにどれだけ早くリンクするかに影響します。問題は、検索エンジンのアクティビティを測定するのが難しいということです。企業は当然、自分のサイトが検索結果の上位にランクされることを望んでいます。検索エンジンがサイトのランクをどのように決定するかについては、次のことがわかっています。

+ + + +

SEO (検索エンジン最適化) は、検索結果で Web サイトを上位にランク付けする方法の研究です。Web サイトのリンクの使用を改善することは、1つの役に立つ SEO テクニックです。

+ +

次のステップ

+ +

それでは、いくつか Web ページにリンクを設定しましょう。

+ + diff --git a/files/ja/learn/common_questions/what_is_a_domain_name/index.html b/files/ja/learn/common_questions/what_is_a_domain_name/index.html new file mode 100644 index 0000000000..37d78285c8 --- /dev/null +++ b/files/ja/learn/common_questions/what_is_a_domain_name/index.html @@ -0,0 +1,160 @@ +--- +title: ドメイン名とは何ですか? +slug: Learn/Common_questions/What_is_a_domain_name +tags: + - Web + - イントロダクション + - インフラ + - ウェブ + - ドメイン名 + - 初心者 + - 導入 +translation_of: Learn/Common_questions/What_is_a_domain_name +--- +
+

この記事ではドメイン名について説明し、何であるか、どのように構造化されているのか、そして取得する方法を説明します。

+
+ + + + + + + + + + + + +
前提知識:まずインターネットの仕組みURL とは何かを理解している必要があります。
目的:ドメイン名とはどのようなもので、どのように働くのか、なぜ重要なのかを学びます。
+ +

概要

+ +

ドメイン名はインターネット基盤の重要な部分です。インターネット上で利用できるあらゆるウェブサーバーに対して、人間が読めるアドレスを提供します。

+ +

インターネットに接続しているコンピューターはすべて、パブリック {{Glossary("IP")}} アドレスからアクセスでき、これは IPv4 では32ビット (通常、ドットで区切られた 0〜255 までの4桁の数値 (例: 173.194.121.32) として記述される)、 IPv6 では128ビット (通常はコロンで区切られた4桁の16進数の8つのグループ (例: 2027:0da8:8b73:0000:0000:8a2e:0370:1337)として記述される) で構成されます。コンピューターはこれらのアドレスを簡単に処理できますが、人間にとってはだれがサーバーを運営しているのか、またはウェブサイトがどのようなサービスを提供しているかを理解するのは困難です。 IP アドレスは覚えにくく、時間の経過とともに変わる可能性があります。これらすべての問題を解決するために、ドメイン名と呼ばれる人間が読めるアドレスを使用します。

+ +

より深い追求

+ +

ドメイン名の構造

+ +

ドメイン名は単純な構造であり、ドットで区切られたいくつかの部分 (1つの部分だけの場合もあれば、2つ、3つの場合も...) からできており、右から左に向かって読まれます

+ +

MDN のドメイン名の構造

+ +

これらのそれぞれの部分は、ドメイン名全体に関する特定の情報を提供します。

+ +
+
{{Glossary("TLD")}} (トップレベルドメイン)
+
TLD は最も一般的な情報を提供します。 TLD は、ドメイン名の背後にあるサービスの全般的な目的をユーザーに伝えます。多くの一般的な TLD (.com, .org, .net) はウェブサービスが特定の基準を満たしていることを要求しませんが、 TLD によってはより厳密な基準を適用するため、目的がより明確になります。例えば、 +
    +
  • .jp, .us, .fr, .se などのローカル TLD では、サービスを特定の言語で提供しているか、特定の国でホスティングされていることを要求します。これらは、特定の言語や国のリソースであることを示しているとみなされます。
  • +
  • .gov.go.jp を含む TLD は、政府機関のみが使用できます。
  • +
  • .edu.ac.jp のような TLD は教育・学術機関のみで使用されていると見なされます。
  • +
+ TLD にはラテン文字だけでなく特殊文字も含めることができ、長さは最大63文字ですが、ほとんどは2〜3文字です。
+
ラベル (またはコンポーネント)
+
ラベルは TLD の後に続くものです。ラベルは1文字から完全な一文まで何でも構いません。 TLD の直前にあるラベルは、二次レベルドメイン (SLD) とも呼ばれます。ドメイン名は多数のラベル (またはコンポーネント) を持つことができますが、ドメイン名を構成するのにラベルを3つ持つことが必須でも必要でもありません。例えば、 www.inf.ed.ac.uk は正しいドメイン名です。制御権のあるドメイン (例えば mozilla.org) には、 developer.mozilla.orghttps://iot.mozilla.org/ のように、互いに異なる内容で「サブドメイン」を作成することができます。
+
+ +

ドメイン名の購入

+ +

誰がドメイン名を所有しているか

+ +

「ドメイン名を買う」ことはできません。これは、未使用のドメイン名が最終的に他の人が再び使用できるようになるためです。すべてのドメイン名が購入されてしまうと、ウェブはすぐにロックされていて誰も利用ができない未使用のドメイン名であふれてしまいます。

+ +

代わりに、1年間または数年間ドメイン名を使用する権利を購入します。この権利は更新することができ、他の人々の応募よりも更新の方が優先されます。しかし、決してドメイン名を所有するわけではありません。

+ +

登録機関と呼ばれる会社は、ドメイン名のレジストリを使用して、あなたをドメイン名に結び付ける技術的および管理的情報を維持します。

+ +
+

メモ : ドメイン名によっては、追跡を担当している登録機関ではない可能性があります。たとえば、.fire の下のすべてのドメイン名は Amazon によって管理されています。

+
+ +

利用可能なドメイン名を探す

+ +

特定のドメイン名が利用可能かどうかを調べるには、

+ + + +
$ whois mozilla.org
+Domain Name:MOZILLA.ORG
+Domain ID: D1409563-LROR
+Creation Date: 1998-01-24T05:00:00Z
+Updated Date: 2013-12-08T01:16:57Z
+Registry Expiry Date: 2015-01-23T05:00:00Z
+Sponsoring Registrar:MarkMonitor Inc. (R37-LROR)
+Sponsoring Registrar IANA ID: 292
+WHOIS Server:
+Referral URL:
+Domain Status: clientDeleteProhibited
+Domain Status: clientTransferProhibited
+Domain Status: clientUpdateProhibited
+Registrant ID:mmr-33684
+Registrant Name:DNS Admin
+Registrant Organization:Mozilla Foundation
+Registrant Street: 650 Castro St Ste 300
+Registrant City:Mountain View
+Registrant State/Province:CA
+Registrant Postal Code:94041
+Registrant Country:US
+Registrant Phone:+1.6509030800
+
+ +

ご覧のとおり、 mozilla.org を登録することはできません。 Mozilla Foundation がすでに登録しているからです。

+ +

一方、 afunkydomainname.org を登録できるかどうか確認しましょう。

+ +
$ whois afunkydomainname.org
+NOT FOUND
+
+ +

ご覧のとおり、ドメインは (執筆時点で) whois データベースには存在しませんので、登録を依頼することができます。知っておくと良いでしょう!

+ +

ドメイン名の取得

+ +

プロセスは非常に簡単です。

+ +
    +
  1. 登録機関のウェブサイトにアクセスします。
  2. +
  3. 通常、「ドメイン名を取得する」という操作があります。それをクリックします。
  4. +
  5. フォームに必要事項をすべて記入してください。希望するドメイン名のスペルを間違えていないことを特に確認してください。支払いが済んだら、手遅れです。
  6. +
  7. 登録機関は、ドメイン名が正しく登録されたことを知らせます。数時間以内に、すべての DNS サーバーがあなたの DNS 情報を受信するでしょう。
  8. +
+ +
+

メモ: この過程で、登録機関は現実世界の住所を尋ねます。国によっては、有効な住所を提供できないと登録機関がドメインを強制的に閉鎖する可能性があるため、正しく入力するようにしてください。

+
+ +

DNS の更新

+ +

DNS データベースは世界中のすべての DNS サーバーに格納されており、これらのサーバーはすべて「権威ネームサーバー」または「トップレベル DNS サーバー」と呼ばれるいくつかの特別なサーバーを参照しています。これらはシステムを管理する上司サーバーのようなものです。

+ +

登録機関が特定のドメインの情報を作成または更新するたびに、すべての DNS データベース内で情報を更新する必要があります。指定されたドメインについて知っている DNS サーバーはそれぞれ、しばらく情報を保持し、その後で情報を自動的に無効化して更新します (DNS サーバーが権威サーバーに照会し、そこから更新された情報を取得します)。したがって、このドメイン名について知っている DNS サーバーが最新の情報を入手するには時間がかかります。

+ +

DNS リクエストはどのように機能するのか

+ +

すでに見たように、ブラウザーにウェブページを表示したい場合は、 IP アドレスよりもドメイン名を入力する方が簡単です。プロセスを見てみましょう。

+ +
    +
  1. ブラウザーのロケーションバーに mozilla.org と入力してください。
  2. +
  3. ブラウザーは、このドメイン名で識別される IP アドレスを (ローカル DNS キャッシュを使用して) すでに認識しているかどうかをコンピューターに確認します。存在する場合、ドメイン名は IP アドレスに変換され、ブラウザーはウェブサーバーとコンテンツをネゴシエートします。話は終わりです。
  4. +
  5. どの IP が mozilla.org の名前の背後にあるのかわからない場合は、DNS サーバーに問い合わせます。DNS サーバーの役割は、登録されている各ドメイン名に一致する IP アドレスをコンピューターに通知することです。
  6. +
  7. コンピューターがリクエストされた IP アドレスを認識したので、ブラウザーはウェブサーバーとコンテンツをネゴシエートできます。
  8. +
+ +

Explanation of the steps needed to obtain the result to a DNS request

+ +

次のステップ

+ +

さて、私たちはプロセスとアーキテクチャについて多くのことを話しました。そろそろ次に進みましょう。

+ + diff --git a/files/ja/learn/common_questions/what_is_a_url/index.html b/files/ja/learn/common_questions/what_is_a_url/index.html new file mode 100644 index 0000000000..433ead1fa4 --- /dev/null +++ b/files/ja/learn/common_questions/what_is_a_url/index.html @@ -0,0 +1,159 @@ +--- +title: URL とは何か +slug: Learn/Common_questions/What_is_a_URL +tags: + - Infrastructure + - URL + - urls + - インフラ + - リソース + - 初心者 +translation_of: Learn/Common_questions/What_is_a_URL +--- +
+

この記事では Uniform Resource Locators (URL) について説明し、その内容と構造を説明します。

+
+ + + + + + + + + + + + +
前提知識:まずインターネットの仕組みウェブサーバーとは何か、および ウェブ上のリンクの背後にある概念を知る必要があります。
目的:URL の内容とウェブ上での URL の仕組みを学習します。
+ +

概要

+ +

URL は{{Glossary("Hypertext", "ハイパーテキスト")}}や {{Glossary("HTTP")}} とともに、ウェブの重要な概念の一つです。{{Glossary("Browser", "ブラウザー")}}がウェブ上の公開されたリソースを取得するために使用するメカニズムです。

+ +

URLUniform Resource Locator の略です。URL はウェブ上の特定の一意のリソースのアドレスにすぎません。理論的には、それぞれ有効な URL は一意のリソースを指しています。そのようなリソースは HTML ページ、 CSS 文書、画像などである可能性があります。実際には一部例外もあります。最も一般的なものは、もはや存在しないリソースや移動したリソースを指す URL です。URL で表されるリソースと URL 自体はウェブサーバーによって処理されるため、ウェブサーバーの所有者がそのリソースとその関連 URL を慎重に管理する必要があります。

+ +

アクティブラーニング

+ +

アクティブラーニングはまだありません。協力してください

+ +

より深く

+ +

基本: URL の解剖

+ +

URL の例を次に示します。

+ +
https://developer.mozilla.org
+https://developer.mozilla.org/en-US/docs/Learn/
+https://developer.mozilla.org/en-US/search?q=URL
+ +

これらの URL のいずれかをブラウザーのアドレスバーに入力して、関連するページ (リソース) をロードするように指示することができます。

+ +

URL はさまざまな部分で構成されていますが、必須のものと任意のものもあります。次の URL を使用して最も重要な部分を見てみましょう。

+ +
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
+ +
+
プロトコル
+
http はプロトコルです。 URL の最初の部分は、ブラウザーが使用するプロトコルを示します。プロトコルとは、コンピューターネットワークを介してデータを交換または転送するための設定方法です。通常、ウェブサイトの場合は HTTP プロトコルまたはそのセキュアバージョンの HTTPS です。ウェブにはこれらの2つのうちの1つが必要ですが、ブラウザーは mailto: (メールクライアントを開くため) や ftp: などの他のプロトコルを扱う方法も知っていますので、そのようなプロトコルを見ても驚かないでください。
+
ドメイン名
+
www.example.com はドメイン名です。リクエストされるウェブサーバーを示します。他にも {{Glossary("IP address", "IP アドレス")}} を直接使用することも可能ですが、あまり便利ではないため、ウェブ上では頻繁に使用されることはありません。
+
ポート番号
+
:80 はポート番号です。これはウェブサーバー上のリソースにアクセスするために使用される技術的な「ゲート」を示します。ウェブサーバーが HTTP プロトコルの標準ポート (HTTP の場合は80、 HTTPS の場合は443) を使用してそのリソースへのアクセスを許可する場合、通常は省略されます。それ以外の場合は必須です。
+
ファイルへのパス
+
/path/to/myfile.html は、ウェブサーバー上のリソースへのパスです。初期のウェブでは、このようなパスはウェブサーバー上の物理的なファイルの場所を表していました。今日ではほとんどの場合、物理的なものではなくウェブサーバーによって処理される抽象的なものです。
+
引数
+
?key1=value1&key2=value2 は、ウェブサーバーに提供される追加の引数です。これらの引数は & 記号で区切られたキー/値のペアのリストです。ウェブサーバーは、リソースを返す前にこれらの引数を使用して追加の処理を行うことができます。各ウェブサーバーには引数に関する独自のルールがありますので、特定のウェブサーバーが引数を処理するかどうかを確認する確実な方法は、ウェブサーバーの所有者に問い合わせることだけです。
+
アンカー
+
#SomewhereInTheDocument は、リソース自体の別の部分へのアンカーです。アンカーはリソース内の一種の「ブックマーク」を表し、ブラウザーにそのブックマークされた場所にあるコンテンツを表示するための指示を与えます。たとえば、 HTML 文書では、ブラウザーはアンカーが定義されている位置までスクロールします。ビデオやオーディオ文書では、ブラウザーはアンカーが表す時刻に移動しようとします。 # の後の部分はフラグメント識別子とも呼ばれ、リクエストとともにサーバーに送信されることはありません。
+
+ +

{{Note('URL に関する他の部分と規則もありますが、それらは通常のユーザーやウェブ開発者には関係ありません。これについて心配する必要はありません。完全に機能する URL を構築して使用するためにそれらを知る必要はありません。')}}

+ +

URL を通常の郵送先住所のように考えるといいかもしれません。プロトコルは、使用したい郵便サービスを表し、ドメイン名は都市または町であり、ポート番号は郵便番号のようなものです。パスは郵便物が配信される建物を表します。引数は建物内の部屋番号などの追加情報を表します。最後に、アンカーは郵便物の宛先に当たる実際の人物を表します。

+ +

URL の使い方

+ +

ブラウザーのアドレスバーの中に正しく URL を入力すれば、それに対応するリソースを得ることができます。しかし、これは氷山の一角にすぎません。

+ +

後で説明する {{Glossary("HTML")}} 言語では、 URL を幅広く使用しています。

+ + + +
+

メモ: <script>, <audio>, <img>, <video> を使用する場合など、ページの一部としてリソースを読み込む URL を指定する場合は、HTTP と HTTPS の URL のみを使用してください。たとえば FTP を使用しても、特に安全になることはなく、、多くのブラウザーでは対応していません。

+
+ +

{{Glossary("CSS")}} や {{Glossary("JavaScript")}} などの他の技術は、URL を広範囲に使用し、真にウェブの中核です。

+ +

絶対 URL と相対 URL

+ +

上記で見たものは絶対 URL と呼ばれていますが、相対 URL と呼ばれるものもあります。その違いが何を意味するのかをもっと詳しく調べてみましょう。

+ +

URL の必須部分は、その URL が使用されているコンテキストによって大きく異なります。ブラウザーのアドレスバーでは、 URL にはコンテキストがありません。そのため、上で見たように、完全 (または絶対) URL を指定する必要があります。プロトコル (ブラウザーは既定で HTTP を使用します) やポート番号 (対象となるウェブサーバーが通常以外のポートを使用している場合にのみ必要) を含める必要はありませんが、 URL の他の部分はすべて必要です。

+ +

HTML ページ内など、文書内で URL が使用されている場合は状況が少し異なります。ブラウザーはすでに文書自身の URL を持っているので、この情報を文書内で利用される URL の欠けている部分を補うために利用することができます。絶対 URL相対 URL は、 URL のパスの部分を見るだけで区別することができます。 URL のパスの部分が "/" の文字で始まっていれば、ブラウザーは現在の文書で指定されているコンテキストを参照せずに、サーバーの最上位のルートからそのリソースを取得します。

+ +

これを明確にするためにいくつかの例を見てみましょう。

+ +

絶対 URL の例

+ +
+
完全 URL (以前に使用したものと同じ)
+
+
https://developer.mozilla.org/en-US/docs/Learn
+
+
暗黙のプロトコル
+
+
//developer.mozilla.org/en-US/docs/Learn
+ +

この場合、ブラウザーはその URL をホストしている文書を読み込むために使用されたものと同じプロトコルで、その URL を呼び出します。

+
+
暗黙のドメイン名
+
+
/en-US/docs/Learn
+ +

これは、 HTML 文書内の絶対 URL の最も一般的な使用例です。ブラウザーは、その URL をホストしている文書を読み込むために使用されたものと同じプロトコルおよび同じドメイン名を使用します。メモ: プロトコルを省略せずにドメイン名だけ省略することはできません。

+
+
+ +

相対 URL の例

+ +

次の例をよく理解するために、これらの URL が https://developer.mozilla.org/en-US/docs/Learn という URL にある文書内から呼び出されると仮定しましょう。

+ +
+
サブリソース
+
+
Skills/Infrastructure/Understanding_URLs
+
+ URL が / で始まっていないので、ブラウザーは現在のリソースを含んでいるディレクトリのサブディレクトリでその文書を見つけようとします。そのため、この例では本当に達したい URL である https://developer.mozilla.org/en-US/docs/Learn/Skills/Infrastructure/Understanding_URLs に到達します。
+
ディレクトリツリーを遡る
+
+
../CSS/display
+ +

この場合、 UNIX ファイルシステムの世界から継承された ../ の表記規則を使用して、ブラウザーに1つのディレクトリから上に移動したいことを伝えます。つまり、 https://developer.mozilla.org/en-US/docs/Learn/../CSS/display という URL にアクセスしたいわけで、これは https://developer.mozilla.org/en-US/docs/CSS/display のように単純化できます。

+
+
+ +

セマンティック URL

+ +

URL はとても技術的な香りがするにもかかわらず、人間が読めるウェブサイトの入口を表します。覚えることができ、誰でもブラウザーのアドレスバーに入力することができます。人々はウェブの中核にいるので、セマンティック URL と呼ばれるものを構築することがベストプラクティスと考えられています。セマンティック URL は、技術的な知識に関係なく、誰でも理解できる固有の意味を持つ単語を使用します。

+ +

言語的セマンティックはもちろんコンピューターとは無関係です。おそらくランダムな文字を組み合わせたように見える URL を見たことがあるでしょう。しかし、人間が読める URL を作成することには多くの利点があります。

+ + + +

次のステップ

+ + diff --git a/files/ja/learn/common_questions/what_is_a_web_server/index.html b/files/ja/learn/common_questions/what_is_a_web_server/index.html new file mode 100644 index 0000000000..1278ee5d38 --- /dev/null +++ b/files/ja/learn/common_questions/what_is_a_web_server/index.html @@ -0,0 +1,119 @@ +--- +title: Web サーバとは +slug: Learn/Common_questions/What_is_a_web_server +tags: + - Beginner + - インフラ +translation_of: Learn/Common_questions/What_is_a_web_server +--- +
+

この記事では、Webサーバとは何か、Webサーバの仕組み、なぜWebサーバが重要なのかを復習します。

+
+ + + + + + + + + + + + +
学習の前提:すでにインターネットの仕組みを知っており、Webページ、Webサイト、Webサーバ、検索エンジンの違いを理解していること
学習の目的:Webサーバとは何かを学び、その仕組みに関して全般的な理解すること。
+ +

概要

+ +

「Webサーバ」はハードウェアまたはソフトウェア、あるいは両方が動作しているものを指します。

+ +
    +
  1. ハードウェアの観点では、Webサーバとは、WebサーバソフトウェアとWebサイトのコンポーネントファイル (例えば、 HTML 文書、画像、 CSS スタイルシート、 JavaScript ファイル) を格納しているコンピューターのことです。インターネットに接続され、Webに接続された他の端末と物理的なデータ交換に対応しています。
  2. +
  3. ソフトウェアの観点では、Webサーバとは、ホストにあるファイルに対する、Webユーザーのアクセスを制御する、いくつかの部品の集まりです。最小限の部品は HTTP サーバです。 HTTP サーバは {{Glossary("URL")}} (Webアドレス) および {{Glossary("HTTP")}} (ブラウザーがWebページを閲覧するためのプロトコル) を理解するソフトウェアのことです。格納しているWebサイトのドメイン名 (mozilla.org など) を通してアクセスすることができ、コンテンツをエンドユーザーの端末に配信します。
  4. +
+ +

最も基本的な水準では、ブラウザーはWebサーバが保持しているファイルが必要になったらいつでも、 HTTP でファイルをリクエストします。リクエストが正しいWebサーバ (ハードウェア) に届くと、 HTTP サーバ (ソフトウェア) がリクエストを受け付け、リクエストされた文書を探し (ない場合は 404 レスポンスが返される)、ブラウザーに HTTP を通して送り返します。

+ +

HTTP を通したクライアント/サーバー接続の基本的な説明

+ +

Webサイトを公開するには、静的または動的Webサーバが必要です。

+ +

静的Webサーバ、はスタックとも呼ばれますが、コンピューター (ハードウェア) と HTTP サーバ (ソフトウェア) から構成されます。サーバが保持しているファイルをブラウザーへ「そのまま」送るので、「静的」と呼ばれます。

+ +

動的Webサーバは、静的Webサーバと追加のソフトウェアからなります。追加ソフトウエアは、一般的にはアプリケーションサーバとデータベースからなります。アプリケーションサーバが、 保持しているファイルを変更してから、HTTP サーバを通してブラウザーに送信するので「動的」と呼ばれます。

+ +

例えば、ブラウザーで見ることができる最終的なWebページを生成するために、アプリケーションサーバはデータベースからのコンテンツで HTML のテンプレートを埋めることがあります。 MDN やウィキペディアのようなサイトは非常に多くのWebページを持っていますが、実際の HTML 文書が存在するわけではなく、巨大なデータベースとわずかな HTML テンプレートのみが存在しているのです。この構成をとることで、より速く、より簡単にコンテンツを保守したり配信したりすることができます。

+ +

アクティブラーニング

+ +

まだアクティブラーニングはありません。ご協力をお願いします

+ +

より深く学ぶ

+ +

すでに述べたとおり、Webページを呼び出すために、ブラウザーはWebサーバにリクエストを送信し、Webサーバは自身のストレージスペースからリクエストされたファイルを探し始めます。ファイルを見つけると、サーバはファイルを読み込み、必要に応じて処理を行い、ブラウザーに送信します。それらのプロセスを詳細に見てみましょう。

+ +

ファイルの格納

+ +

Webサーバは最初に、Webサイトの HTML 文書およびその関連資産である画像、 CSS スタイルシート、 JavaScript ファイル、フォント、動画などのファイルを格納する必要があります。

+ +

技術的には、Webサーバとは別のコンピューターにこれらのファイルをすべて保持するようにもできます。しかし、次のような理由で、専用のWebサーバにすべてを格納したほうがはるかに便利です。

+ + + +

これらすべての理由から、良いホスティングのプロバイダーを探すことは、Webサイトを構築する上で重要な部分です。様々なサービス会社が提供するものを探し、ニーズや予算に合う一つを選択しましょう (無料から月当たり数千ドルまでのサービスがあります)。詳しくはこの記事にあります。

+ +

Webのホスティングサービスを構成したら、後はWebサーバにファイルをアップロードするだけです。

+ +

HTTP による通信

+ +

次に、Webサーバは {{Glossary("HTTP")}} (Hypertext Transfer Protocol) への対応を提供しています。名前にある通り、 HTTP はコンピューター間でハイパーテキスト (リンクされたWeb文書) を転送する方法を定義しています。

+ +

{{Glossary("Protocol", "プロトコル")}}は二台のコンピューター間で通信をする規則を設定します。 HTTP はテキストによる、ステートレス(下記参照)のプロトコルです。

+ +
+
テキストによる
+
すべてのコマンドがプレーンテキストで、人間が読める形です。
+
ステートレス
+
サーバもクライアントも以前の通信を覚えていません。例えば、 HTTP 単独では、サーバは入力したパスワードや、処理中のどのステップにいるかを覚えていることはできません。このような仕事をするには、アプリケーションサーバが必要になります。 (以降の記事で様々な技術を説明します。)
+
+ +

HTTP はクライアントとサーバがどのように通信するかについての明確なルールを提供しています。 HTTP 自体については、後で技術記事で説明します。これからは、以下のようなことに気を付けてください。

+ + + +

エラーページの例として、 MDN の 404 ページWebサーバにおいて、 HTTP サーバは受信したリクエストを処理してレスポンスを返す責任があります。

+ +
    +
  1. リクエストを受信すると、 HTTP サーバは最初にリクエストされた URL が既存のファイルに一致するかどうかをチェックします。
  2. +
  3. もしあれば、Webサーバはブラウザーにファイルを送り返します。なければ、アプリケーションサーバが必要なファイルを作成します。
  4. +
  5. どちらの処理もできない場合、Webサーバは {{HTTPStatus("404", "404 Not Found")}} としてよく知られているエラーメッセージをブラウザーに返します。 (このエラーはよく起こるので、多くのWebデザイナーが、404 エラーページのデザインに時間を割くことになります。)
  6. +
+ +

動的コンテンツと静的コンテンツ

+ +

大まかに言って、サーバは静的コンテンツと動的コンテンツのどちらかを提供することができます。「静的」は「そのまま提供する」という意味です。静的なWebサイトは構築するのが最も簡単なので、最初に静的サイトを作成することをお勧めします。

+ +

「動的」はサーバがコンテンツを処理したり、データベースからその場で作成したりすることを意味します。この方法は、柔軟なページを提供できる反面、技術的難易度が高く、Webサイトの構築が複雑になります。

+ +

例を挙げれば、今あなたが見ているページがそれです。この Web サーバには、データベースから記事コンテンツを取り出し、整形し、HTML テンプレート内に配置し、結果を送信するためのアプリケーションサーバがあります。この場合、アプリケーションサーバは Kuma と呼ばれ、 (Django フレームワークを使用した) Python 言語で構築されています。 Mozilla チームは Kuma を MDN の特定のニーズのために作成しましたが、他のたくさんの技術で構築された同様のアプリケーションがたくさんあります。

+ +

アプリケーションサーバは多くの種類があり、特定のサーバを選ぶのはとても難しいといえます。あるものは、ブログ、Wiki、 E ショップなどに特殊化しています。いっぽう、 {{Glossary("CMS")}} (Content Management System) と呼ばれるものはより一般的です。動的Webサイトを構築するときは、ニーズに合ったツールの選択に時間をかけましょう。Webサーバプログラミングを学習しようとするのでなければ (これ自体はエキサイティングな領域ですが)、独自のアプリケーションサーバを作成する必要はありません。それは{{Interwiki("wikipedia", "車輪の再発明")}}のような、無用な努力になるからです。

+ +

次のステップ

+ +

Web サーバのことがよく分かったら、次のステップに進みましょう。

+ + diff --git a/files/ja/learn/common_questions/what_is_accessibility/index.html b/files/ja/learn/common_questions/what_is_accessibility/index.html new file mode 100644 index 0000000000..2790e3bcd2 --- /dev/null +++ b/files/ja/learn/common_questions/what_is_accessibility/index.html @@ -0,0 +1,90 @@ +--- +title: What is accessibility? +slug: Learn/Common_questions/What_is_accessibility +translation_of: Learn/Common_questions/What_is_accessibility +--- +
+

この記事はwebアクセシビリティの背景にある基本的なコンセプトを紹介します。

+
+ + + + + + + + + + + + +
前提条件:なし
対象:アクセスビリティが何なのか、なぜ重要なのかを学ぶ
+ +

概要

+ +

物理的、技術的制限のせいで、たぶんあなたの訪問者はあなたの望むような体験をあなたのウェブサイトからできません。 この記事では一般的なアクセシビリティの原則や平易ないくつかの規則を示します。

+ +

能動的学習

+ +

まだ可能な能動的学習がありません。 Please, consider contributing.

+ +

深く掘っていく

+ +

アクセスビリティ: 一般的な原則

+ +

まず、我々は負の制限に伴うアクセスビリティに関連付けられなければならないだろう。このビルはアクセスブルでなければならず、そうなのでトイレのサイズやエレベーターの設置場所のこれらの規制に従わなければならない。

+ +

それはアクセスビリティで考えられる狭い方法である。人々に委ねたり、より多くの顧客に出す、びっくりするような方法を考えてみて下さい。 ブラジルにいる人々に英語のサイトをどのように出しますか? スマートフォンのブラウザが重く、大きなデスクトップモニターにデザインされたウェブサイトが乱雑であったり、帯域が制限されていないことなどできますか?それらは別の場所に行くべきでしょう。一般的にターゲット顧客の観点から我々のプロダクトを考え、変化を採用しなければなりません。従って、アクセスビリティなのです。

+ +

ウェブアクセシビリティ

+ +

ウェブの特定の文脈において、アクセシビリティは障害、場所、技術的な制約、他の事情などにも関わらずコンテンツからの利益を誰もが得られることを意味します。 

+ +

ビデオについて考えてみましょう

+ +
+
聴覚障害
+
ビデオを聴覚障害の人はどのようにみるのでしょうか?  字幕を提供しなくてはなりませんし、 — もしくはそうであってもより良いのはフルテキストの写しです。
+
もしくはその人に適応したボリュームに調整してあげることができます。
+
視覚障害
+
もう一度、ビデオを上映することなしにテキストの写しを説明してあげたり、音声説明を提供することができます。 (ビデオで何が起こっているか述べる画面外の音声)
+
中断する能力
+
ユーザーがビデオで何か理解できない事態に見舞われるかもしれません。ビデオを止めて、字幕や情報のプロセス読むでしょう。 
+
キーボードの能力
+
ビデオの内外のタブを使うことで、仕掛けなしにビデオの再生中断をします。
+
+ +

ウェブアクセスビリティの基本

+ +

いくつかの必要性を基本的なウェブアクセスビリティは含みます。

+ + + +

そして、今、始めよう。

+ +

アクセスビリティのチャンピオンたち

+ +

1999年以来, the {{Glossary("W3C")}} は{{Glossary("WAI","Web Accessibility Initiative")}}と呼ばれるグループを動かしてきた。このグループはガイドライン、マテリアル、国際的なリソースを通じてアクセスビリティを促進してきた。

+ +

より詳細には

+ +

以下を参照して下さい:

+ + + +

次のステップ

+ +

アクセスビリティはウェブデザインや技術構造の両方にインパクトを与えることができます。

+ + diff --git a/files/ja/learn/common_questions/what_software_do_i_need/index.html b/files/ja/learn/common_questions/what_software_do_i_need/index.html new file mode 100644 index 0000000000..9b042b3c06 --- /dev/null +++ b/files/ja/learn/common_questions/what_software_do_i_need/index.html @@ -0,0 +1,222 @@ +--- +title: Web サイトを作成するのにどんなソフトウェアが必要か? +slug: Learn/Common_questions/What_software_do_I_need +tags: + - NeedsActiveLearning + - WebMechanics + - 初心者 +translation_of: Learn/Common_questions/What_software_do_I_need +--- +
+

この記事では、Webサイトを編集、アップロード、または閲覧するときに必要なソフトウェアについて説明します。

+
+ + + + + + + + + + + + +
学習の前提:Web ページ、Web サイト、Web サーバ、検索エンジンの違いを理解しておいてください。
学習の目的:Web サイトを編集、アップロード、閲覧するときに必要なソフトウェアについて学びます。
+ +

概要

+ +

Web 開発に必要なほとんどのプログラムは無料でダウンロードできます。この記事では、いくつかのリンクを提供します。

+ +

次のようなツールが必要です。

+ + + +

ほぼすべてのオペレーティングシステムには、デフォルトでテキストエディタとブラウザが含まれており、Web サイトの閲覧に使用できます。結果的には、通常はファイルを Web サーバに転送するためのソフトウェアを入手するだけで済みます。

+ +

アクティブラーニング

+ +

実習はまだありません。あなたの力をお貸しください

+ +

より深く掘り下げる

+ +

Webページの作成と編集

+ +

Webサイトを作成したり編集したりするために、テキストエディターが必要です。テキストエディターは、形式を持たないテキストファイルの作成や修正を行います。 {{Glossary("RTF")}} のような他の形式では、太字や下線のような書式を追加することができます。しかし、これらの形式はWebページの作成には適していません。Webサイトを構築する際に幅広い作業に使用するので、どのテキストエディターを使用するかを考えておきましょう。

+ +

すべてのデスクトップ OS には、基本的なテキストエディターが付属しています。これらのエディターはすべて簡単なものですが、Webページのコーディングのための特別な機能は持っていません。そこで、お望みなら、利用可能なサードパーティのツールがたくさんあります。サードパーティのテキストエディターには、構文の色付け、自動補完、セクションの折りたたみ、コード検索などの便利な追加機能がよくついています。エディターの簡単なリストを挙げておきます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OS内蔵エディターサードパーティのエディター
Windows + + + +
Mac OS + + + +
Linux + + + +
Chrome OS + +
+ +

こちらは、高度なテキストエディターのスクリーンショット例です。

+ +

Notepad++ のスクリーンショット

+ +

こちらは、オンラインのテキストエディターのスクリーンショット例です。

+ +

ShiftEdit のスクリーンショット

+ +

Web上へのファイルのアップロード

+ +

Web サイトを公開する準備が整ったら、Web ページを Web サーバにアップロードする必要があります。さまざまなプロバイダからサーバ上のスペースを購入できます (Web で何かをするためにどのくらいコストがかかりますか?を参照)。どのプロバイダを使用するかが決まったら、プロバイダは通常、SFTP URL、ユーザ名、パスワード、およびそれらのサーバへの接続に必要なその他の情報の形式で、アクセス情報をメールで送信します。(S)FTPは今や幾分時代遅れになっていて、RSyncGit/GitHub のような他のアップロードシステムが普及し始めていることを覚えておいてください。

+ +
+

メモ: FTP は本質的に安全ではありません。ホスティングプロバイダが安全な接続、例えば  SSH を介した SFTP または RSync の使用を許可していることを確認してください。

+
+ +

Web サーバを作成する際、Web サーバにファイルをアップロードすることは非常に重要なステップなので、別の記事で詳しく説明します。ここでは、単純な機能に限った無料 (S)FTP クライアントの例を示すにとどめます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSFTP ソフトウェア
Windows + + + +
Linux + +
Mac OS + +
Chrome OS + +
+ +

Webサイトの閲覧

+ +

ご存知の通り、Webサイトを閲覧するためにはWebブラウザが必要です。 私用でブラウザ使う時には、たくさんのブラウザの選択肢がありますが、あなたがWebサイトを開発している時には、あなたのWebサイトがほとんどの人々のために働くことを確認するために、少なくとも以下のブラウザで動作確認、テストをする必要があります。

+ + + +

特定のグループ (技術プラットフォームや国など) を対象にする場合は、追加で Opera, Konqueror, UC Browser などブラウザでサイトをテストする必要があります。

+ +

しかし、ブラウザによっては特定のオペレーティングシステムでしか動作しないものがあるため、テストをすることは複雑になります。 Apple Safari は iOS と Mac OS 上で動作し、 Internet Explorer は Windows 上でのみ動作します。 BrowsershotsBrowserstack のようなサービスを利用するのが最善です。 Browsershots は、様々なブラウザで見た場合のWebサイトのスナップショットを提供します。 Browserstack は実際には仮想マシンへの完全なリモートアクセスを提供し、最も一般的な環境でサイトをテストすることができます。他にも、独自の仮想マシンをセットアップする方法もありますが、それにはいくらかの専門知識が必要です。 (もしこの方法を使うのであれば、 Microsoft は modern.ie ですぐに使える仮想マシンを含む開発者のためのいくつかのツールを提供しています。)

+ +

是非、実際のデバイス、特に実際のモバイル機器でいくつかのテストを実行してください。モバイル機器のシミュレーションは、進化中の新技術であり、デスクトップのシミュレーションよりも信頼性が低いです。もちろん、モバイル機器はお金を必要としますので、 Open Device Lab の取り組みを見てみることをお勧めします。多くのプラットフォームでテストする場合は、過度な出費を抑えて機器を共有することもできます。

+ +

次のステップ

+ + diff --git a/files/ja/learn/css/building_blocks/advanced_styling_effects/index.html b/files/ja/learn/css/building_blocks/advanced_styling_effects/index.html new file mode 100644 index 0000000000..650851a8a3 --- /dev/null +++ b/files/ja/learn/css/building_blocks/advanced_styling_effects/index.html @@ -0,0 +1,426 @@ +--- +title: ボックスの高度なエフェクト +slug: Learn/CSS/Building_blocks/Advanced_styling_effects +tags: + - Article + - Beginner + - Blend modes + - Boxes + - CSS + - CodingScripting + - Filters + - Styling + - box shadows + - effects +translation_of: Learn/CSS/Building_blocks/Advanced_styling_effects +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/Styling_boxes/Styling tables", "Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper", "Learn/CSS/Styling_boxes")}}
+ +

この記事はトリックの箱として機能し、ボックスの影、ブレンドモード、フィルタのようなボックスの装飾に使用できる高度な機能のいくつかを紹介します。

+ + + + + + + + + + + + +
前提知識:HTML の基礎(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:ボックスの高度なエフェクトの使用方法についてのアイデアを得ることと、CSS 言語に登場しているいくつかの新生のスタイル設定ツールについて知ること。
+ +

ボックスの影

+ +

テキストの装飾のモジュールに戻って、{{cssxref("text-shadow")}} プロパティを見てみましょう。 これにより、要素のテキストに1つ以上のドロップシャドウを適用できます。 ボックスにも同等のプロパティがあります — {{cssxref("box-shadow")}} を使用すると、実際の要素ボックスに1つ以上のドロップシャドウを適用できます。 テキストの影と同様に、ボックスの影はブラウザー間で非常によくサポートされていますが、IE9 以降のみです。 古いバージョンの IE を使用しているユーザーは、影なしで対処するしかないかもしれないので、コンテンツがそれらなしで判読可能であることを確かめるためにデザインをテストするだけです。

+ +

このセクションの例は box-shadow.html にあります(ソースコードも参照)。

+ +

簡単なボックスの影

+ +

物事を始めるための簡単な例を見てみましょう。 まず、いくつかの HTML です。

+ +
<article class="simple">
+  <p><strong>Warning</strong>: The thermostat on the cosmic transcender has reached a critical level.</p>
+</article>
+ +

そして、CSS です。

+ +
p {
+  margin: 0;
+}
+
+article {
+  max-width: 500px;
+  padding: 10px;
+  background-color: red;
+  background-image: linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,0.25));
+}
+
+.simple {
+  box-shadow: 5px 5px 5px rgba(0,0,0,0.7);
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('A_simple_box_shadow', '100%', 100) }}

+ +

box-shadow プロパティ値に次の4つの項目があることがわかります。

+ +
    +
  1. 最初の長さの値は水平オフセット(horizontal offset)です — 影が元のボックスから右へオフセットした距離です(値が負の場合は左)。
  2. +
  3. 2番目の長さの値は垂直オフセット(vertical offset)です — 影が元のボックスから下方向へオフセットした距離です(値が負の場合は上方向)。
  4. +
  5. 3番目の長さの値は、ぼかし半径(blur radius)です — 影に適用されるぼかしの量です。
  6. +
  7. 色の値は、影の基本色(base color)です。
  8. +
+ +

これらの値を定義するために必要な長さと色の単位を使用できます。

+ +

複数のボックスの影

+ +

次のように、1つの box-shadow の宣言で、複数のボックスの影をコンマで区切って指定することもできます。

+ + + +
p {
+  margin: 0;
+}
+
+article {
+  max-width: 500px;
+  padding: 10px;
+  background-color: red;
+  background-image: linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,0.25));
+}
+
+.multiple {
+  box-shadow: 1px 1px 1px black,
+              2px 2px 1px black,
+              3px 3px 1px red,
+              4px 4px 1px red,
+              5px 5px 1px black,
+              6px 6px 1px black;
+}
+ +

そして、この結果を得ます。

+ +

{{ EmbedLiveSample('Multiple_box_shadows', '100%', 100) }}

+ +

ここでは、複数の色付きレイヤーを持つ凸型のボックスを作成することで楽しいことができましたが、例えば複数の光源に基づいて影を付けてよりリアルな外観を作成するなど、好きな方法で使用できます。

+ +

その他のボックスの影の機能

+ +

{{cssxref("text-shadow")}} とは異なり、{{cssxref("box-shadow")}} には inset キーワードがあります — これを影の宣言の最初に置くと、外側の影ではなく内側の影になります。 見て理解してもらいましょう。

+ +

まず、この例では一部異なる HTML を使用します。

+ +
<button>Press me!</button>
+ +
button {
+  width: 150px;
+  font-size: 1.1rem;
+  line-height: 2;
+  border-radius: 10px;
+  border: none;
+  background-image: linear-gradient(to bottom right, #777, #ddd);
+  box-shadow: 1px 1px 1px black,
+              inset 2px 3px 5px rgba(0,0,0,0.3),
+              inset -2px -3px 5px rgba(255,255,255,0.5);
+}
+
+button:focus, button:hover {
+  background-image: linear-gradient(to bottom right, #888, #eee);
+}
+
+button:active {
+  box-shadow: inset 2px 2px 1px black,
+              inset 2px 3px 5px rgba(0,0,0,0.3),
+              inset -2px -3px 5px rgba(255,255,255,0.5);
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('Other_box_shadow_features', '100%', 70) }}

+ +

ここでは、フォーカス/ホバー/アクティブ状態と共にボタンの装飾を設定しました。 このボタンには、デフォルトで単純な黒いボックスの影が設定されています。 さらに、1つは明るく、もう1つは暗い、2つの内側の影を、ボタンに素晴らしい陰影エフェクトを与えるためにボタンの反対側の角に置きます。

+ +

ボタンが押されたとき、アクティブ状態は最初のボックスの影を非常に暗い内側の影と交換し、押されているボタンの外観を与えます。

+ +
+

: box-shadow 値に設定できる別の項目があります — 色の値の直前に別の長さの値をオプションで設定できるのが、広がり半径(spread radius)です。 設定すると、影が元のボックスよりも大きくなります。 あまり一般的ではありませんが、言及する価値があります。

+
+ +

フィルタ

+ +

CSS フィルタは、Photoshop のようなグラフィックパッケージのレイヤーにフィルタを適用するのと同じ方法で、要素にフィルタを適用する方法を提供します。 利用可能ないくつかの異なるオプションがあり、{{cssxref("filter")}} のリファレンスページでそれらすべてについて詳しく読むことができます。 このセクションでは、構文について説明し、結果がどれほど楽しいものになるかを説明します。

+ +

基本的に、フィルタは任意の要素、ブロック、インラインに適用することができます — あなたは単に filter プロパティを使い、それに特定のフィルタ関数の値を与えるだけです。 利用可能なフィルタオプションの中には他の CSS 機能と非常によく似た機能を持つものがあります。 例えば、drop-shadow() は非常によく似た方法で機能し、{{cssxref("box-shadow")}} や {{cssxref("text-shadow")}} と同じエフェクトをもたらします。 しかし、フィルタに関して本当に素晴らしいことは、ボックス自体を1つの大きな塊としてではなく、ボックス内のコンテンツの正確な形状に作用することです。 それは常に望んだものではないかもしれませんが、もっときれいに見えます。 簡単な例を使用して、意味を説明しましょう。

+ +

まず、いくつかの簡単な HTML です。

+ +
<p class="filter">Filter</p>
+
+<p class="box-shadow">Box shadow</p>
+
+ +

そして今、いくつかの CSS はドロップシャドウをそれぞれに適用します。

+ +
p {
+  margin: 1rem auto;
+  padding: 20px;
+  width: 100px;
+  border: 5px dashed red;
+}
+
+.filter {
+  -webkit-filter: drop-shadow(5px 5px 1px rgba(0,0,0,0.7));
+  filter: drop-shadow(5px 5px 1px rgba(0,0,0,0.7));
+}
+
+.box-shadow {
+  box-shadow: 5px 5px 1px rgba(0,0,0,0.7);
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('Filters', '100%', 200) }}

+ +

ご覧のとおり、フィルタのドロップシャドウは、テキストの正確な形と境界線の破線に従います。 ボックスの影はボックスの四角形にちょうど従っています。

+ +

その他注意すべきこと。

+ + + +
+

: コードで接頭辞を使用する場合は、接頭辞が必要なバージョンと接頭辞の付かないバージョンを必ずすべて含めてください。 そうすれば、可能な限り最大数のブラウザーでこの機能を使用できるようになり、後でブラウザーが接頭辞をなくすときに接頭辞の付かないバージョンも使用できます。 また、これらの実験的な機能は変更される可能性があるため、コードが壊れる可能性があります。 接頭辞が削除されるまで、これらの機能を試してみることが本当に最善です。

+
+ +

その他のフィルタの例が filters.html にあります(ソースコードも参照)。

+ +

ブレンドモード

+ +

CSS ブレンドモードでは、2つの要素が重なるときにブレンドエフェクトを指定する要素にブレンドモードを追加できます — 各ピクセルに表示される最終的な色は、元のピクセル色とその下のレイヤーにあるピクセル色を組み合わせた結果になります。 ブレンドモードは、Photoshop のようなグラフィックアプリケーションのユーザーにとっては非常によく知られています。

+ +

CSS でブレンドモードを使用する次の2つのプロパティがあります。

+ + + +

こちらの blend-modes.html サンプルページ(ソースコードを参照)、および {{cssxref("<blend-mode>")}} リファレンスページには、ここに掲載されている以外にもたくさんの例があります。

+ +
+

: ブレンドモードもまた非常に新しいもので、フィルタよりもサポートが多少劣ります。 Edge にはまだサポートがありませんし、Safari はブレンドモードオプションのいくつかをサポートするだけです。

+
+ +

background-blend-mode

+ +

ここでも、これをよりよく理解できるように、いくつかの例を見てみましょう。 まず、{{cssxref("background-blend-mode")}} です — ここでは次のいくつかの簡単な {{htmlelement("div")}} を示すことで、オリジナルとブレンドバージョンを比較できます。

+ +
<div>
+</div>
+<div class="multiply">
+</div>
+ +

次にいくつかの CSS です — <div> に1つの背景画像と緑色の背景色を追加しています。

+ +
div {
+  width: 250px;
+  height: 130px;
+  padding: 10px;
+  margin: 10px;
+  display: inline-block;
+  background: url(https://mdn.mozillademos.org/files/13090/colorful-heart.png) no-repeat center 20px;
+  background-color: green;
+}
+
+.multiply {
+  background-blend-mode: multiply;
+}
+ +

結果はこれです — 左側にオリジナル、右側に乗算ブレンドモードがあります。

+ +

{{ EmbedLiveSample('background-blend-mode', '100%', 200) }}

+ +

mix-blend-mode

+ +

それでは、{{cssxref("mix-blend-mode")}} を見てみましょう。 ここでは上と同様の2つの <div> を提示しますが、要素がどのようにブレンドされるかを示すために、それぞれが紫色の背景を持つ単純な <div> の上に乗っています。

+ +
<article>
+  No mix blend mode
+  <div>
+
+  </div>
+  <div>
+  </div>
+</article>
+
+<article>
+  Multiply mix
+  <div class="multiply-mix">
+
+  </div>
+  <div>
+  </div>
+</article>
+ +

次がこれをスタイルする CSS です。

+ +
article {
+  width: 280px;
+  height: 180px;
+  margin: 10px;
+  position: relative;
+  display: inline-block;
+}
+
+div {
+  width: 250px;
+  height: 130px;
+  padding: 10px;
+  margin: 10px;
+}
+
+article div:first-child {
+  position: absolute;
+  top: 10px;
+  left: 0;
+  background: url(https://mdn.mozillademos.org/files/13090/colorful-heart.png) no-repeat center 20px;
+  background-color: green;
+}
+
+article div:last-child {
+  background-color: purple;
+  position: absolute;
+  bottom: -10px;
+  right: 0;
+  z-index: -1;
+}
+
+.multiply-mix {
+  mix-blend-mode: multiply;
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('mix-blend-mode', '100%', 200) }}

+ +

ここでは、乗算混合(multiply mix)ブレンドが2つの背景画像だけでなく、その下の <div> からの色もブレンドしていることがわかります。

+ +
+

: {{cssxref("position")}}、{{cssxref("top")}}、{{cssxref("bottom")}}、{{cssxref("z-index")}} など、上記のレイアウトプロパティの一部を理解していなくても心配しないでください。 これらについては、CSS レイアウトのモジュールで詳しく説明します。

+
+ +

-webkit-background-clip: text

+ +

先に進む前に、簡単に言及しておきたいと思うもう1つの新生機能は、{{cssxref("background-clip")}} の text 値です(現在 Chrome、Safari、Opera でサポートされており、Firefox で実装されています)。 独自の -webkit-text-fill-color: transparent; 機能とともに使用すると、背景画像を要素のテキストの形に切り取ることができ、いくつかの素晴らしいエフェクトをもたらします。 これは公式の標準ではありませんが、普及しており、開発者によってかなり広く使用されているため、複数のブラウザーにわたって実装されています。 このコンテキストで使用すると、Webkit / Chrome 以外のブラウザーでも、両方のプロパティに -webkit- ベンダー接頭辞が必要になります。

+ +
.text-clip {
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+}
+ +

では、なぜ他のブラウザーが -webkit- 接頭辞を実装したのでしょうか? 主にブラウザーの互換性のためにです — 非常に多くのウェブ開発者が -webkit- 接頭辞を使用してウェブサイトを実装し始めているため、実際には標準に従っているのに、他のブラウザーでは壊れているように見え始めました。 そこで彼らはそのような機能をいくつか実装することを余儀なくされました。 これはあなたの仕事で標準的でなく接頭辞の付いた CSS 機能を使用する危険性を浮き彫りにします — それらはブラウザーの互換性の問題を引き起こすだけでなく、変更される可能性もあるため、コードはいつでも壊れる可能性があります。 標準に固執するほうがはるかに良いです。

+ +

本番環境でこのような機能を使用したい場合は、ブラウザー間で徹底的なテストを行い、機能が機能しない場合でもサイトが引き続き使用可能であることを確認してください。

+ +
+

: 完全な -webkit-background-clip: text のコードの例については、background-clip-text.html を参照してください(ソースコードも参照)。

+
+ +

能動的学習: いくつかのエフェクトを用いた実験

+ +

今度は、あなたの番です。 この能動的学習のために、下に提供されているコードを使用して、上で読んだエフェクトのいくつかを試してみてください。

+ +

間違えた場合は、Reset ボタンを使用して例をいつでもリセットできます。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 820) }}

+ +

まとめ

+ +

この記事が楽しかったことを願っています — ぴかぴかのおもちゃで遊ぶのは概してそうで、最先端のブラウザーで、どのような種類のツールが使用可能になりつつあるのかを見るのはいつも面白いです。 ボックスの装飾の記事の終わりに到達したので、次に私たちの評価であなたのボックスの装飾のスキルをテストします。

+ +

{{PreviousMenuNext("Learn/CSS/Styling_boxes/Styling tables", "Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper", "Learn/CSS/Styling_boxes")}}

+ +

 

+ +

このモジュール内の文書

+ + + +

 

diff --git a/files/ja/learn/css/building_blocks/backgrounds_and_borders/index.html b/files/ja/learn/css/building_blocks/backgrounds_and_borders/index.html new file mode 100644 index 0000000000..d2e65370cd --- /dev/null +++ b/files/ja/learn/css/building_blocks/backgrounds_and_borders/index.html @@ -0,0 +1,338 @@ +--- +title: 背景と枠線 +slug: Learn/CSS/Building_blocks/Backgrounds_and_borders +tags: + - Background + - Beginner + - CSS + - Image + - Learn + - Position + - borders + - color +translation_of: Learn/CSS/Building_blocks/Backgrounds_and_borders +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks")}}
+ +
+ +

このレッスンでは、CSS の背景・枠線モジュールの機能を使ったクリエイティブな表現方法をいくつか見ていきます。グラデーション、背景画像、角の丸めを加えることを通じて、CSS を使ったスタイリングの多様な課題に対する解答が得られるでしょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:ボックスの背景と枠線をスタイルする方法を学ぶ。
+ +

CSS による背景の設定

+ +

CSSの {{cssxref("background")}} プロパティは、このレッスンで説明する多くの個別指定プロパティ(longhand property)を一度に指定する一括指定プロパティ(shorthand property)です。スタイルシートで複雑な背景プロパティを見かけると、一度に多くの値を渡していて理解するのが少し難しく感じるかもしれません。

+ +
.box {
+  background: linear-gradient(105deg, rgba(255,255,255,.2) 39%, rgba(51,56,57,1) 96%) center center / 400px 200px no-repeat,
+  url(big-star.png) center no-repeat, rebeccapurple;
+} 
+
+ +

一括指定の仕方については後ほど改めて扱います。まずは背景に対してCSSで何ができるのかを知るために、ひとつひとつのプロパティを見ていきましょう。

+ +

背景色

+ +

 {{cssxref("background-color")}} プロパティは、要素の背景色を定義します。このプロパティは、有効な<color>値を受け入れます。background-colorは、要素の Content box, Padding box の範囲でコンテンツの下に広がります。

+ +

次の例では、さまざまな色の値値を使用して、ボックス(.box)、見出し(h2)、および {{htmlelement("span")}} 要素に背景色を指定しています。

+ +

利用可能な <color> を使ってみましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/color.html", '100%', 600)}}

+ +

背景画像

+ +

 {{cssxref("background-image")}} プロパティは、要素の背景に表示する画像を指定します。次の例には、2個のボックスがあります。片方のボックスでは背景画像がボックスより大きく、他方のボックスの背景画像は小さな星の画像です。

+ +

この例は、背景画像に関する2つのことを示しています。
+ デフォルトでは、大きな画像はボックスに収まるように縮小されず、一部分のみが表示されます。いっぽう、小さな画像はボックスの内側いっぱいまで繰り返されます。この場合、実際の画像は星1個のみです。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/background-image.html", '100%', 600)}}

+ +

背景画像と背景色を同時に指定すると、背景色より手前に背景画像が表示されます。上記の例にbackground-colorプロパティを追加して、動作を確認してみましょう。

+ +

背景画像の繰り返しの指定

+ +

 {{cssxref("background-repeat")}} プロパティは、画像の繰り返し表示の動作を制御するために使用されます。使用可能な値には次のものがあります:

+ + + +

以下の例でこれらの値を試してみましょう。値をno-repeatに設定したため、星が1つだけ表示されます。異なる値(repeat-xrepeat-y)に変えてみて、その効果を確認してみましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/repeat.html", '100%', 600)}}

+ +

背景画像のサイズ指定

+ +

先ほどの例では、背景を設定したい要素より画像のほうが大きいため画像の一部しか表示されませんでした。 {{cssxref("background-size")}} プロパティを使用して、背景内に収まるように画像のサイズを調整できます。

+ +

background-sizeプロパティは、<length> または <percentage> の値をとることができます。

+ +

また、次のキーワードを使うこともできます:

+ + + +

次の例では、<length>値を使用して先ほどの大きな画像がボックス内におさまる大きさに変更しました。結果として、画像が歪んでいることがわかります。

+ +

以下を試してみましょう。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/size.html", '100%', 750)}}

+ +

背景画像の位置の指定

+ +

 {{cssxref("background-position")}} プロパティを適用すると、そのボックス上で背景画像を表示する位置を選択できます。このプロパティでは、ボックスの左上隅を(0, 0)として、水平方向の座標軸(horisontal axis)をx軸(x axis, 複数形はaxes)、垂直方向の座標軸(vertical axis)をy軸(y axis)とする座標系にそって画像を配置します。

+ +
+

: デフォルトのbackground-positionの値は(0, 0)です。

+
+ +

最も一般的なbackground-positionの値は、2個の値をとります—水平方向、垂直方向の順で値を指定します。

+ +

toprightなどのキーワードを使用できます (詳しくは{{cssxref("background-image")}}ページを参照):

+ +
.box {
+  background-image: url(star.png);
+  background-repeat: no-repeat;
+  background-position: top center;
+} 
+
+ +

そして、 <length>および<percentage>を使用できます:

+ +
.box {
+  background-image: url(star.png);
+  background-repeat: no-repeat;
+  background-position: 20px 10%;
+} 
+
+ +

次のように、キーワードの値を<length>や<percentage>の値と混在させてもかまいません。

+ +
.box {
+  background-image: url(star.png);
+  background-repeat: no-repeat;
+  background-position: top 20px;
+}
+ +

最後に、4つの値をとる構文を使って、ボックスのいずれかの端からの距離を示すこともできます。この場合の長さは、その直前の値で指定した位置からの距離(オフセット, offset)です。下のCSSでは、背景を上(top)から20px、右(right)から10pxに配置しています。

+ +
.box {
+  background-image: url(star.png);
+  background-repeat: no-repeat;
+  background-position: top 20px right 10px;
+} 
+ +

次の例を使い、プロパティの値を変えてボックス内で星を動かしてみましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/position.html", '100%', 600)}}

+ +
+

: background-position は {{cssxref("background-position-x")}} および {{cssxref("background-position-y")}} の一括指定プロパティで、それぞれの座標軸の方向の位置を個別に設定できます。

+
+ +

グラデーション背景

+ +

グラデーション(gradient, 勾配(こうばい) )は、背景に使用する場合には画像と同じようにふるまいます。グラデーションは{{cssxref("background-image")}}プロパティを使用して設定されます。

+ +

<gradient>データ型のMDNページで、さまざまな種類のグラデーションとそれらを使ってできることについて詳しく読むことができます。Webで数多く提供されているCSSグラデーションジェネレーター(例えば "CSS Gradient")を使用して、グラデーションを楽しく試せます。このWebサービスでは、グラデーションを作成したのち、グラデーションを生成するソースコードをコピー&ペーストできます。

+ +

以下の例でいろいろなグラデーションを試してみましょう。 1つめのボックスには、ボックス全体に広がる線形グラデーション(linear gradient)を指定しています。2つめのボックスには、サイズを設定して(そのために繰り返されている)放射状グラデーション(radial gradinet)を指定しています。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/gradients.html", '100%', 600)}}

+ +

複数の背景画像

+ +

background-imageプロパティにコンマ区切りで複数の画像を指定することで、複数の背景画像を使用することもできます。

+ +

これを行うと、背景画像が互いに重なり合う可能性があります。背景は、最後に指定したものが一番下に置かれ、先のものが順に上に重ねられます。

+ +
+

: グラデーションを通常の背景画像と同じように重ね合わせることができます。

+
+ +

他のbackground-*プロパティも、background-imageと同じ方法でコンマ区切りの値を持つことができます:

+ +
background-image: url(image1.png), url(image2.png), url(image3.png), url(image1.png);
+background-repeat: no-repeat, repeat-x, repeat;
+background-position: 10px 20px,  top right;
+ +

プロパティに指定した複数のプロパティ値は、他のプロパティの同じ位置にある値と対応します。上の例で、image1background-repeat値はno-repeatです。では、プロパティごとに値の個数が異なるとどうなるでしょうか?答えは、個数が少ない値が繰り返し使われる、ということです。上の例では、4つの背景画像がありますが、2つの background-position の値しかありません。最初の2つの位置の値は対応する位置の画像に適用され、その後は繰り返されます。つまり、image3には1番目、image4には2番目の値がふたたび使われます。

+ +

実際に試してみましょう。以下の例には2つの画像があります。重ね合わせの順序を確かめるために、どの背景画像を先にするかを変えてみてください。また、他のプロパティを操作して、位置、サイズ、繰り返し方法を変えてみてください。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/multiple-background-image.html", '100%', 500)}}

+ +

スクロール時の背景画像の固定

+ +

背景に使用できるもうひとつのオプションは、コンテンツがスクロールするときのスクロール方法を指定することです。これは, {{cssxref("background-attachment")}} プロパティを使用して制御され、次の値を取ることができます:

+ + + +

 {{cssxref("background-attachment")}} プロパティはスクロールするコンテンツがある場合にのみ効果があります。3つの値の違いを示すデモ(background-attachment.html)を作成したのでご覧ください(ソースコードも公開しています)。

+ +

背景に関する指定をまとめておこなう

+ +

このレッスンの冒頭で、 {{cssxref("background")}} プロパティを使って背景が指定されている場合についてふれました。この一括指定プロパティを使うと、複数のプロパティを一度に設定できます。

+ +

複数の背景を使用する場合は、最初の背景に対するプロパティをすべて指定してから、カンマで区切って次の背景を追加します。以下の例では、サイズと位置を伴ったグラデーションno-repeatと位置指定を伴った背景画像、最後に背景色を指定しています。

+ +

背景画像に関する一括指定を書くとき、いくつかのルールを守る必要があります。例えば:

+ + + +

すべての注意点を確認するには、 {{cssxref("background")}} のMDNページをご覧ください。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/background.html", '100%', 700)}}

+ +

アクセシビリティの観点での注意点

+ +

テキストを背景画像や背景色の上に配置する際には、閲覧者がテキストを読み取れるだけの十分なコントラストを確保するよう注意する必要があります。画像の上にテキストを配置する場合は、画像が読み込まれない場合でもテキストが読み取れるような背景色も指定する必要があります。

+ +

スクリーンリーダーは背景画像を解析できないため、画像は装飾としての役割のみを担うべきです。重要なコンテンツはすべてHTMLページのなかで表現するべきで、背景画像のなかに含めるべきではありません。

+ +

枠線

+ +

ボックスモデルについて学習するとき、枠線(border)がボックスのサイズにどのように影響するかを見てきました。このレッスンでは、枠線をクリエイティブに活用する方法を見ていきます。

+ +

通常、CSSで要素に枠線を追加するときは、CSSの1行で枠線の色、幅、スタイルを指定する一括指定プロパティを使います。

+ +

 {{cssxref("border")}}:を使用して、ボックスの4辺すべてに枠線を設定できます。

+ +
.box {
+  border: 1px solid black;
+} 
+ +

または、次のように、ボックスの1つの辺を対象にすることができます。:

+ +
.box {
+  border-top: 1px solid black;
+} 
+ +

一括指定で指定した個々のプロパティは次のとおりです:

+ +
.box {
+  border-width: 1px;
+  border-style: solid;
+  border-color: black;
+} 
+ +

一辺ごとの個別指定については次のようになります:

+ +
.box {
+  border-top-width: 1px;
+  border-top-style: solid;
+  border-top-color: black;
+} 
+ +
+

: top, right, bottom, leftの各方向の枠線を指定するプロパティには、HTML文書の書字モード(writing mode)と結びついた論理プロパティ(logical property)が割り当てられています(書字モードは、左から右、右から左、上から下といったテキストの方向を制御するものです)。次のレッスンでは、さまざまなテキストの方向の処理について説明します。

+
+ +

枠線にはさまざまなスタイルを指定できます。以下の例では、ボックスの4辺にそれぞれ異なる枠線スタイルを使用しています。枠線の色、幅、スタイルを試して、枠線の動作を確認しましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/borders.html", '100%', 700)}}

+ +

角の丸み

+ +

{{cssxref("border-radius")}}一括指定プロパティと、各々の角に対応した個別指定プロパティを使用して、ボックスの角の丸みを実現できます。各プロパティは2個の<length>または<percentage>を値として使用できます。最初の値は水平方向の半径(radius)を定義し、2番目の値は垂直方向の半径を定義します。多くの場合、1つの値のみを指定して両方向に適用します。

+ +

例えば、ボックスの4つの角すべてに半径 10px の丸みを持たせるには:

+ +
.box {
+  border-radius: 10px;
+} 
+ +

または、右上角の水平方向の半径を1em、垂直方向の半径を 10% にするには:

+ +
.box {
+  border-top-right-radius: 1em 10%;
+} 
+ +

以下の例では、はじめに4つの角すべてについて角の丸みを設定したのち、右上角を他と異なる値に変更しました。値を変えて試してみましょう。使用できる構文は{{cssxref("border-radius")}} プロパティのページを見て確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/corners.html", '100%', 650)}}

+ +

背景と枠線を試す

+ +

学んだ知識を試すために、背景と枠線を使って次のものを作成してみてください。コード例を出発点として使ってください:

+ +
    +
  1. ボックスに幅が5pxの黒い実線の境界線を付け、角に半径が10pxの丸みをつけてください。
  2. +
  3. 背景画像を追加し(URL balloons.jpgを使用)、ボックスを覆うようにサイズを変更してください。
  4. +
  5. <h2>に半透明の黒い背景色を指定し、テキストを白にしてください。
  6. +
+ +

{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/task.html", '100%',650)}}

+ +
+

: ここで正解を確認できますが、まずは自分の力で解答してみてください!

+
+ +

まとめ

+ +

このレッスンではかなり多くのことを説明してきましたが、そのなかで背景や枠線をボックスに追加する方法がたくさんあることがわかりました。これまでに説明した機能について詳しく知りたくなったら、各プロパティのMDNページに目を通してみましょう。これらのページには知識を活用したり強化したりするための使用例が書かれています。

+ +

次のレッスンでは、ドキュメントの書字モードがCSSとどのように相互作用するかを説明します。テキストが左から右以外の方向に流れる場合に何が起こるのでしょうか?

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/cascade_and_inheritance/index.html b/files/ja/learn/css/building_blocks/cascade_and_inheritance/index.html new file mode 100644 index 0000000000..a385a103b6 --- /dev/null +++ b/files/ja/learn/css/building_blocks/cascade_and_inheritance/index.html @@ -0,0 +1,339 @@ +--- +title: カスケードと継承 +slug: Learn/CSS/Building_blocks/Cascade_and_inheritance +tags: + - Beginner + - CSS + - Cascade + - Inheritance + - Learn + - rules + - source order + - specificity +translation_of: Learn/CSS/Building_blocks/Cascade_and_inheritance +--- +
{{LearnSidebar}}{{NextMenu("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks")}}
+ +

このレッスンでの目的は、CSS を HTML に適用する方法と競合した場合の解決方法について、もっとも基本的な概念(カスケード・詳細度・継承)の理解を深めていくことです。

+ +

このレッスンは他の記事よりも収穫が少なく座学っぽく感じるかもしれませんが、本記事の内容を理解しておくことで今後に役立ちます。このセクションを注意深く読み、次に進む前に概念をよく理解することをお勧めします。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:カスケードと詳細度、および CSS の継承の仕組みについて学ぶ。
+ +

競合するルール

+ +

CSS は Cascading Style Sheets の略で、最初の単語であるカスケード (cascading) を理解することは非常に重要です。カスケードのふるまいは、CSS を理解するための鍵となりえます。

+ +

プロジェクトに取り組んでいるとき、要素に適用されているはずの CSS が機能していないと感じることがあります。それは大抵の場合、同じ要素に適用される可能性のある 2 つ のルールを作ってしまったことに由来します。カスケードおよび、それと密接に関連する詳細度の概念は、そのような競合が存在する際のメカニズムです。実際に要素をスタイリングしているルールがどれなのかは期待と異なる場合があるため、このメカニズムを理解しておく必要があります。

+ +

このほかに重要なのは継承という概念です。一部の CSS プロパティは親要素の値をデフォルトで継承し、一方で継承しないものもあります。これにより、予期しない動作が発生する可能性もあります。

+ +

まず重要なものを簡単に見てみましょう。それぞれ順に追っていって CSS でどのように相互作用するかを見ていきます。これらはトリッキーな概念のように見えるかもしれませんが、CSSを書く練習を積んでいくと、その動作は明らかになってくるでしょう。

+ +

カスケード

+ +

スタイルシートのカスケードついて、とてもシンプルに考えるなら CSS ルールの順序が重要であることを意味します。等しい詳細度を持つ 2 つ のルールが適用される場合、CSS の最後に来るものが使用されます。

+ +

以下の例では、 h1 に対して 2 つ のルールがあります。この h1 は最終的に青色になります。これらのルールは個別のセレクターを持つため同じ詳細度であるので、ソースで最後にきている方が採用されています。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/cascade-simple.html", '100%', 400)}}

+ +

詳細度

+ +

詳細度とは、複数のルールに異なるセレクターがある場合にブラウザーがどのルールを適用するかを決定する方法ですが、同じ要素に適用することもできます。基本的に、セレクターの選択がどの程度具体的になるかの尺度です。

+ + + +

例を見てみましょう。以下に h1 に適用できる 2 つ のルールを再度示します。この h1 は最終的には赤色になります。クラスセレクターはルールにより高い詳細度を与えるため、要素セレクターを使用したルールがソースの順序でさらに下の方にあっても適用されます。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-simple.html", '100%', 500)}}

+ +

詳細度スコアリングなどについては、あとで説明します。

+ +

継承

+ +

ここでは継承についても理解する必要があります。親要素に設定された CSS プロパティ値には、子要素に継承されるものとそうでないものがあります。

+ +

例えば、要素に color と font-family を設定すると、異なる色とフォントの値を直接適用しない限り、その中のすべての要素もその色とフォントでスタイルされます。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance-simple.html", '100%', 550)}}

+ +

いくつかのプロパティは継承されません。例えば、要素に {{cssxref("width")}} 50% と設定した場合、すべての子孫要素は親の幅の 50% の幅を取得しません。もしそんなことになるのら CSS を使うととてもイライラするでしょう。

+ +
+

: MDN の CSS プロパティリファレンスページには、仕様書セクションの下部に技術情報ボックスがあるのが通例です。このボックスには、そのプロパティに関する多数のデータポイント(継承されているかどうかなど)が一覧表示されます。例として color プロパティの仕様書セクション を参照してください。

+
+ +

これらの概念がどう連携するか理解する

+ +

これら 3 つ の概念は、どの CSS をどの要素に適用するかを一緒に制御します。以下のセクションでは、それらがどのように連携するかを見ていきます。少し複雑に見えることもありますが、CSS を使いこなせば覚えやすくなり、忘れた場合はいつでも調べることができます。経験豊富な開発者でさえ、すべてを詳しく覚えているわけではありません。

+ +

継承を理解する

+ +

継承から始めます。次の例では {{HTMLElement("ul")}} があり、内部にさらに 2 つ のレベルの順序なしリストがネストされています。外側の <ul> に境界線、パディング、および文字色が指定されています。

+ +

文字色については直接の子だけでなく、間接の子にも適用されています。つまり直接の子である <li> 、それに最初のネストされたリスト内のものにも適用されています。そして 2番目 にネストされたリストに special クラスを追加し、別の色が適用されています。これは子に継承します。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance.html", '100%', 700)}}

+ +

幅(上述したとおり)、マージン、パディング、境界線などは継承されません。境界線がリストの子に継承される場合、すべてのリストとリストアイテムは境界線を表示してしまいます。おそらく、それは欲しい効果ではないはずです。

+ +

デフォルトで継承されるプロパティとそうでないものは、主に常識に基づいているのです。

+ +

継承の制御

+ +

CSS は、継承を制御するための 4 つ の特別なユニバーサルプロパティ値 (universal property values) を提供します。すべての CSS プロパティはこれらの値を受け入れます。

+ +
+
{{cssxref("inherit")}}
+
選択した要素に適用されるプロパティ値を、その親要素と同じものに設定します。これは「継承を有効にする」ことを意味します。
+
{{cssxref("initial")}}
+
選択された要素に適用されるプロパティ値を、ブラウザーのデフォルトスタイルシートでその要素に設定されているものと同じ値に設定します。ブラウザーのデフォルトのスタイルシートで値が設定されておらず、かつ、そのプロパティが自然に継承される場合は inherit が代わりにプロパティ値として設定されます。
+
{{cssxref("unset")}}
+
プロパティを自然な値にリセットします。つまり、プロパティが自然に継承される場合は inherit のように動作し、そうでない場合は initial のように動作します。
+
+ +
+

: 新しい値で {{cssxref("revert")}} もありますが、これはブラウザーのサポートが制限されます。

+
+ +
+

: それらの動作の詳細については CSS カスケード入門CSS 宣言のオリジンを参照してください。

+
+ +

リンクのリストを見て、ユニバーサル値 (universal values) がどのように機能するかを調べることができます。以下のライブサンプルでは、CSS に変更を加えて何が起こるかを確認できます。HTML と CSS を理解するには、実際にコードを試すのが最善の方法です。

+ +

以下を試してみてください。

+ +
    +
  1. 2番目 のリストアイテムには、my-class-1 が適用されています。これは、内部にネストされた <a> 要素に色を継承します。ルールを削除すると、リンクの色はどのように変わるでしょうか?
  2. +
  3. なぜ 3番目 と 4番目 のリンクがその色であるのか理解できていますか?そうでない場合は、上述しているそれぞれの値の説明を確認してください。
  4. +
  5. 例えば a { color: red; } というように <a> 要素に新しい色を定義すると、どのリンクの色が変わるでしょうか?
  6. +
+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/keywords.html", '100%', 700)}}

+ +

すべてのプロパティ値のリセット

+ +

CSS の一括指定プロパティ all を使用して、これらの継承値の 1 つ を(ほぼ)すべてのプロパティに一度に適用できます。その値として、いずれかの継承値 (inheritinitialunset、または revert) を指定できます。新しく変更を開始する際、既知の開始点に戻ることができるように、変更されたスタイルを元に戻す便利な方法です。

+ +

以下の例では 2 つ のブロック引用要素 (blockquote) があります。最初のスタイルは blockquote 要素自体に適用され、2 つ目には all に unset をセットするようにblockquote に適用されるクラスがあります。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/all.html", '100%', 700)}}

+ +

all の値を他の有効な値に設定してみて、違いを観察してみてください。

+ +

カスケードを理解する

+ +

HTML 構造に深くネストされた段落が body の CSS と同じ色である理由がわかりました。また導入レッスンではドキュメントの任意の時点で CSS を変更する方法がわかりました(CSS を要素自体に割り当てたり、クラスを作成したり)。そしてここからは、スタイルを設定できるものが複数ある場合に、カスケードがどのようにして CSS ルールを適用していくかを見ていきます。

+ +

考慮すべき 3 つ の要因がありますが、ここでは重要度の高い順にリストしています。前にあるものは、後のものを無効にします。

+ +
    +
  1. 重要性 (Importance)
  2. +
  3. 詳細度 (Specificity)
  4. +
  5. ソースオーダー (Source order)
  6. +
+ +

これらを下から順に、ブラウザーがどうやって CSS を適用しているのかを見ていきましょう。

+ +

ソースオーダー

+ +

カスケードにおいてソースオーダーがどう重要であるかは、すでに見てきました。重みがまったく同じであるルールが複数ある場合、CSS の最後にあるルールが優先されるというものです。後にあるものが前のものに勝ち、要素のスタイルを上書きしていく規則のようなものと考えることができます。

+ +

詳細度

+ +

ソースオーダーが重要であるということがわかりました。ある時には、より後ろにあるルールが適用されるはずなのに、競合関係にある前方のものの方が適用されるという状況に出会います。それは前方にあるルールの方がより高い詳細度を持っているためです。より具体的であり、要素をスタイリングするべきものとしてブラウザーによって選択されたのです。

+ +

このレッスンで前述したように、クラスセレクターは要素セレクターよりも重みがあるため、クラスで定義されたプロパティは、要素指定されたプロパティをオーバーライドします。

+ +

ここで特筆すべきは、セレクターとそれによって適用されるルールについて注目しているのですが、上書きされるのはルール全体ではなく同じプロパティのみであるということです。

+ +

この振る舞いは CSS での反復を避けるのに役立ちます。一般的な方法としては、要素に基本スタイルを定義したあと、違いがでるようにクラスを作成することです。例えば、次のスタイルシートではレベル 2 見出し (h2) の基本スタイルを定義し、プロパティと値の一部のみを変更するクラスを作成しました。最初に定義された値はすべての見出しに適用され、その後、より具体的な値がクラスありのものに適用されます。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/mixing-rules.html", '100%', 700)}}

+ +

ブラウザーが詳細度を計算する方法を見てみましょう。要素セレクターの詳細度は低く、クラスで上書きできることはすでにわかったはずです。基本的に、セレクターの重みはポイント単位の値で与えられ、これらを合計して特定セレクターの重みが与えられて、他の一致するものと相対して評価することができます。

+ +

セレクターが持つ詳細度の量は、4 つ の異なる値(またはコンポーネント)を使用して測定されます。これは、1,000、100、10、1 のそれぞれの位として考えることができます。

+ +
    +
  1. 「1,000」 宣言が {{htmlattrxref("style")}} 属性(別名、インラインスタイル)内にある場合、これがスコアされます。このような宣言にはセレクターがないため、その詳細度は常にシンプルに 1,000 です。
  2. +
  3. 「100」 全体のセレクターの内部にある ID セレクターは、これがスコアされます。
  4. +
  5. 「10」 全体のセレクターの内部にあるクラスセレクター・属性セレクター・擬似クラスは、これがスコアされます。
  6. +
  7. 「1」 全体のセレクターの内部にある要素セレクターまたは疑似要素には、これがスコアされます。
  8. +
+ +
+

: ユニバーサルセレクタ (*)、コンビネータ (+>~、' ') 、及び否定擬似クラス(:not)は詳細度に影響を及ぼしません。

+
+ +

次の表でわかりやすいいくつかの例を示します。これらを試してみて、なぜ詳細度が与えられるのかをしっかり理解してください。セレクターについてはまだ詳しく説明していませんが、MDN の CSS セレクターで詳細を参照することができます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクター1,000100101詳細度の合計
h100010001
h1 + p::first-letter00030003
li > a[href*="en-US"] > .inline-warning00220022
#identifier01000100
セレクターなし、要素の {{htmlattrxref("style")}} 属性にルールがある。10001000
+ +

先に進む前に、実例を見てみましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-boxes.html", '100%', 700)}}

+ +

何が起こっているのでしょうか?まず、この例の最初の 7 つ のルールにのみ関心があり、お気づきのように、各ルールの前に詳細度の値をコメントしてあります。

+ + + +
+

: これは理解しやすくするためのざっくりとした一例に過ぎません。実際には、セレクタータイプごとにはそれぞれレベルの詳細度があり、より低い詳細度レベルのセレクターによって上書きすることはできません。例えば 100万 のクラスセレクターを組み合わせても、1 つ の ID セレクターのルールを上書きすることはできません

+ +

詳細度を評価するためのより正確な方法は、詳細度を高レベルから開始し必要に応じて低レベルにしていくことです。高い方の詳細度のセレクタースコアが同点の場合にのみ、低レベルを評価することになります。同点でない場合、より高い詳細度レベルを上書きできないため、より低い詳細度レベルのセレクターを無視できます。

+
+ +

!important

+ +

ここまで見てきた計算を無効にする特別な CSS があります。使用には十分注意してください !importantというものです。これは特定のプロパティと値を最も重要であると指定するもので、カスケードの通常のルールを上書きします。

+ +

例を見てみましょう。2 つの段落があり、そのうちの 1 つ には ID がついています。

+ +

{{EmbedGHLiveSample("css-examples/learn/cascade/important.html", '100%', 700)}}

+ +

何が起きているのかを見てみましょう。理解しにくい場合は、いくつかのプロパティを削除しながら、どうなるか見てみてください。

+ +
    +
  1. 3番目のルールでは {{cssxref("color")}} と {{cssxref("padding")}} が適用されていますが、{{cssxref("background-color")}} は適用されていないことようですなぜでしょうか?ソースオーダーの後の方は、普通は前の方のルールをオーバーライドするため、その観点では 3 つ すべてが適用されるはずです。
  2. +
  3. とはいえ、クラスセレクターは要素セレクターよりも詳細度が高いため前者のルールが優先されます
  4. +
  5. 両方の要素には better という {{htmlattrxref("class")}} ありますが、2番目 の要素には winning という {{htmlattrxref("id")}} もあります。ID はクラスよりもより高い詳細度があるため(ページ上では ID を持つ要素は一意に 1 つ しか置けないのに対し、同じクラスを持つ多くの要素がありえるため、ID セレクターの方が非常に限定的になります)、2番目の要素には赤い背景色と 1 ピクセルの黒い境界線が適用され、最初の要素についてはクラスで指定されたように灰色の背景色となり、境界線は消えます。
  6. +
  7. 2番目 の要素は赤い背景が適用されていますが、あるはずの境界線はありませんなぜでしょうか? 2番目 のルールでは border: none のあとに !important と宣言されており、高い詳細度であるはずの ID よりも重要なものとして扱われているためです。
  8. +
+ +
+

: この !important 宣言をオーバーライドする唯一の方法は、ソースオーダーの後半で同じ詳細度を持つように !important 宣言するか、またはより高い詳細度を持つ宣言に含めることです。

+
+ +

!important を知っていると便利です。他人のコードでも見かけることがあるからです。ただし絶対に必要な場合を除きあまり使用しないことを強くお勧めします。 !important はカスケードの普通の挙動とは異なってしまうため、特に大きなスタイルシートで CSS に関わるデバッグが非常に困難になるためです。

+ +

使用しなければならない状況の 1 つ としては、コアにある CSS モジュールを編集できない CMS で作業している等で、他の方法では難しい場合にスタイルを実際にオーバーライドしたい場合等があります。でも本当に、回避できる場合は使用しないでください。

+ +

CSS ロケーションの効果

+ +

最後に、CSS 宣言の重要性は指定されたスタイルシートに依存することにも注意してください。ユーザーは、カスタムスタイルシートを設定して、開発者のスタイルをオーバーライドできます。例えば、視覚障害を持っているユーザーが閲覧するすべてのウェブページのフォントサイズを通常の 2倍 に設定して読みやすくするといったこともあります。

+ +

要約

+ +

競合する宣言は次の順序で適用され、後の方がそれより前のものを上書きします。

+ +
    +
  1. ユーザーエージェントのスタイルシートの宣言。例えば、他のスタイルが設定されていない場合に使用されるブラウザー標準のスタイルなど。
  2. +
  3. ユーザースタイルシートの通常の宣言 (ユーザーが設定したカスタムスタイル)
  4. +
  5. 作者のスタイルシートでの通常の宣言 (私たちウェブ開発者によって設定されたスタイルのことです)
  6. +
  7. 作者のスタイルシートの重要 (important) な宣言
  8. +
  9. ユーザーのスタイルシートの重要 (important) な宣言
  10. +
+ +

ウェブ開発者のスタイルシートがユーザーそれを上書きするのは理にかなっているので設計を意図どおりに保つことができますが、前述したとおり、ユーザーがウェブ開発者スタイルをオーバーライドする正当な理由がある場合もあります。それは !important ルールを使用することで実現できます。

+ +

スキルをテストしよう!

+ +

この記事で多くを網羅しましたが、最も重要な情報を覚えていますか?次に移る前に、この情報を保持しているかを検証するテストがあります — Test your skills: the Cascadeを見てください。

+ +

次のステップ

+ +

この記事の大部分を理解したのなら、よいでしょう。CSS の基本的な仕組みに慣れてきたということです。次に、セレクターについて詳しく見ていきます。

+ +

カスケード・詳細度・継承を完全に理解していなくても心配する必要はありません。このコースでこれまで取り上げてきたなかで、間違いなく最も複雑なことであり、プロのウェブ開発者でさえもたまに扱いにくく感じるものです。このコースを続行していくなかで、この記事にときどき戻り、それについて考え続けることをお勧めします。

+ +

スタイルが期待どおりに適用されないという奇妙な問題に出くわした場合は、この記事を参照してください。詳細度の問題である可能性があります。

+ +

{{NextMenu("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/debugging_css/index.html b/files/ja/learn/css/building_blocks/debugging_css/index.html new file mode 100644 index 0000000000..77abbd982c --- /dev/null +++ b/files/ja/learn/css/building_blocks/debugging_css/index.html @@ -0,0 +1,206 @@ +--- +title: CSS のデバッグ +slug: Learn/CSS/Building_blocks/Debugging_CSS +tags: + - Beginner + - CSS + - DOM + - Debugging + - DevTools + - Learn + - source +translation_of: Learn/CSS/Building_blocks/Debugging_CSS +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks/Organizing", "Learn/CSS/Building_blocks")}}
+ +

CSS を書くとき、期待どおりに動作していないように見える問題が発生する場合があります。セレクターは合っているはずなのに何も起こらなかったり、ボックスのサイズが期待したどおりにならなかったりなどです。この記事では CSS の問題をデバッグする方法について案内し、何が起こっているかを調べるのに各モダンブラウザーのデベロッパーツールはどう役立つかを示します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:ブラウザーの開発ツールの基本と、 CSS の簡単な検査と編集の方法を学ぶ。
+ +

ブラウザーの開発ツールの使い方

+ +

ブラウザー開発者ツールとは」という記事は、さまざまなブラウザーやプラットフォームでツールにアクセスする方法を説明する最新のガイドです。ほとんどの場合、特定のブラウザで開発することを選択し、そのブラウザに含まれるツールに最も慣れ親しむことになるかもしれませんが、他のブラウザでのアクセス方法を知っておく価値はあります。これは、複数のブラウザ間で異なるレンダリングが表示されている場合に役立ちます。

+ +

また、DevToolsを作成するときに、ブラウザーがさまざまな領域に焦点を合わせていることもわかります。例えば、Firefoxには、CSSレイアウトを視覚的に操作するための優れたツールがいくつかあり、グリッドレイアウトフレックスボックス、およびシェイプを検査および編集できます。ただし、ページ上の要素に適用されているプロパティや値を検査したり、エディタから変更を加えたりするためのツールなど、基本的なツールはすべての異なるブラウザに共通しています。

+ +

このレッスンでは、CSSを操作するためのFirefox DevToolsの便利な機能をいくつか見ていきます。そのために、サンプルファイルを使用します。続けたい場合は、新しいタブでこれを読み込み、上のリンク先の記事で説明したようにDevToolsを開きます。

+ +

DOM とソース表示の違い

+ +

DevTools を初めて使用する人が困るのは、Web ページのソースを表示したとき、またはサーバーに配置した HTML ファイルを見たときに表示されるものと、DevTools の HTML ペインに表示されるものが異なることです。「ソースの表示」で表示されるものとほぼ同じように見えますが、いくつかの違いがあります。

+ +

レンダリングされた DOM では、ブラウザはあなたのために書き方の悪い HTML を修正しているかもしれません。例えば <h2> を開いて <h3> で閉じるといったように、要素を誤って閉じてしまった場合、ブラウザはあなたが何をしようとしていたのかを理解し、DOM の HTML は開いていた <h2> を正しく <h2> で閉じるようになります。ブラウザはすべての HTML を正規化し、DOM は JavaScript によって行われた変更も表示します。

+ +

これと比較して、ソースの表示は、サーバーに保存されている HTML ソース コードにすぎません。DevTools の HTML ツリーには、ブラウザが任意の時点でレンダリングしている内容が正確に表示されるため、実際に何が起こっているのかを知ることができます。

+ +

適用された CSS の調査

+ +

ページ上の要素を選択するには、右クリックまたは Ctrl キーを押しながらクリックして [検査] を選択するか、または DevTools ディスプレイの左側にある HTML ツリーから選択します。box1 のクラスを持つ要素を選択してみてください。これは、ページ上の最初の要素で、周囲に枠線で囲まれたボックスが描かれています。

+ +

DevToolsを開いたこのチュートリアルのサンプルページ。

+ +

HTMLの右側にあるルールビューを見ると、その要素に適用されているCSSのプロパティと値を見ることができるはずです。box1 クラスに直接適用されているルールと、box の先祖から継承されている CSS、この場合は <body> に適用されている CSS が表示されています。これは、予想していなかったCSSが適用されている場合に便利です。おそらくそれは親要素から継承されているもので、この要素のコンテキストでそれを上書きするルールを追加する必要があるでしょう。

+ +

また、速記プロパティを展開する機能も便利です。この例では、margin の短縮形を使用しています。

+ +

小さな矢印をクリックしてビューを展開すると、さまざまなロングハンドプロパティとその値が表示されます。

+ +

パネルがアクティブになっているときは、ルールビューの値のオンオフを切り替えることができます。マウスをかざすとチェックボックスが表示されます。border-radius などのルールのチェックボックスのチェックを外すと、CSS は適用されなくなります。

+ +

これを使って A / B 比較を行い、ルールを適用した方が良く見えるかどうかを判断したり、デバッグの手助けをしたりすることができます。例えば、レイアウトがおかしくなり、どのプロパティが問題の原因になっているのかを調べたい場合などです。

+ +

値の変更

+ +

プロパティのオン/オフに加えて、それらの値を編集できます。おそらく、別の色の方が見栄えが良いかどうかを確認したい、または何かのサイズを微調整したいですか。 DevToolsを使用すると、スタイルシートを編集してページを再ロードする時間を大幅に節約できます。

+ +

box1 を選択した状態で、境界線に適用された色を示すスウォッチ (小さな色付きの円) をクリックします。カラーピッカーが開き、いくつかの異なる色を試すことができます。同様の方法で、ボーダーの幅やスタイルを変更することができます。

+ +

カラーピッカーを開いたDevToolsスタイルパネル。

+ +

新しいプロパティの追加

+ +

DevToolsを使ってプロパティを追加することができます。おそらく、<body> 要素のフォント サイズを継承せず、ボックスに独自のサイズを設定したいことに気がついたのではないでしょうか?これは、CSS ファイルに追加する前に DevTools で試すことができます。

+ +

ルールの閉じ中括弧をクリックすると、ルールへの新しい宣言の入力が開始され、その時点で新しいプロパティの入力を開始することができます。font-size を選択したら、試したい値を入力します。また、[+] ボタンをクリックして同じセレクタで追加ルールを追加し、そこに新しいルールを追加することもできます。

+ +

DevToolsパネル、新しいプロパティをルールに追加し、フォントのオートコンプリートを開く

+ +
+

:ルールビューには他にも便利な機能があります。たとえば、無効な値の宣言には取り消し線が引かれています。詳しくは、CSSの確認と編集をご覧ください。

+
+ +

ボックスモデルについて

+ +

前のレッスンでは、ボックスモデルについて説明しまし。また、指定したサイズに基づいて要素のサイズの計算方法を変更する代替のボックスモデルと、パディングおよび境界線があることを説明しました。DevToolsは、要素のサイズの計算方法を理解するのに役立ちます。

+ +

レイアウトビューでは、選択した要素上のボックス・モデルのダイアグラムと、要素のレイアウト方法を変更するプロパティと値の説明が表示されます。これには、要素で明示的に使用していないが初期値が設定されているプロパティの説明も含まれます。

+ +

このパネルでは、詳細なプロパティの 1 つに box-sizing プロパティがあり、これは要素が使用するボックスモデルを制御します。

+ +

box1box2 のクラスを持つ 2 つのボックスを比較してみましょう。どちらも同じ幅 (400px) が適用されていますが、box1 の方が視覚的には広くなっています。レイアウトパネルを見ると、content-box を使用していることがわかります。これは、要素に与えたサイズを受け取り、パディングとボーダーの幅を追加する値です。

+ +

box2 のクラスを持つ要素は border-box を使用しているので、ここでは要素に与えたサイズからパディングとボーダーが差し引かれています。つまり、ページ上でボックスが占めるスペースは、あなたが指定したサイズ(この例では width: 400px)と同じになります。

+ +

DevToolsのレイアウトセクション

+ +
+

:詳細については、ボックスモデルの調査と検査をご覧ください。

+
+ +

詳細度に関する問題の解決

+ +

開発中に、特に既存のサイトのCSSを編集する必要があるときに、いくつかのCSSを適用させるのに苦労することがあります。何をしても要素がCSSを適用してくれないのです。このような場合、一般的には、より具体的なセレクタが変更を上書きしていることが考えられますが、ここではDevToolsを使用することで解決することができます。

+ +

この例のファイルでは、<em> 要素に包まれた2つの単語があります。1つはオレンジ色で、もう1つはホットピンク色で表示されています。CSSでは、以下のようにしています。

+ +
em {
+  color: hotpink;
+  font-weight: bold;
+}
+ +

しかし、スタイルシートの上には .special セレクタ―を持つルールがあります。

+ +
.special {
+  color: orange;
+}
+ +

カスケードと継承のレッスンで特異性について説明したことを思い出していただけると思いますが、クラス セレクタは要素セレクタよりも特異性が高いため、この値が適用されます。特に情報が巨大なスタイルシートのどこかに埋もれている場合は、DevToolsを使用することで、このような問題を見つけることができます。

+ +

.special のクラスを持つ <em> を検査すると、DevToolsがオレンジ色が適用されていることを示し、また、emに適用されている color プロパティが取り消されていることを示しています。これで、クラスが要素セレクタをオーバーライドしていることがわかります。

+ +

emを選択し、DevToolsを見て、何が色を上書きしているかを確認します。

+ +

Firefoxの開発ツールについて

+ +

MDNには、Firefox DevToolsに関する多くの情報があります。DevToolsのメインセクションをご覧くださいこのレッスンで簡単に説明した内容の詳細については、ハウツーガイドをご覧ください。

+ +

CSS 不具合のデバッグ

+ +

CSSの問題を解決する場合、DevToolsは非常に役立ちます。CSSが期待どおりに動作しない状況に陥った場合、どのように解決すればよいでしょうか。次の手順が役立ちます。

+ +

問題から一歩離れてみる

+ +

コーディングの問題はどんなものでもイライラすることがありますが、特に CSS の問題は、解決策を見つけるのに役立つようなエラーメッセージをオンラインで検索しても出てこないことが多いので、イライラします。イライラしてきたら、しばらく問題から離れてみましょう。散歩に行ったり、飲み物を飲んだり、同僚とおしゃべりしたり、しばらく他のことに取り組んでみましょう。問題を考えるのをやめれば、魔法のように解決策が現れることもありますし、そうでなくても、スッキリした気分の時に取り組むと、ずっと楽になります。

+ +

HTML と CSS が正しく記述されていますか?

+ +

ブラウザーはCSSとHTMLが正しく記述されていることを期待しますが、ブラウザーは非常に寛容であり、マークアップまたはスタイルシートにエラーがある場合でも、最善を尽くしてWebページを表示します。コードに誤りがある場合、ブラウザはあなたが何を意味するのかを推測する必要があり、それはあなたが考えていたものとは異なる決定をするかもしれません。さらに、2つの異なるブラウザーが2つの異なる方法で問題に対処する場合があります。したがって、適切な最初のステップは、HTMLおよびCSSをバリデーターで実行し、エラーを見つけて修正することです。

+ + + +

プロパティと値は対象ブラウザーでサポートされていますか?

+ +

ブラウザは、理解できないCSSを単に無視します。使用しているプロパティまたは値が、テストしているブラウザーでサポートされていない場合、何も壊れませんが、そのCSSは適用されません。DevToolsは一般的に、サポートされていないプロパティと値を何らかの方法で強調表示します。下のスクリーンショットでは、ブラウザは {{cssxref("grid-template-columns")}} のサブグリッド値をサポートしていません。

+ +

grid-template-columns:サブグリッド値がサポートされていないため、サブグリッドに線を引いたブラウザDevToolsの画像。

+ +

また、MDNの各プロパティページの下部にあるブラウザの互換性の表を見ることもできます。これらの表は、そのプロパティのブラウザのサポート状況を示しており、そのプロパティの一部の使用法がサポートされていて、他の使用法がサポートされていない場合は分類されていることが多いです。以下の表は {{cssxref("shape-outside")}} プロパティの互換性データを示しています。

+ +

{{compat("css.shape-outside")}}

+ +

どこかで CSS が上書きされていませんか?

+ +

ここで、特異性について学んだ情報が非常に役に立つでしょう。自分が行おうとしていることをより具体的にオーバーライドしているものがある場合、何が何だかわからないという非常にイライラするゲームに突入してしまうことがあります。しかし、上記のように、DevTools を使用すると、どのような CSS が適用されているかが表示されるので、新しいセレクタをオーバーライドするのに十分なほど具体的なものにする方法を見つけることができます。

+ +

問題の縮小テストケースを作成する

+ +

上記の手順で問題が解決されない場合は、もう少し調査する必要があります。この時点での最善の方法は、縮小テストケースとして知られているものを作成することです。問題を減らす」ことができるということは、非常に有用なスキルです。自分のコードや同僚のコードの問題を見つけるのに役立ちますし、バグを報告したり、より効果的に助けを求めたりすることができるようになります。

+ +

縮小テストケースとは、関連のない周囲のコンテンツやスタイリングを削除して、可能な限りシンプルな方法で問題を示すコード例のことです。これは、問題のあるコードをレイアウトから取り出して、そのコードや機能だけを示す小さな例を作ることを意味することが多いでしょう。

+ +

縮小されたテストケースを作成するには:

+ +
    +
  1. マークアップが動的に生成される場合—例えば、CMSを介して—問題を示す出力の静的バージョンを作成します。CodePenなどのコード共有サイトは、オンラインでアクセスでき、同僚と簡単に共有できるため、テストケースを減らすのに役立ちます。まず、ページで[ソースの表示]を実行し、HTMLをCodePenにコピーしてから、関連するCSSとJavaScriptを取得して、それも含めます。その後、問題がまだ明らかかどうかを確認できます。
  2. +
  3. JavaScriptを削除しても問題が解決しない場合は、JavaScriptを含めないでください。JavaScriptを削除ても問題が解決しない場合は、できるだけ多くのJavaScriptを削除して、問題の原因はすべて残してください。
  4. +
  5. 問題の原因となっていないHTMLを削除します。コンポーネントまたはレイアウトの主要な要素を削除します。繰り返しになりますが、まだ問題を示している最小限のコードになるようにしてください。
  6. +
  7. 問題に影響を与えないCSSをすべて削除します。
  8. +
+ +

その過程で、何が問題を引き起こしているのかを発見したり、特定の何かを取り除くことで、 少なくとも問題のオン/オフを切り替えることができるようになるかもしれません。あなたが物事を発見したときに、あなたのコードにいくつかのコメントを追加する価値はあります。助けを求める必要がある場合は、それがあなたがすでに試したものを助けてくれる人に伝えてくれます。これにより、考えられる問題や回避策を検索するのに十分な情報が得られる場合があります。

+ +

問題を解決するのにまだ苦労している場合は、テストケースを減らすことで、フォーラムに投稿したり、同僚に見せたりして、助けを求めることができます。助けを求める前に、問題を軽減し、どこで問題が発生しているかを正確に特定する作業を行ったことを示すことができれば、助けを得る可能性が高くなります。経験豊富な開発者であれば、問題を迅速に発見して正しい方向に導くことができるかもしれませんが、そうでない場合でも、テストケースを縮小したことで、開発者はすばやく確認することができ、少なくとも何らかの助けを提供できるようになるでしょう。

+ +

問題が実際にブラウザーのバグである場合、テストケースの縮小を使用して、関連するブラウザーベンダーにバグレポートを提出することもできます(例:Mozillaのbugzillaサイト)。

+ +

CSS を使いこなせるようになると、問題を発見するのが早くなることに気づくでしょう。しかし、最も経験豊富な人でも、「一体何が起こっているのか」と疑問に思うことがあります。体系的なアプローチをとり、テストケースを減らし、他の人に問題を説明すると、通常、修正が見つかります。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks/Organizing", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/handling_different_text_directions/index.html b/files/ja/learn/css/building_blocks/handling_different_text_directions/index.html new file mode 100644 index 0000000000..d3a5c98298 --- /dev/null +++ b/files/ja/learn/css/building_blocks/handling_different_text_directions/index.html @@ -0,0 +1,153 @@ +--- +title: テキスト方向の操作 +slug: Learn/CSS/Building_blocks/Handling_different_text_directions +tags: + - Beginner + - CSS + - Learn + - logical properties + - writing modes +translation_of: Learn/CSS/Building_blocks/Handling_different_text_directions +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks")}}
+ +

CSSの学習でこれまでに遭遇したプロパティと値の多くは、画面の物理的な大きさに関係しています。たとえば、ボックスの上下左右にborderを作成します。これらの物理的大きさは、水平に表示されるコンテンツに非常にきちんとマッピングされ、デフォルトでは、ウェブは右から左への言語(アラビア語など)よりも左から右への言語(英語やフランス語など)をサポートする傾向があります。

+ +

しかし近年、CSSは、右から左へのコンテンツや上から下へのコンテンツ(日本語など)を含むコンテンツのさまざまな方向性をより適切にサポートするために進化しました。これらのさまざまな方向性は書き込みモードと呼ばれます。学習を進めてレイアウトの操作を開始すると、書き込みモードを理解することが非常に役立ちます。そのため、これらのモードを紹介します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:最新の CSS の "writing modes" の重要性を理解する。
+ +

書き込みモードとは?

+ +

CSSの書き込みモードは、テキストが水平方向または垂直方向のどちらで実行されているかを示します。{{cssxref("writing-mode")}} プロパティにより、ある書き込みモードから別の書き込みモードに切り替えることができます。これを行うために縦書きモードを使用する言語で作業する必要はありません。また、創造的な目的のためにレイアウトの一部の書き込みモードを変更することもできます。
+
+ 次の例では、writing-mode: vertical-rlを使用して見出しを表示しています。これで、テキストが垂直方向に実行されます。縦書きテキストはグラフィックデザインでは一般的であり、Webデザインにより興味深い外観を追加する方法になります。

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/simple-vertical.html", '100%', 800)}}

+ +

writing-mode プロパティの3つの可能な値は次のとおりです:

+ + + +

したがって、writing-modeプロパティは、実際には、ページにブロックレベルの要素が表示される方向(上から下、右から左、または左から右)を設定します。これにより、文章内のテキストの流れが決まります。

+ +

"writing modes" と ブロックレイアウトとインラインレイアウト

+ +

ブロックとインラインのレイアウト、およびいくつかの要素がブロック要素として表示され、他の要素がインライン要素として表示されるという事実についてはすでに説明しました。上で説明したように、ブロックとインラインは、物理的な画面ではなく、ドキュメントの書き込みモードに関連付けられています。英語などのテキストを水平方向に表示する書き込みモードを使用している場合、ブロックはページの上から下にのみ表示されます。

+ +

例を見れば、これはより明確になります。この次の例では、見出しと段落を含む2つのボックスがあります。 1つ目は、writing-mode: horizo​​ntal-tbを使用します。これは、水平にページの上部から下部に向かって書き込まれる書き込みモードです。 2番目はwriting-mode: vertical-rlを使用します;これは、垂直に右から左に書き込まれる書き込みモードです。

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/block-inline.html", '100%', 1200)}}

+ +

書き込みモードを切り替えると、ブロックの方向とインラインの方向が変更されます。 horizontal-tb書き込みモードでは、ブロックの方向は上から下に向かっています。 vertical-rl書き込みモードでは、ブロックの方向は右から左に水平に実行されます。したがって、block dimension は常に、使用中の書き込みモードでページにブロックが表示される方向です。 inline dimensionは、常に文が流れる方向です。

+ +

この図は、横書きモードでの2つのdimensionsを示しています。Showing the block and inline axis for a horizontal writing mode.

+ +

この図は、縦書きモードの2つのdimensionsを示しています。

+ +

Showing the block and inline axis for a vertical writing mode.

+ +

CSSレイアウト、特に新しいレイアウトメソッドを検討し始めると、このブロックとインラインの考え方が非常に重要になります。後で再検討します。

+ +

方向

+ +

書き込みモードに加えて、テキストの方向もあります。上記のように、アラビア語などの一部の言語は水平に書かれていますが、右から左に書かれています。これは、創造的な意味で使用する可能性のあるものではありません。単に右側に何かを並べたい場合は、他の方法もありますが、CSSの性質の一部としてこれを理解することが重要です。 Webは、左から右に表示される言語専用ではありません!
+
+ 書き込みモードとテキストの方向が変更される可能性があるため、新しいCSSレイアウトメソッドは、左右、上下を参照しません。代わりに、インラインとブロックのこのアイデアとともに、開始と終了について話します。心配する必要はありませんが、レイアウトを見始めるときにはこれらのアイデアに留意してください。 CSSを理解する上で非常に役立ちます。

+ +

論理プロパティと値

+ +

ただし、学習のこの時点で書き込みモードと方向を記述することについて説明する理由は、私たちはすでに、画面の物理的な大きさに関連付けられた多くのプロパティを見ており、横書きモードのときに最も意味があるという事実のためです

+ +

2つのボックスをもう一度見てみましょう。1つは horizontal-tb の書き込みモード、もう1つは vertical-rlです。これらの両方のボックスに {{cssxref("width")}} を指定しました。ボックスが縦書きモードでも width があるため、テキストがオーバーフローすることがわかります。

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/width.html", '100%', 1200)}}

+ +

このシナリオで本当に必要なのは、書き込みモードに合わせて基本的にheightとwidthを入れ替えることです。縦書きモードのときは、横書きモードの場合と同じように、ボックスをブロックのディメンションで拡大したいです。
+
+ これを簡単にするために、CSSは最近マッピングされたプロパティのセットを開発しました。これらは本質的に、物理的なプロパティ(widthheight など)を論理的な、またはフローに関連するバージョンに置き換えます。
+
+ 横書きモードでwidthにマップされるプロパティは{{cssxref("inline-size")}} と呼ばれます。これはインラインディメンションのサイズを参照します。heightのプロパティの名前は{{cssxref("block-size")}} で、ブロックディメンションのサイズです。widthinline-sizeに置き換えた以下の例で、これがどのように機能するかを見ることができます。

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/inline-size.html", '100%', 1200)}}

+ +

論理マージン、ボーダー、パディングのプロパティ

+ +

最後の2つのレッスンでは、CSSのボックスモデルとCSSのボーダーについて学びました。マージン、ボーダー、およびパディングのプロパティには{{cssxref("margin-top")}}, {{cssxref("padding-left")}}, および {{cssxref("border-bottom")}} があります。widthとheightのマッピングと同じ方法で、これらのプロパティのマッピングがあります。
+
+ margin-topプロパティは{{cssxref("margin-block-start")}}にマップされます—これは常にブロックディメンションの先頭のマージンを参照します。
+
+  {{cssxref("padding-left")}}プロパティは、インライン方向の開始に適用されるパディングである{{cssxref("padding-inline-start")}}にマップされます。これは、その書き込みモードで文章が始まる場所です。 {{cssxref("border-bottom")}} プロパティは、{{cssxref("border-block-end")}}にマップされます。これは、ブロックディメンションの最後のボーダーです。
+
+ 以下の物理的特性と論理的特性の比較を見ることができます。
+
+ .boxwriting-modeプロパティをvertical-rlに切り替えてボックスの書き込みモードを変更すると、物理プロパティが物理方向にどのように関連付けられているかがわかりますが、論理プロパティは書き込みモードで切り替わります。
+
+ また、 {{htmlelement("h2")}} には黒い border-bottomがあることがわかります。両方のライティングモードで、下の境界線が常にテキストの下に来るようにする方法を見つけられますか?

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/logical-mbp.html", '100%', 1200)}}

+ +

個々のボーダーロングハンドをすべて考慮すると、膨大な数のプロパティがあり、論理プロパティと値のMDNページですべてのマッピングプロパティを確認できます。

+ +

論理値

+ +

これまで、論理プロパティ名について見てきました。また、toprightbottom, および leftの物理値をとるプロパティもあります。これらの値には、論理値(block-startinline-endblock-end, および inline-start)へのマッピングもあります。
+
+ たとえば、画像を左にフロートさせて、画像の周りにテキストを折り返すことができます。以下の例に示すように、leftinline-startに置き換えることができます。
+
+ この例の書き込みモードをvertical-rlに変更して、画像がどうなるかを確認します。 inline-startinline-endに変更して、フロートを変更します。

+ +

{{EmbedGHLiveSample("css-examples/learn/writing-modes/float.html", '100%', 1200)}}

+ +

ここでは、書き込みモードが何であってもマージンが正しい場所にあることを保証するために、論理マージン値も使用しています。

+ +

物理的または論理的なプロパティを使うべきか?

+ +

論理的なプロパティと値は、物理的に同等のものよりも新しいため、ブラウザにはごく最近実装されました。 MDNの任意のプロパティページをチェックして、ブラウザーサポートがどの程度前にサポートしているかを確認できます。複数の書き込みモードを使用していない場合は、現時点では物理バージョンを使用することをお勧めします。ただし、フレックスボックスやグリッドなどのレイアウトメソッドの処理を開始すると、多くの人が理にかなっているため、最終的にはほとんどの場合、人々は論理バージョンに移行することを期待しています。

+ +

まとめ

+ +

このレッスンで説明する概念は、CSSでますます重要になっています。ブロックとインラインの方向、および書き込みモードの変更に伴うテキストフローの変化を理解することは、今後非常に役立ちます。水平モード以外の書き込みモードを使用しない場合でも、CSSを理解するのに役立ちます。
+
+ 次のモジュールでは、CSSのオーバーフローについて詳しく見ていきます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/images_media_form_elements/index.html b/files/ja/learn/css/building_blocks/images_media_form_elements/index.html new file mode 100644 index 0000000000..f21577f7d5 --- /dev/null +++ b/files/ja/learn/css/building_blocks/images_media_form_elements/index.html @@ -0,0 +1,201 @@ +--- +title: 画像・メディア・フォーム要素 +slug: Learn/CSS/Building_blocks/Images_media_form_elements +tags: + - Beginner + - CSS + - Forms + - Images + - Learn + - Media + - replaced content +translation_of: Learn/CSS/Building_blocks/Images_media_form_elements +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks")}}
+ +

このレッスンでは、特定の要素が CSS でどのように扱われるかを見ていきます。画像・メディア・フォーム要素では、CSS でスタイルを設定するにあたって通常のボックスとは少し異なる動作をします。何が可能で何が不可能かを理解することで、フラストレーションを軽減することができます。このレッスンでは、知っておくべきことのをいくつかを取り上げます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:CSS でスタイルを設定したときに一部の要素が異常に動作することを理解する。
+ +

置換要素

+ +

画像とビデオは、置き換えられた要素として説明されています。これは、CSSがこれらの要素の内部レイアウトに影響を与えることはできず、他の要素の中でのページ上の位置のみに影響を与えることを意味します。ただし、後で説明するように、CSSが画像に対して様々なことができます。

+ +

画像や動画などの特定の置換された要素は、アスペクト比を持つものとしても記述されています。これは、水平方向 (x) と垂直方向 (y) の両方の寸法を持ち、デフォルトではファイルの本質的な寸法を使って表示されることを意味します。

+ +

画像サイズ

+ +

これらのレッスンを受けてすでにお分かりのように、CSSではすべてのものがボックスを生成します。画像ファイルの固有の寸法よりも小さいか大きいサイズの画像をボックス内に配置すると、ボックスよりも小さく表示されるか、ボックスをオーバーフローさせてしまいます。オーバーフローで何が起こるかについて決定を下す必要があります。

+ +

以下の例では、2つのボックスがあり、どちらもサイズは200ピクセルです。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/images/size.html", '100%', 1000)}}

+ +

では、オーバーフローの問題について何ができるでしょうか?

+ +

前のレッスンで学んだように、一般的な手法は、画像の {{cssxref("max-width")}} を100%にすることです。これにより、画像のサイズはボックスよりも小さくなりますが、大きくはなりません。この手法は、<video><iframe> などの他の置換された要素でも機能します。

+ +

上記の例 max-width: 100%<img> 要素に追加してみてください。小さい画像は変更されないままですが、大きい画像はボックスに収まるように小さくなります。

+ +

コンテナー内のイメージについて他の選択を行うことができます。例えば、ボックスを完全に覆うように画像のサイズを変更したい場合があります。

+ +

ここでは、{{cssxref("object-fit")}} プロパティが役立ちます。object-fit 置き換えられた要素を使用する場合、さまざまな方法でボックスに合うようにサイズを変更できます。

+ +

以下では、値 cover を使用して画像を縮小し、アスペクト比を維持してボックスをきれいに埋めます。アスペクト比が維持されているため、画像の一部がボックスでトリミングされます。

+ +

{{EmbedGHLiveSample("css-examples/learn/images/object-fit.html", '100%', 1000)}}

+ +

contain を値として使用する場合、ボックス内に収まるほど小さくなるまで画像が縮小されます。これは、ボックスと同じアスペクト比ではない場合、「レターボックス」になります。

+ +

fill を試すこともできます 。これは、ボックスを塗りつぶしますが、アスペクト比を維持しません。

+ +

レイアウト内の置換要素

+ +

置換された要素にさまざまなCSSレイアウト手法を使用すると、他の要素とは動作が少し異なる場合があります。 たとえば、フレックスまたはグリッドレイアウトでは、要素はデフォルトで領域全体に拡大されます。 画像は伸縮せず、代わりにグリッド領域またはフレックスコンテナーの始点に揃えられます。

+ +

次の例では、2列2行のグリッドコンテナーがあり、4つのアイテムが含まれています。すべての <div> 要素には背景色があり、行と列に合わせて伸縮します。ただし、画像は引き伸ばされません。

+ +

{{EmbedGHLiveSample("css-examples/learn/images/layout.html", '100%', 1000)}}

+ +

これらのレッスンを順番に実行している場合は、まだレイアウトを確認していない可能性があります。置き換えられた要素は、グリッドまたはフレックスレイアウトの一部になると、基本的にレイアウトによって不自然に引き伸ばされないようにするために、異なるデフォルトの動作になることに注意してください。

+ +

画像を強制的に引き伸ばして、グリッドセルを塗りつぶすには、次のような操作を行う必要があります。

+ +
img {
+  width: 100%;
+  height: 100%;
+}
+ +

ただし、これは画像を引き伸ばすため、おそらく望んでいることではありません。

+ +

フォーム要素

+ +

CSSでのスタイル設定に関しては、フォーム要素はトリッキーな問題であり、HTMLフォームモジュールには、フォーム要素のスタイル設定に関する詳細なガイドが含まれていますが、ここでは完全には再現しません。記事のこのセクションでは、強調すべきいくつかの重要な点があります。

+ +

多くのフォームコントロールは <input> 要素によってページに追加されます。これは、テキスト入力などの単純なフォームフィールドから、色や日付の選択などのHTML5で追加されたより複雑なフィールドまでを定義します。の <textarea> などの追加要素や、<fieldset><legend> などのフォームの一部を格納したりラベルを貼ったりするために使われる要素もあります。

+ +

HTML5には、Web開発者が必須フィールド、さらには入力する必要があるコンテンツのタイプを指定できるようにする属性も含まれています。ユーザーが予期しない何かを入力したり、必須フィールドを空白のままにしたりすると、ブラウザにエラーメッセージが表示されることがあります。 ブラウザによって、このようなアイテムのスタイリングやカスタマイズがどの程度可能なのかについては一貫性がありません。

+ +

テキスト入力欄のスタイル

+ +

<input type="text"><input type="email"><textarea> 要素などのテキスト入力を可能にする要素は、スタイルを整えるのが非常に簡単で、ページ上の他のボックスと同じように振る舞う傾向があります。しかし、これらの要素のデフォルトのスタイルは、ユーザーがサイトを訪問する際に使用するオペレーティングシステムやブラウザによって異なります。

+ +

以下の例では、CSSを使用していくつかのテキスト入力にスタイルを設定しています。境界線、マージン、パディングなどがすべて期待どおりに適用されていることがわかります。属性セレクターを使用して、さまざまな入力タイプをターゲットにしています。ボーダーを調整し、フィールドに背景色を追加し、フォントとパディングを変更して、このフォームの外観を変更してみてください。

+ +

{{EmbedGHLiveSample("css-examples/learn/images/form.html", '100%', 1000)}}

+ +
+

重要:フォーム要素のスタイルを変更するときは、ユーザーがフォーム要素であることをユーザーに明確に伝えるように注意する必要があります。周囲のコンテンツとほとんど見分けがつかない境界線や背景のないフォーム入力を作成することもできますが、これにより認識や入力が非常に難しくなります。

+
+ +

このコースのHTMLパートのフォームスタイリングに関するレッスンで説明したように、より複雑な入力タイプの多くはオペレーティングシステムによってレンダリングされ、スタイリングにアクセスできません。そのため、フォームは訪問者によってかなり違って見えることを常に想定し、複雑なフォームをいくつかのブラウザでテストする必要があります。

+ +

継承とフォーム要素

+ +

一部のブラウザでは、フォーム要素はデフォルトではフォントのスタイルを継承しません。そのため、フォームのフィールドがボディや親要素で定義されたフォントを使用するようにしたい場合は、CSSにこのルールを追加する必要があります。

+ +
button,
+input,
+select,
+textarea {
+  font-family : inherit;
+  font-size : 100%;
+} 
+ +

フォーム要素と box-sizing

+ +

ブラウザー間で、フォーム要素は、さまざまなウィジェットに対してさまざまなボックスサイズ設定ルールを使用します。ボックスモデルのレッスンでbox-sizing プロパティについて学習しました。フォームのスタイル設定時にこの知識を使用して、フォーム要素に幅と高さを設定するときに一貫したエクスペリエンスを確保できます。

+ +

一貫性を保つために、すべての要素でマージンとパディングに 0 を設定し、特定のコントロールをスタイリングするときにこれらを追加することをお勧めします

+ +
button,
+input,
+select,
+textarea {
+  box-sizing: border-box;
+  padding: 0;
+  margin: 0;
+}
+ +

その他の便利な設定

+ +

上記のルールに加えて、スクロールバーが不要な場合にIEがスクロールバーを表示しないよう overflow: auto<textarea>sを設定する必要があります。

+ +
textarea {
+  overflow: auto;
+}
+ +

リセット処理としてまとめる

+ +

最後のステップとして、上記で説明したさまざまなプロパティを次の「フォームリセット」にラップして、作業の一貫性のあるベースを提供できます。これには、最後の3つのセクションで言及したすべてのアイテムが含まれます。

+ +
button,
+input,
+select,
+textarea {
+  font-family: inherit;
+  font-size: 100%;
+  box-sizing: border-box;
+  padding: 0; margin: 0;
+}
+
+textarea {
+  overflow: auto;
+} 
+ +
+

:正規化スタイルシートは、すべてのプロジェクトで使用する一連のベースラインスタイルを作成するために、多くの開発者によって使用されています。通常、これらは上記で説明したものと同様のことを行います。CSSで独自の作業を行う前に、ブラウザー間で異なるものがすべて一貫したデフォルトに設定されていることを確認してください。ブラウザは通常、以前より一貫性があるため、以前ほど重要ではありません。ただし、1つの例を見てみたい場合は、Normalize.cssをチェックしてください。Normalize.cssは、多くのプロジェクトでベースとして使用されている非常に人気のあるスタイルシートです。

+
+ +

フォームのスタイル設定の詳細については、これらのガイドのHTMLセクションにある2つの記事をご覧ください。

+ + + +

まとめ

+ +

このレッスンでは、CSSで画像、メディア、およびその他の異常な要素を操作するときに発生するいくつかの違いを強調しました。次の記事では、HTMLテーブルをスタイルする必要がある場合に役立ついくつかのヒントについて説明します。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/index.html b/files/ja/learn/css/building_blocks/index.html new file mode 100644 index 0000000000..3094d16d9c --- /dev/null +++ b/files/ja/learn/css/building_blocks/index.html @@ -0,0 +1,88 @@ +--- +title: CSS の構成要素 +slug: Learn/CSS/Building_blocks +tags: + - Beginner + - CSS + - Learn + - building blocks +translation_of: Learn/CSS/Building_blocks +--- +
{{LearnSidebar}}
+ +

このモジュールは CSS の第一歩から派生しています。CSS の言語や文法に慣れてきて、それを使う上での基本的な経験を得てきたという前提で、もう少し掘り下げてみましょう。カスケードと継承・セレクターの全種類・単位・サイズ設定・背景と枠線・デバッグなどを見ていきます。

+ +

ここでの目的は、テキストの装飾や CSS レイアウトなどのより具体的な分野に進む前に、適切な CSS を書くための手法を知り、すべての重要な理論を理解できるようになることです。

+ +

前提知識

+ +

このモジュールを始めるまえに、つぎの状態になっておくべきです。

+ +
    +
  1. コンピューターの使い方と(ウェブを見たりコンテンツを消費したりといった)ウェブの受動的な使い方に関する基本的な知識に慣れ親しんでいること。
  2. +
  3. 基本的なソフトウェアのインストールで説明されている基本的な作業環境と、ファイルの扱い方で説明されているファイルの作り方や管理の仕方について理解していること。
  4. +
  5. HTML 入門で説明されている HTML についての基礎知識に慣れ親しんでいること。
  6. +
  7. CSS の第一歩で説明されている CSS の基本について理解していること。
  8. +
+ +
+

: 自分自身でファイルを作れない環境 (タブレットやその他の端末) で作業する場合、(ほとんどの) コードサンプルは JSBinGlitch といったオンラインコーディングプログラムで試すことが可能です

+
+ +

ガイド

+ +

このモジュールは CSS 言語のもっとも重要な部分をカバーする以下の記事で構成されます。各記事には理解度を試すエクササイズも含まれます。

+ +
+
カスケードと継承
+
このレッスンでの目的は、CSS を HTML に適用する方法と競合した場合の解決方法について、もっとも基本的な概念(カスケード・詳細度・継承)の理解を深めていくことです。
+
CSS セレクター
+
CSS セレクターにはさまざまな種類があり、スタイルを設定する要素を厳密に指定することができます。この記事と以下のサブ記事では、それらがどのように機能するかを詳しく見ていきます。サブ記事は以下の通りです: + +
+
ボックスモデル
+
CSS のすべてにはボックスの概念があり、これを理解することは CSS でレイアウトを作成したりアイテム同士を揃えたりするためのコツとなります。このレッスンでは CSS ボックスモデルを詳しく解説し、その仕組みと関連する用語を理解することで、より複雑なレイアウトに進んでいけるようにします。
+
背景と枠線
+
このレッスンでは、CSS の背景と枠線を使ってできるクリエイティブなことをいくつか見ていきます。グラデーションや背景画像や角丸について、背景と枠線は CSS のスタイリングに関する多くの疑問の解決策です。
+
テキスト方向の操作
+
近年では、右から左へだけでなく上から下へのコンテンツ(日本語など)を含むコンテンツのさまざまな向きをより適切にサポートするために CSS サポートが進化しています。これらのさまざまな向きの考え方については "writing modes" と呼ばれます。レイアウトの学習を進めて進めていくと "writing modes" の理解がとても役に立っていきますので、この記事ではそれらを紹介していきます。
+
要素のはみ出し(オーバーフロー)
+
このレッスンでは、CSS のもう 1 つの重要な概念である オーバーフロー(overflow)を見ていきますオーバーフローは、ボックス内にコンテンツが収まりきらないときに発生します。このガイドでは、その詳細とそれらについてどのように対処するかを学びます。
+
CSS の値と単位
+
CSS で使用されるすべてのプロパティには、特定の値または値の組み合わせのみが許可されます。このレッスンでは、もっともよく使用される値と単位について見ていきます。
+
CSS によるサイズ設定
+
これまでのさまざまなレッスンで、CSS を使用してウェブページ上の項目のサイズを調整するいくつかの方法に出会いました。デザイン作業をしていくうえで、それぞれの手法がどれほど大きく異なっているのかを理解することが重要です。このレッスンでは、CSS によって要素のサイズを設定する方法をまとめ、サイジングに役立ついくつかの用語を定義します。
+
画像・メディア・フォーム要素
+
このレッスンでは、特定の要素が CSS でどのように扱われるかを見ていきます。画像・メディア・フォーム要素では、CSS でスタイルを設定するにあたって通常のボックスとは少し異なる動作をします。何が可能で何が不可能であるのかを理解することで、フラストレーションを軽減することができます。このレッスンでは、知っておくべきことをいくつか取り上げます。
+
表のスタイリング
+
HTML 表を装飾することは、世界で最も魅力的な仕事ではありませんが、時にはそれをしなければならないこともあります。この記事では、表をスタイリングするテクニックとともに、HTML 表を見栄え良くするためのガイドを提供します。
+
CSS のデバッグ
+
CSS を書くとき、期待どおりに動作していないように見える問題が発生する場合があります。この記事では CSS の問題をデバッグする方法について案内し、何が起こっているかを調べるのに、すべてのモダンブラウザーに入っている開発者ツールがどう役立つかを示します。
+
CSS の整理
+
スタイルシートやプロジェクトが大きい状態で作業しはじめると、巨大な CSS ファイルを維持するのが難しいことがわかります。この記事では、保守しやすい CSS を書くためのベストプラクティスと、他の人が保守性を向上させるための解決策の一部を紹介します。
+
+ +

評価

+ +

CSS スキルをテストしたいですか?以下の各評価では上記のガイドで説明されている CSS の理解度をテストできます。

+ +
+
基本的な CSS の理解
+
この評価では基本的な構文・セレクター・詳細度・ボックスモデル・その他の理解度をテストします。
+
装飾的なレターヘッド付きの便箋の作成
+
好印象を与えたいのなら、素敵なレターヘッドの便箋に手紙を書くのはとても良い考えです。この評価では、そのような見た目のオンラインテンプレートの作成に挑戦します。
+
かっこいいボックス
+
ここでは背景と枠線のスタイリングを使った人目を引くボックスの作り方を実践します。
+
+ +

関連情報

+ +
+
ボックスの高度なエフェクト
+
この記事はトリックの箱として機能し、ボックスの影・ブレンドモード・フィルターのような、ボックスの装飾に使用できる高度な機能のいくつかを紹介します。
+
diff --git a/files/ja/learn/css/building_blocks/organizing/index.html b/files/ja/learn/css/building_blocks/organizing/index.html new file mode 100644 index 0000000000..f1508b0edb --- /dev/null +++ b/files/ja/learn/css/building_blocks/organizing/index.html @@ -0,0 +1,375 @@ +--- +title: CSS の整理 +slug: Learn/CSS/Building_blocks/Organizing +tags: + - Beginner + - CSS + - CodingScripting + - Learn + - comments + - formatting + - methodologies + - organizing + - post-processor + - pre-processor + - styleguide +translation_of: Learn/CSS/Building_blocks/Organizing +--- +
{{LearnSidebar}}{{PreviousMenu("Learn/CSS/Building_blocks/Debugging_CSS", "Learn/CSS/Building_blocks")}}
+ +

スタイルシートやプロジェクトが大きい状態で作業しはじめると、巨大な CSS ファイルを維持するのが難しいことがわかります。この記事では、CSS を書いていくのと保守していくのをやりやすくするためのベストプラクティスと、保守性を向上させるための解決策の一部を紹介します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:スタイルシートを整理するためのヒントとベストプラクティスを学び、 CSS の整理およびチーム作業を手助けするいくつかの命名規則とツールについて調べる。
+ +

CSS を整理するためのヒント

+ +

スタイルシートを整理して整頓するための一般的な提案を次に示します。

+ +

プロジェクトのコーディング規約があるか?

+ +

既存のプロジェクトでチームと作業している場合、最初に確認することは、プロジェクトに CSS の既存のスタイルガイドがあるかどうかです。チームスタイルガイドは常に自分の個人的な好みに勝つ必要があります。多くの場合、正しい方法や間違った方法はありませんが、一貫性が重要です。

+ +

例えば、MDN コードの例の CSS ガイドラインを見てみましょう。

+ +

一貫性を保つ

+ +

プロジェクトのルールを設定したり、単独で作業している場合、最も重要なことは、一貫性を保つことです。一貫性は、クラスに同じ命名規則を使用する、色を説明する1つの方法を選択する、一貫したフォーマットを維持するなど、あらゆる方法で適用できます(例えば、タブまたはスペースのどちらを使用してコードをインデントしますか。スペースの場合、いくつのスペース?)

+ +

常に従う一連のルールがあると、CSS を作成するときに必要な精神的なオーバーヘッドの量が減ります。

+ +

CSS を読みやすくする

+ +

CSS がフォーマットされているのを確認するには、いくつかの方法があります。一部の開発者は、次のようにすべてのルールを1行に配置します。

+ +
.box { background-color: #567895; }
+h2 { background-color: black; color: white; }
+ +

他の開発者はすべてを新しい行に分割することを好みます:

+ +
.box {
+  background-color: #567895;
+}
+
+h2 {
+  background-color: black;
+  color: white;
+}
+ +

CSSはどちらを使用してもかまいません。個人的には、各プロパティと値のペアを新しい行に置く方が読みやすくなっています。

+ +

CSS にコメントを書いておく

+ +

あなたの CSS にコメントを追加することは、将来の開発者があなたの CSS ファイルを使って作業する際の助けになるだけでなく、休暇の後にプロジェクトに戻ってきたときにも役立ちます。

+ +
/* これは CSS コメントです
+複数行に分割できます。 */
+ +

ヒントとしては、スタイルシートの論理セクション間にコメントブロックを追加して、スキャンするときにさまざまなセクションをすばやく見つけられるようにしたり、CSS のその部分にジャンプするために検索するものを提供したりすることもできます。コードに表示されない文字列を使用する場合は、検索することでセクションからセクションにジャンプできます。以下では || を使用しています。

+ +
/* || 一般的なスタイル */
+
+...
+
+/* || タイポグラフィ*/
+
+...
+
+/* || ヘッダーとメインナビゲーション */
+
+...
+
+
+ +

あなたのCSSにある全てのことにコメントをつける必要はありません。コメントすべきなのは、理由があって特定の決定をしたものです。

+ +

古いブラウザの非互換性を回避するために、CSS プロパティを特定の方法で使用した可能性があります。例えば:

+ +
.box {
+  background-color: red; /* グラデーションをサポートしない古いブラウザのフォールバック */
+  background-image: linear-gradient(to right, #ff0000, #aa0000);
+}
+
+ +

おそらく、何かを達成するためにチュートリアルに従ったのではないかと思いますが、CSSが少し自明ではなくなっているのではないかと思います。その場合は、コメントにチュートリアルの URL を追加することができます。1年後かそこらでこのプロジェクトに戻ってきたときに自分自身に感謝するだろうし、漠然とそのことについての素晴らしいチュートリアルがあったことを思い出すことができますが、それはどこにあるのでしょうか?

+ +

スタイルシートを合理的に分割する

+ +

スタイルシートで最初にすべての一般的なスタイルを設定することをお勧めします。これは、その要素で特別なことをしない限り、通常適用されるすべてのスタイルを意味します。通常、次のルールを設定します。

+ + + +

スタイルシートのこのセクションでは、サイトのタイプにデフォルトのスタイルを提供したり、データテーブルとリストのデフォルトスタイルを設定したりします。

+ +
/* || 一般的なスタイル */
+
+body { ... }
+
+h1, h2, h3, h4 { ... }
+
+ul { ... }
+
+blockquote { ... }
+
+ +

このセクションの後で、いくつかのユーティリティクラスを定義できます。例えば、フレックスアイテムとして、または他の方法で表示するリストのデフォルトのリストスタイルを削除するクラス。多くの異なる要素に適用したいことがわかっていることがいくつかある場合、それらはこのセクションにあります。

+ +
/* || ユーティリティ */
+
+.nobullets {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+
+...
+
+
+ +

次に、サイト全体で使用されるすべてのものを追加できます。それは、基本的なページレイアウト、ヘッダー、ナビゲーションスタイルなどのようなものかもしれません。

+ +
/*  || サイトワイド */
+
+.main-nav { ... }
+
+.logo { ... }
+
+ +

最後に、コンテキスト、ページ、またはそれらが使用されているコンポーネントで分類された特定のものの CSS を含めます。

+ +
/* || 店のページ */
+
+.product-listing { ... }
+
+.product-box { ... }
+
+ +

このように物事を順番に並べることで、少なくともスタイルシートのどの部分に変更したいものがあるのかを知ることができます。

+ +

過剰なセレクターを避ける

+ +

非常に特殊なセレクタを作成した場合、別の要素に同じルールを適用するために CSS の塊を複製する必要があることに気づくことがよくあります。例えば、以下のセレクタのようなものがあるかもしれませんが、これは main のクラスを持つ <article> の中の box のクラスを持つ <p> にルールを適用します。

+ +
article.main p.box {
+  border: 1px solid #ccc;
+}
+ +

同じルールを main 以外のものや <p> 以外のものにも適用したい場合は、これらのルールに別のセレクタを追加するか、まったく新しいルールセットを作成しなければなりません。その代わりに、box というクラスを作成して、どこでも適用することができます。

+ +
.box {
+  border: 1px solid #ccc;
+}
+ +

もっと具体的にすることが理にかなっている場合もありますが、これは通常の習慣ではなく、一般的に例外です。

+ +

スタイルシートが大きくなってきたら分割する

+ +

特に、サイトの異なる部分に対して非常に異なるスタイルを持っている場合には、すべてのグローバルルールを含むスタイルシートと、それらのセクションに必要な特定のルールを含む小さなスタイルシートを持ちたいと思うかもしれません。一つのページから複数のスタイルシートにリンクすることができ、カスケードの通常のルールが適用され、後からリンクされたスタイルシートのルールは前からリンクされたスタイルシートのルールの後から適用されます。

+ +

例えば、サイトの一部としてオンラインストアがあり、ストアに必要な商品リストやフォームのスタイリングにのみ多くの CSS が使用されているとします。それらを別のスタイルシートにして、ストアページでのみリンクさせるのは理にかなっていると思います。

+ +

これにより、CSS の整理が容易になります。また、複数のユーザーが CSS で作業している場合、2人が同時に同じスタイルシートで作業する必要がなくなり、ソース管理で競合が発生する可能性も少なくなります。

+ +

その他の役立つツール

+ +

CSS 自体には内蔵された整理の方法があまりないので、CSS の書き方に一貫性やルールを作る作業をする必要があります。また、ウェブ・コミュニティでは、大規模な CSS プロジェクトを管理するのに役立つ様々なツールやアプローチが開発されています。これらはあなたが調べてみると役に立つかもしれませんし、他の人と一緒に作業をしているときに出くわす可能性が高いので、これらのいくつかについての簡単なガイドを載せておきます。

+ +

CSS の方法論

+ +

CSS を作成するための独自のルールを考え出す必要はなく、コミュニティーによってすでに設計され、多くのプロジェクトでテストされているアプローチの1つを採用することでメリットが得られる場合があります。これらの方法論は基本的に CSS のコーディングガイドであり、CSS の作成と管理に非常に構造化されたアプローチを採用しています。通常、これらの方法論では、すべてのセレクタを作成してそのプロジェクトのカスタムルールセットに最適化した場合よりも、CSS の使用が冗長になる傾向があります。

+ +

しかし、1つを採用することで多くの構造を得ることができますし、これらのシステムの多くは非常に広く使われているので、他の開発者はあなたが使用しているアプローチを理解し、自分の個人的な方法論を一から作り上げるよりも、同じように CSS を書くことができる可能性が高くなります。

+ +

OOCSS

+ +

あなたが遭遇するであろうアプローチのほとんどは、Nicole Sullivan の業績によって人気を博した Object Oriented CSS (OOCSS) のコンセプトに起因しています。OOCSS の基本的な考え方は、CSS を再利用可能なオブジェクトに分割し、サイト上の必要な場所で使用できるようにすることです。OOCSS の標準的な例は、The Media Object として記述されているパターンです。これは、片面に固定サイズの画像や動画などの要素を配置し、もう片面には柔軟なコンテンツを配置したパターンです。コメントやリスティングなどのウェブサイトでよく見かけるパターンです。

+ +

OOCSS の手法を採用していない場合は、このパターンが使用されるさまざまな場所に対してカスタムCSSを作成することができます。たとえば、コンポーネント・パーツに対して一連のルールを持つ comment というクラスを作成し、次に、いくつかの小さな違いを除いて、comment クラスとほとんど同じルールを持つ list-item というクラスを作成します。これら2つのコンポーネントの違いは、list-item には下罫線があり、comment 内のイメージには罫線がありますが、list-item のイメージにはないことです。

+ +
.comment {
+  display: grid;
+  grid-template-columns: 1fr 3fr;
+}
+
+.comment img {
+  border: 1px solid grey;
+}
+
+.comment .content {
+  font-size: .8rem;
+}
+
+.list-item {
+  display: grid;
+  grid-template-columns: 1fr 3fr;
+  border-bottom: 1px solid grey;
+}
+
+.list-item .content {
+  font-size: .8rem;
+}
+ +

OOCSS では、media と呼ばれる1つのパターンを作成して、両方のパターンに共通の CSSをすべて持つようにします。一般的には media オブジェクトの形状を表す基底クラスです。そして、それらの小さな違いに対応するために追加のクラスを追加して、特定の方法でスタイリングを拡張します。

+ +
.media {
+  display: grid;
+  grid-template-columns: 1fr 3fr;
+}
+
+.media .content {
+  font-size: .8rem;
+}
+
+.comment img {
+  border: 1px solid grey;
+}
+
+ .list-item {
+  border-bottom: 1px solid grey;
+} 
+ +

HTMLでは、コメントに mediacomment クラスの両方を適用する必要があります。

+ +
<div class="media comment">
+  <img />
+  <div class="content"></div>
+</div>
+
+ +

リストアイテムは次のように medialist-item が適用されます。

+ +
<ul>
+  <li class="media list-item">
+    <img />
+   <div class="content"></div>
+  </li>
+</ul>
+ +

Nicole Sullivan がこのアプローチを説明し、促進するために行った作業は、今日ではOOCSS のアプローチに厳密に従っていない人でも、一般的にはこの方法で CSS を再利用することを意味します。これは、一般的に物事に取り組むための良い方法としての理解につながりました。

+ +

BEM

+ +

BEM は、Block Element Modifier の略です。BEM では、ブロックはボタン、メニュー、ロゴなどのスタンドアロンエンティティです。要素とは、リストアイテムやタイトルのようなものであり、それが入っているブロックに関連付けられています。修飾子は、スタイルや動作を変更するブロックまたは要素のフラグです。CSS クラスではダッシュとアンダースコアが多用されているため、BEM を使用するコードを認識できます。例えば、BEMの命名規則に関するページから、この HTML に適用されるクラスを見てみましょう。

+ +
<form class="form form--theme-xmas form--simple">
+  <input class="form__input" type="text" />
+  <input
+    class="form__submit form__submit--disabled"
+    type="submit" />
+</form>
+ +

追加のクラスは、OOCSS の例で使用されているクラスに似ていますが、BEM の厳密な命名規則を使用しています。

+ +

BEM は大規模な Web プロジェクトで広く使用されており、多くの人がこの方法で CSS を作成しています。チュートリアルでさえ、CSS がこのように構造化されている理由について触れずに、BEM 構文を使用する例に出くわす可能性があります。

+ +

システムの詳細については、CSS トリックの BEM 101 を参照してください。

+ +

その他

+ +

これらのシステムは多数使用されています。その他の一般的なアプローチには、Jonathan Snook によって作成された CSSのスケーラブルでモジュール式のアーキテクチャ(SMACSS)、Harry Roberts の ITCSS、および Yahoo! によって最初に作成された Atomic CSS(ACSS)があります。これらのアプローチのいずれかを使用するプロジェクトに遭遇した場合の利点は、同じスタイルでコーディングする方法を理解するのに役立つ多くの記事とガイドを検索して見つけることができることです。

+ +

このようなシステムを使用することの欠点は、特に小規模なプロジェクトの場合、過度に複雑に見える可能性があることです。

+ +

CSS のビルドシステム

+ +

CSS を編成するもう1つの方法は、フロントエンド開発者が利用できるツールのいくつかを利用することです。これにより、CSS を書くために、よりプログラム的なアプローチを取ることができます。プリプロセッサポストプロセッサと呼ばれるツールは多数あります。プリプロセッサは未加工ファイルを実行してそれらをスタイルシートに変換し、ポストプロセッサは完成したスタイルシートに何かを実行します。おそらく、ロードを高速化するために最適化します。

+ +

これらのツールを使用するには、開発環境で前処理と後処理を行うスクリプトを実行できる必要があります。多くのコードエディタでこれを行うことができます。または、コマンドラインツールをインストールして支援することもできます。

+ +

最も人気のあるプリプロセッサは Sass です。これは Sass のチュートリアルではありませんので、Sass でできることを簡単に説明します。これは Sass の他の機能を使っていなくても、整理する上で非常に便利です。 Sass についてもっと知りたいのであれば、Sass の基礎知識の記事から始めて、他のドキュメントに進んでください。

+ +

変数の定義

+ +

CSS にネイティブカスタムプロパティが追加されたため、この機能の重要性は低下していますが、Sass を使用する理由の1つは、プロジェクトで使用されるすべての色とフォントを設定として定義し、その変数をプロジェクトで使用できるようにすることです。これは、間違った青の色合いを使用したことがわかった場合、1つの場所で変更するだけでよいことを意味します。

+ +

$base-color 以下の最初の行のように呼び出される変数を作成した場合、その色が必要な場所であればどこでも、スタイルシートを介してその変数を使用できます。

+ +
$base-color: #c6538c;
+
+.alert {
+  border: 1px solid $base-color;
+}
+ +

CSS にコンパイルすると、最終的なスタイルシートには次の CSS が含まれます。

+ +
.alert {
+  border: 1px solid #c6538c;
+}
+ +

コンポーネントスタイルシートのコンパイル

+ +

CSS を整理する1つの方法は、スタイルシートを小さなスタイルシートに分解することであると上記で述べました。Sass を使用すると、これを別のレベルに引き上げ、非常に小さなスタイルシートをたくさん持つことができます。コンポーネントごとに個別のスタイルシートを用意することもできます。Sass のインクルード機能を使用することで、これらすべてを1つまたは少数のスタイルシートにまとめて、実際に Web サイトにリンクできます。

+ +

例えば、partial を使って、ディレクトリ内にいくつかのスタイルファイル、例えば foundation/_code.scssfoundation/_lists.scssfoundation/_footer.scssfoundation/_links.scss などを作成し、Sass の @use ロールを使って他のスタイルシートにロードすることができます。

+ +
// foundation/_index.sass
+@use 'code'
+@use 'lists'
+@use 'footer'
+@use 'links'
+ +

上記のように、パーシャルがすべてインデックスファイルにロードされている場合、ディレクトリ全体を一度に別のスタイルシートにロードすることができます。

+ +
// style.sass
+@use 'foundation'
+ + + +
+

:Sass を試す簡単な方法は、CodePen を使用することです。これを有効にすると、CodePen が Sass パーサを実行してくれるので、通常の CSS を適用したウェブページを見ることができます。CSS チュートリアルでは、CodePen のデモでプレーンな CSS ではなく Sass を使用しているのを見つけることがありますので、少しでも知っておくと便利です。

+
+ +

ポストプロセッサー

+ +

もし、コメントや空白を大量に追加することでスタイルシートのサイズが大きくなることを気にしているのであれば、本番バージョンでは不要なものを取り除くことで CSS を最適化することが後処理のステップになります。これを実現するポストプロセッサの例としては、cssnano があります。

+ +

まとめ

+ +

これは CSS 学習ガイドの最後の部分で、ここから CSS の探求を続けるための様々な方法があることがお分かりいただけると思います。

+ +

CSS のレイアウトの詳細については、「CSSレイアウトの学習」セクションを参照してください。

+ +

また、これで MDN の CSS の資料の残りの部分を探索するためのスキルを身につけることができます。プロパティや値を調べたり、CSS クックブックで使用するパターンを調べたり、Guide to CSS Grid Layout などの特定のガイドを読んだりすることができます。

+ +

{{PreviousMenu("Learn/CSS/Building_blocks/Debugging_CSS", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/overflowing_content/index.html b/files/ja/learn/css/building_blocks/overflowing_content/index.html new file mode 100644 index 0000000000..313f2cc3b0 --- /dev/null +++ b/files/ja/learn/css/building_blocks/overflowing_content/index.html @@ -0,0 +1,132 @@ +--- +title: 要素のはみ出し(オーバーフロー) +slug: Learn/CSS/Building_blocks/Overflowing_content +tags: + - Beginner + - Block Formatting Context + - CSS + - Data Loss + - Learn + - overflow +translation_of: Learn/CSS/Building_blocks/Overflowing_content +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks")}}
+ +

このレッスンでは、CSS のもう1つの重要な概念である オーバーフロー(overflow)を見ていきますオーバーフローは、ボックス内にコンテンツが収まりきらないときに発生します。このガイドでは、その詳細とそれらについてどのように対処するかを学びます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:オーバーフローとその管理方法を理解する。
+ +

オーバーフロー (overflow) とは?

+ +

CSS のすべてがボックスであり、 {{cssxref("width")}} と {{cssxref("height")}}(または {{cssxref("inline-size")}} や {{cssxref("block-size")}}) の値を与えることにより、これらのボックスのサイズを制御できることを見てきました。オーバーフローはボックス内のコンテンツが多すぎる場合に発生し、快適に収まらないという状態です。CSS はこのオーバーフローを管理するためのさまざまなツールを提供しますが、早めに理解しておくと役立つ概念でもあります。CSS を書いていると、とりわけ CSS によるレイアウトを深く理解していくにつれ、オーバーフローによく出くわします。

+ +

CSS のデータ損失の回避

+ +

オーバーフローが発生した場合の CSS の既定の動作を示す2つの例を見てみましょう。

+ +

1つめの例です。まずブロックに height でボックスの高さを制限します。そしてそのスペースよりも多くのコンテンツを追加します。コンテンツはボックスからはみ出し、下の段落にかぶさってしまいます。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/block-overflow.html", '100%', 600)}}

+ +

2つめに、インラインとして制限されているボックス内の単語の例です。ボックスは単語が収まらないほど小さいため、ボックスからはみ出てしまいます。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/inline-overflow.html", '100%', 500)}}

+ +

CSS のこの既定のアプローチは、コンテンツをかなり乱雑にオーバーフローさせているように感じられるかもしれません。追加のコンテンツを非表示にしたり、ボックスを大きくさせたりしないのはなぜなのでしょう。

+ +

CSS は可能な限りコンテンツを隠しません。これをやってしまうと、通常は問題となりうるデータ損失が発生するためです。CSS はこのようにコンテンツが消えることを懸念します。コンテンツが消失したことに気付かない可能性があるのは問題だからです。見ている人は消えたことに気付かないかもしれません。フォーム上の送信ボタンが消えてしまい、フォームが完了できない場合それは大きな問題です。代わりに CSS は目に見える方法でオーバーフローしようとします。あなたもしくは訪問者がコンテンツが重なっているという状況に気づき、修正が必要であることを知ることができます。

+ +

ボックスを width または height で制御している場合、CSS はオーバーフローの可能性が管理されていると想定します。一般にボックスにテキストがある場合、ブロックのサイズを制御することは問題になりがちです。例えば、想定していたよりも多くのテキストになってしまったか、フォントサイズを大きくした場合などです。 

+ +

次のいくつかのレッスンでは、オーバーフローを起こしにくいサイジング方法を見ていきます。固定サイズが必要な場合は、オーバーフローの動作を制御することもできます。読み進めましょう。

+ +

overflow プロパティ

+ +

{{cssxref("overflow")}} プロパティは要素のオーバーフローを制御し、ブラウザにどのように動作させるかを伝えます。既定値は visible のため、オーバーフロー時にコンテンツは表示されます。

+ +

オーバーフロー時にコンテンツをトリミングしたい場合、overflow: hidden をボックスに指定します。これは文字通り、はみ出たものを見えなくします。これにより内容が隠れてしまうことが起こりうるため、コンテンツが非表示になっても問題にならない場合にのみに限定した方がいいでしょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/hidden.html", '100%', 600)}}

+ +

コンテンツのオーバーフロー時にスクロールバーを表示したいこともあるでしょう。 overflow: scroll を指定すればコンテンツがオーバーフローしない場合でも、ブラウザーはスクロールバーを表示します。コンテンツに応じてスクロールバーが表示されたり消えたりするのを防ぐため、これが必要な場合があります。

+ +

下のボックスからコンテンツの一部を削除すると、スクロールするものがなくてもスクロールバー(または少なくともトラック部品)が残っていることがわかります。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/scroll.html", '100%', 600)}}

+ +

上記の例では y 軸のスクロールバーだけがあればいいのですが、横スクロールバーも表示されてしまいます。{{cssxref("overflow-y")}} プロパティを使えば、y 軸のみのスクロールバーを指定できます。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/scroll-y.html", '100%', 600)}}

+ +

{{cssxref("overflow-x")}} を使用して、x 軸のみのスクロールバーを表示できますが、文字が見切れてしまうことの回避策としては推奨されません。小さなボックスで長い文字列を処理する場合は、{{cssxref("word-break")}} や {{cssxref("overflow-wrap")}} を検討してください。CSS によるサイズ設定 で説明した方法のいくつかは、さまざまな量のコンテンツに適切に対応するボックスを作成するのに役立つ場合があります。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/scroll-x.html", '100%', 500)}}

+ +

scroll にしておけばコンテンツが少ないとしても、それとは関係なくスクロールバーは常に表示されます。

+ +
+

: overflow プロパティでは  x と y の2つの値を渡すことができることに注意してください。2つのキーワードが指定されている場合、ひとつめは overflow-x、2つめは overflow-y として適用されます。それ以外の場合は overflow-x と overflow-y の両方に同じ値が設定されます。例えば、overflow: scroll hidden とした場合は、overflow-x は scrolloverflow-y は hidden となります。

+
+ +

コンテンツがボックスに収まらない場合にのみ、スクロールバーを表示する場合は overflow: auto を使用します。この場合、スクロールバーを表示するかどうかはブラウザーによります。通常、デスクトップブラウザはコンテンツがオーバーフローする場合にのみそうします。

+ +

以下の例では、ボックスに収まるまでコンテンツを削除していくとスクロールバーが消えます。

+ +

{{EmbedGHLiveSample("css-examples/learn/overflow/auto.html", '100%', 600)}}

+ +

オーバーフローとブロック整形コンテキスト

+ +

CSS には ブロック整形コンテキスト (BFC = Block Formatting Context) の概念があります。これは今のところあまり気にする必要はありませんが、scroll や auto などのオーバーフローの設定で BFC が作成されることを知っておくと便利です。結果として overflow の値を変更したボックスのコンテンツは、独自のミニレイアウトになります。コンテナの外側の物は中に突っ込むことができず、ボックスから周囲のレイアウトに突き出すこともできません。これによってボックスにはすべてのコンテンツが含まれており、かつ、ページ上の他のアイテムと重ならないという、一貫したスクロール体験を生み出します。

+ +

オーバーフローの望ましくないウェブデザイン

+ +

モダンなレイアウト手法(CSS レイアウト モジュールで説明)では、オーバーフローを管理します。これらの方法は、ウェブページ上にどれだけのコンテンツが存在するかについての仮定や依存関係なしに大きく機能します。

+ +

しかし過去には開発者は多くの場合、固定された高さを使用して、実際には互いに関係のないボックスの底を揃えようとしました。それは脆く、レガシーなアプリケーションでは、コンテンツが他のコンテンツに重なってしまっているのを見かけることがあります。それによってオーバーフローが起きていることがわかります。理想としては、ボックスサイズの固定に依存しないようにレイアウトを調整します。

+ +

サイトを開発するときは、常にオーバーフローの問題に留意する必要があります。大量のコンテンツと少量のコンテンツを含むデザインをテストし、テキストのフォントサイズを大きくし、CSS が堅牢に対処できていると確認する必要があります。オーバーフローの値を変更してコンテンツを非表示にしたりスクロールバーを追加したりするのは、特別な場合(例えばスクロールが本当に必要な場合など)にのみ使うべきです。

+ +

あなたのスキルをテストしてみてください!

+ +

このレッスンで吸収すべきことはたくさんあります! あなたは最も重要な情報を覚えていますか? あなたの理解度を確認するには、Test your skills: overflow を参照してください。

+ +

まとめ

+ +

この短いレッスンではオーバーフローの概念を紹介しました。CSS はオーバーフローしたコンテンツが見えなくなることによる、データ損失の回避を試みることを理解しました。潜在的なオーバーフローを管理できること、また、問題のあるオーバーフローを引き起こしてしまわないかを確認する必要があることもわかりました。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/selectors/attribute_selectors/index.html b/files/ja/learn/css/building_blocks/selectors/attribute_selectors/index.html new file mode 100644 index 0000000000..57feac8995 --- /dev/null +++ b/files/ja/learn/css/building_blocks/selectors/attribute_selectors/index.html @@ -0,0 +1,180 @@ +--- +title: 属性セレクター +slug: Learn/CSS/Building_blocks/Selectors/Attribute_selectors +tags: + - Attribute + - Beginner + - CSS + - Learn + - Selectors +translation_of: Learn/CSS/Building_blocks/Selectors/Attribute_selectors +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}

+ +

HTML の学習で学んだように、要素はマークアップについてさらに詳細な情報を提供する属性を持つことがあります。 CSS では、属性セレクターを使用して、ある種類の属性のある要素を対象に指定できます。このレッスンでは、これらのとても便利なセレクターの使い方を紹介します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、 HTML の基本 (HTML 入門) および CSS に関するアイデア (CSS の第一歩) に関する基本的な知識を得ている。
目的:属性セレクターとは何かと、その使い方を学ぶ。
+ +

存在や値のセレクター

+ +

これらのセレクターにより、要素を属性が存在するか (href など)、または属性の値に対して様々な方法で一致させて選択できるようになります。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクター説明
[attr]a[title]attr という属性名を持つ要素と一致します。 — 値を角括弧の中に入れます。
[attr=value]a[href="https://example.com"]attr という属性名で値が value と完全一致する要素と一致します。— 文字列は引用符の中に入れます。
[attr~=value]p[class~="special"] +
値が正確に value である attr の属性名を持つ要素、または1つ以上の値を含む attr 属性を持つ要素に一致します。
+ +
+ +
複数の値のリストでは、個別の値が空白で区切られていることに注意してください。
+
[attr|=value]div[lang|="zh"]値が正確に value であるか、または value の直後にハイフンが続く値で始まる attr 属性を持つ要素にマッチします。
+ +

以下の例では、これらのセレクタが使用されていることがわかります。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/selectors/attribute.html", '100%', 800)}}

+ +

部分文字列一致セレクター

+ +

これらのセレクタは、属性の値の中の部分文字列をより高度にマッチさせることができます。例えば、 box-warningbox-error のクラスがあり、文字列 "box-" で始まるものを全てマッチさせたい場合、 [class^="box-"] を使用して両方を選択することができます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクター説明
[attr^=value]li[class^="box-"]値が value で始まる attr 属性(名前は角括弧内の値)を持つ要素とマッチします。
[attr$=value]li[class$="-box"] +
値が value で終わる attr 属性を持つ要素にマッチします。
+
[attr*=value]li[class*="box"]文字列内の任意の場所に value を含む attr 属性を持つ要素にマッチします。
+ +

次の例は、これらのセレクタの使用法を示しています。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-substring.html", '100%', 800)}}

+ +

大文字・小文字の区別

+ +

属性値を大文字小文字を区別せずにマッチさせたい場合は、閉じ括弧の前に値 i を使うことができます。このフラグは、ブラウザにASCII文字を大文字小文字を区別せずにマッチさせるように指示します。このフラグがない場合、値は文書言語の大文字小文字の区別に従ってマッチされます - HTMLの場合は大文字小文字を区別します。

+ +

以下の例では、最初のセレクタは a で始まる値にマッチします。他の 2 つのリスト項目は大文字の A で始まるため、最初のリスト項目にのみマッチします。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-case.html", '100%', 800)}}

+ +
+

:新しい値 s もあります。これは、通常大文字と小文字が区別されないコンテキストで大文字と小文字を区別するマッチングを強制しますが、これはブラウザではあまりサポートされておらず、HTMLコンテキストではあまり役に立ちません。

+
+ +

やってみよう

+ +

下のライブの例では、属性セレクタを使ったCSSを追加して以下のようにします。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-links.html", '100%', 800)}}

+ +
+

: ここで解答を見ることができますが、まずは自分で考えてみてください。

+
+ +

次のステップ

+ +

これで属性セレクターが完了しました。次の記事に進んで、pseudo-class and pseudo-element selectorsについて読むことができます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}

+ +

このモジュール内の文書

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と境界
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し (オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/selectors/combinators/index.html b/files/ja/learn/css/building_blocks/selectors/combinators/index.html new file mode 100644 index 0000000000..309d54b4cc --- /dev/null +++ b/files/ja/learn/css/building_blocks/selectors/combinators/index.html @@ -0,0 +1,118 @@ +--- +title: 結合子 +slug: Learn/CSS/Building_blocks/Selectors/Combinators +tags: + - Beginner + - CSS + - Learn + - Selectors + - combinators +translation_of: Learn/CSS/Building_blocks/Selectors/Combinators +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks")}}

+ +

ここで取り上げる最後のセレクターは、他のセレクターと、ドキュメント内のコンテンツの場所や場所との有用な関係を提供する方法で組み合わせるため、コンビネーターと呼ばれます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:CSS で使用できるさまざまな結合子セレクターについて学ぶ。
+ +

子孫コンビネーター

+ +

子孫コンビネーター(通常は単一のスペース( )文字で表される)は、2つのセレクターを結合して、最初のセレクターと一致する祖先(親、親の親、親の親の親など)要素がある場合、2番目のセレクターと一致する要素が選択されるようにします。 子孫コンビネーターを利用するセレクターは、子孫セレクターと呼ばれます。

+ +
body article p
+
+ +

これらのセレクターは、他のセレクターの子孫である要素を選択します。それらは一致するように直接の子供である必要はありません。

+ +

以下の例では、要素の内部にある <p> 要素のみを .box クラスと照合しています。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/descendant.html", '100%', 500)}}

+ +

子コンビネーター

+ +

子コンビネーターは、大なり記号( > )であり、セレクターが直接の子である要素を選択した場合にのみ一致します。階層のさらに下の子孫は一致しません。例えば、<article> 要素の直接の子である <p> 要素のみを選択するには:

+ +
article > p
+ +

次の例では、順序付けられていないリストがあり、その中にネストされているのは別の順序付けられていないリストです。子コンビネータを使用して、<ul> の直接の子である <li> 要素のみを選択し、上部の境界線を設定しています。

+ +

これを子コンビネーターとして指定している > を削除すると、子孫セレクターになり、すべての <li> 要素に赤い境界線が表示されます。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/child.html", '100%', 600)}}

+ +

隣接する兄弟

+ +
隣接する兄弟セレクター( + )は、階層の同じレベルにある別の要素のすぐ隣にある場合に選択します。例えば、<p> 要素の直後に来るすべての <img> 要素を選択するには:
+ +
p + img
+ +

一般的な使用例は、以下の私の例のように、見出しに続く段落で何かを行うことです。ここでは、<h1> に直接隣接する段落を探し、スタイルを設定しています。

+ +

<h1><p> の間に <h2> のような他の要素を挿入すると、段落がセレクタによってマッチしなくなり、要素が隣接しているときに適用される背景色と前景色が得られなくなることに気づくでしょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/adjacent.html", '100%', 800)}}

+ +

一般的な兄弟

+ +

要素が直接隣接していなくても、その要素の兄弟を選択したい場合は、一般的な兄弟コンビネーター( ~ )を使うことができます。<p> 要素の後のどこかに来る <img> 要素をすべて選択するには、次のようにします。

+ +
p ~ img
+ +
以下の例では、<h1> の後に続くすべての <p> 要素を選択しています。また、ドキュメントに <div> がある場合でも、その後にある <p> が選択されています。
+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/general.html", '100%', 600)}}

+ +

コンビネーターの使用

+ +

ドキュメントの一部を選択するために、前のレッスンで発見したセレクタをコンビネータと組み合わせることができます。 たとえば、<ul> の直接の子であるクラス "a"のリストアイテムを選択する場合、次のように使用できます。

+ +
ul > li[class="a"]  {  }
+ +

ただし、文書の特定の部分を選択する大きなセレクタのリストを作成する際には注意が必要です。マークアップの中でその要素の位置を特定してセレクタを作成しているので、CSS ルールを再利用するのは難しいでしょう。

+ +

多くの場合、単純なクラスを作成し、それを問題の要素に適用する方が適切です。つまり、ドキュメント内の何かにアクセスする必要があり、HTMLにアクセスできない場合、おそらくCMSによって生成されているために、コンビネーターに関する知識は非常に役立ちます。

+ +

あなたのスキルをテストしてみてください!

+ +

この記事では多くのことを取り上げましたが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストがいくつかあります - あなたのスキルをテストするを参照してください。Test your skills: Selectors を参照してください。

+ +

先へ

+ +

これは、セレクターに関するレッスンの最後のセクションです。次に、CSSのもう1つの重要な部分であるCSSボックスモデルに進みます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/selectors/index.html b/files/ja/learn/css/building_blocks/selectors/index.html new file mode 100644 index 0000000000..4ca0ff88db --- /dev/null +++ b/files/ja/learn/css/building_blocks/selectors/index.html @@ -0,0 +1,233 @@ +--- +title: CSS セレクター +slug: Learn/CSS/Building_blocks/Selectors +tags: + - Attribute + - Beginner + - CSS + - Class + - Learn + - Pseudo + - Selectors + - id +translation_of: Learn/CSS/Building_blocks/Selectors +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}
+ +

{{Glossary("CSS")}}では、ウェブページ上の {{glossary("HTML")}} 要素にスタイルを設定するためにセレクターが使用されます。CSS セレクターにはさまざまな種類があり、きめ細かにスタイルを設定する要素を選択できます。この記事とそのサブ記事では、さまざまなタイプについて、どのように機能するかを詳しく見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本 (HTML 入門) および CSS に関するアイデア (CSS の第一歩) に関する基本的な知識を得ている。
目的:CSS セレクターがどのように機能するかを学ぶ。
+ +

セレクターとは

+ +

実はもうこれまでにセレクターを見たことがあるはずです。CSS セレクターは、CSS のもっとも基本的なルールとなるものです。要素やその他を選択して CSS プロパティ値を適用する HTML 要素をブラウザーに伝えるものです。セレクターによって選択される要素は、選択対象 (subject of the selector) と呼ばれます。

+ +

Some code with the h1 highlighted.

+ +

これまでの記事で h1 要素や .special クラスなどのいくつかのセレクターを見てきました。それらはドキュメント内の対象をさまざまな方法で指定できるということも学びました。

+ +

"CSS セレクター仕様" (CSS Selectors specification) で、CSS のセレクターは定義されています。CSS の他の部分と同様に、それらが機能するにはブラウザーでのサポートが必要です。よく使うセレクターは確定仕様である Level 3 Selectors specification で定義されているため、ブラウザーサポートも期待できます。

+ +

セレクター一覧

+ +

同じ CSS を使用するものが複数ある場合は、セレクターリストでまとめてルールを適用することができます。たとえば、h1.special クラスが同じ CSS だとして、2 つの個別のルールとして記述できます。

+ +
h1 {
+  color: blue;
+}
+
+.special {
+  color: blue;
+} 
+ +

カンマ区切りでセレクターリストにもできます。

+ +
h1, .special {
+  color: blue;
+} 
+ +

カンマの前後に空白を入れることもできますし、改行したほうがセレクターを見つけやすくなり読みやすいかもしれません。

+ +
h1,
+.special {
+  color: blue;
+} 
+ +

以下のライブサンプルを使って、同じ宣言を持つ 2 つのセレクターを結合してみてください。作業の前後で見た目が同じになるように留意してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/selector-list.html", '100%', 1000)}} 

+ +

この方法でセレクターをグループ化していると、無効なセレクターがある場合はルール全体が無視されます。

+ +

以下の例では無効なセレクターは無視され、h1 だけがスタイル適用されます。

+ +
h1 {
+  color: blue;
+}
+
+..special {
+  color: blue;
+} 
+ +


+ ただし結合した場合は、h1 もクラスも無効なものとしてスタイルされません。

+ +
h1, ..special {
+  color: blue;
+} 
+ +

セレクターの種類

+ +

セレクターにはいくつかの異なるグループがあり、どれが必要かを知ることは有用です。ここのサブ記事ではさまざまなセレクターグループを詳しく見ていきます。

+ +

要素・クラス・ID によるセレクター

+ +

このグループには <h1> のような HTML 要素を対象とするセレクターを含みます。

+ +
h1 { }
+ +

同様にクラスを対象としたセレクターも含みます。

+ +
.box { }
+ +

あとは ID です。

+ +
#unique { }
+ +

属性によるセレクター

+ +

このセレクターグループは要素の属性によるさまざまな選択方法を提供します。

+ +
a[title] { }
+ +

特定の値を持つ属性で選択することもできます。

+ +
a[href="https://example.com"] { }
+ +

擬似クラスおよび疑似要素によるセレクター

+ +

このセレクターグループは、要素の特定の状態をスタイルする疑似クラスを含みます。たとえば、:hover 擬似クラスはマウスポインターがホバーしているときにのみ要素を選択します。

+ +
a:hover { }
+ +

また要素自体ではなく要素の特定の部分を選択する擬似要素もあります。たとえば、::first-line は要素 (以下では <p>) 内の最初の行をまるで <span> でラップしてスタイルしたかのように動作します。

+ +
p::first-line { }
+ +

結合子

+ +

最後のセレクターグループは、セレクターを組み合わせて文書内のターゲット要素を選びます。たとえば、以下では子コンビネータ (>) によって <article> 要素の直接の子である段落を選択します。

+ +
article > p { }
+ +

次のステップ

+ +

この記事や MDN にあるさまざまなセレクターについては、下の方にある表を参照してください。または、要素・クラス・ID によるセレクターから見ていくこともできます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}

+ +

セレクターのリファレンス表

+ +

以下の表で使用可能な各セレクターの概要と、それぞれの使い方を示すガイド内ページへのリンクを紹介します。そこには各セレクターのブラウザーサポートを確認できる MDN ページへのリンクもあります。セレクターを検索したり一般的に CSS を体験するときに、ここに戻ってきて参照することができます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクターCSS チュートリアル
要素セレクターh1 {  }要素セレクター
全称セレクター* {  }全称セレクター
クラスセレクター.box {  }クラスセレクター
ID セレクター#unique { }ID セレクター
属性セレクターa[title] {  }属性によるセレクター
擬似クラスセレクターp:first-child { }疑似クラス
疑似要素セレクターp::first-line { }疑似要素
子孫結合子article p子孫結合子
子結合子article > p子結合子
隣接兄弟結合子h1 + p隣接兄弟
一般兄弟結合子h1 ~ p一般兄弟
+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し (オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/selectors/pseudo-classes_and_pseudo-elements/index.html b/files/ja/learn/css/building_blocks/selectors/pseudo-classes_and_pseudo-elements/index.html new file mode 100644 index 0000000000..ea84d45c2b --- /dev/null +++ b/files/ja/learn/css/building_blocks/selectors/pseudo-classes_and_pseudo-elements/index.html @@ -0,0 +1,397 @@ +--- +title: 疑似クラスと疑似要素 +slug: Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements +translation_of: Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}

+ +

次に取り上げるセレクターのセットは、疑似クラス疑似要素と呼ばれます。これらは多数あり、多くの場合、それらは非常に特定の目的に役立ちます。それらの使用方法がわかったら、リストを見て、達成しようとしているタスクに有効なものがあるかどうかを確認できます。ここでも、各セレクターに関連するMDNページは、ブラウザーサポートの説明に役立ちます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータリテラシー、インストールされている基本的なソフトウェア、ファイルの操作に関する基本的な知識、HTMLの基本(HTMLの概要を学ぶ)、CSSのしくみ(CSSの最初のステップを学ぶ)。
目的:疑似クラスおよび疑似要素セレクターについて学習します。
+ +

疑似クラスとは何ですか?

+ +

疑似クラスは、特定の状態にある要素を選択するセレクターです。たとえば、それらはそのタイプの最初の要素であるか、マウスポインターによってホバーされています。それらは、ドキュメントの一部にクラスを適用したかのように振る舞う傾向があり、マークアップの余分なクラスを削減し、より柔軟で保守可能なコードを提供するのに役立ちます。

+ +

疑似クラスは、コロンで始まるキーワードです。

+ +
:疑似クラス名
+ +

単純な疑似クラスの例

+ +

簡単な例を見てみましょう。以下の最初の例に示すように、記事の最初の段落を大きく太字にしたい場合は、その段落にクラスを追加してから、そのクラスにCSSを追加できます。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/first-child.html", '100%', 800)}}

+ +

ただし、これを維持するのは面倒な場合があります。ドキュメントの上部に新しい段落が追加された場合はどうなりますか?クラスを新しい段落に移動する必要があります。クラスを追加する代わりに、{{cssxref(":first-child")}} 疑似クラスセレクターを使用できます。これにより、常に記事の最初の子要素がターゲットになり、HTMLを編集する必要がなくなります(これは、CMSによって生成された可能性があるため、とにかく常に可能であるとは限りません。)

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/first-child2.html", '100%', 700)}}

+ +

すべての疑似クラスは、この同じ方法で動作します。特定の状態にあるドキュメントの一部をターゲットにして、HTMLにクラスを追加したかのように動作します。MDNの他の例をいくつか見てみましょう。

+ + + +

ユーザーアクション疑似クラス

+ +

一部の疑似クラスは、ユーザーが何らかの方法でドキュメントを操作したときにのみ適用されます。これらのユーザーアクションの疑似クラスは、動的疑似クラスと呼ばれることもあり、ユーザーが要素を操作したときに、要素にクラスが追加されたかのように動作します。例は次のとおりです。

+ + + +

{{EmbedGHLiveSample("css-examples/learn/selectors/hover.html", '100%', 500)}}

+ +

疑似要素とは何ですか?

+ +

疑似要素は同様に動作しますが、既存の要素にクラスを適用するのではなく、まったく新しいHTML要素をマークアップに追加したかのように動作します。疑似要素はダブルコロンで始まり :: ます。

+ +
::疑似要素名
+ +
+

:一部の初期の疑似要素では、単一のコロン構文が使用されていたため、コードまたは例でこれを見ることがあるでしょう。最新のブラウザは、後方互換性のためにシングルまたはダブルコロン構文で初期の疑似要素をサポートしています。

+
+ +

たとえば、段落の最初の行を選択する場合は、それを <span> 要素にラップして要素セレクターを使用できます。ただし、ラップした単語の数が親要素の幅よりも長いまたは短い場合は、失敗します。1行にいくつの単語が収まるかわからない傾向があるため(画面の幅やフォントサイズが変わると、単語数が変わるため)、HTMLを追加してこれを確実に行うことは不可能です。

+ +

::first-line 擬似要素セレクタは確実にあなたのためにこれを行います-それはまだ最初の行のみを選択します言葉の数が増加した場合と減少します。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/first-line.html", '100%', 800)}}

+ +

それはまるで最初のフォーマットされた行を <span> で魔法のように包み、行の長さが変更されるたびに更新されるかのように動作します。

+ +

これにより、両方の段落の最初の行が選択されていることがわかります。

+ +

疑似クラスと疑似要素を組み合わせる

+ +

最初の段落の最初の行を太字にしたい場合は :first-child::first-line セレクターとセレクターをチェーンすることができます。前のライブ例を編集して、次のCSSを使用するようにしてください。<article>要素内にある最初の <p> 要素の最初の行を選択したいと言っています。

+ +
 article p:first-child::first-line {
+  font-size: 120%;
+  font-weight: bold;
+}
+ +

:: beforeおよび:: afterを使用したコンテンツの生成

+ +

CSSを使用してコンテンツをドキュメントに挿入するための content プロパティと共に使用される特別な疑似要素がいくつかあります。

+ +

以下のライブ例のように、これらを使用してテキストの文字列を挿入できます。{{cssxref("content")}} プロパティのテキスト値を変更してみて、出力でそれを確認してください。 ::before 疑似要素を ::after に変更して、要素の最初ではなく最後に挿入されたテキストを表示することもできます。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/before.html", '100%', 400)}}

+ +

CSSからテキストの文字列を挿入することは、実際にはWebで頻繁に行うことではありません。そのテキストは一部のスクリーンリーダーにはアクセスできず、将来誰かが見つけて編集するのが難しい場合があるためです。

+ +

これらの疑似要素のより有効な使用法は、アイコンを挿入することです。たとえば、以下の例で追加された小さな矢印は、スクリーンリーダーで読みたくない視覚的なインジケーターです。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/after-icon.html", '100%', 400)}}

+ +

これらの疑似要素は、空の文字列を挿入するためにも頻繁に使用され、ページ上の要素と同じようにスタイルを設定できます。

+ +

次の例では、 ::before 疑似要素を使用して空の文字列を追加しています。幅と高さでスタイルを設定できるように、これを display: block に設定しました。次に、CSSを使用して、他の要素と同じようにスタイルを設定します。CSSをいじって、CSSの外観と動作を変更できます。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/before-styled.html", '100%', 500)}}

+ +

content プロパティとともに ::before::after 擬似要素を使用することは、CSSでは「生成されたコンテンツ」と呼ばれ、この手法がさまざまなタスクに使用されているのをよく目にします。良い例は、CSS Arrow Please Pleaseのサイトで、CSSで矢印を生成するのに役立ちます。矢印を作成するときにCSSを見ると、{{cssxref("::before")}} および {{cssxref("::after")}} 疑似要素が使用されていることがわかります。これらのセレクターが表示されたら、{{cssxref("content")}} プロパティを見て、ドキュメントに何が追加されているかを確認してください。

+ +

参照セクション

+ +

疑似クラスと疑似要素は多数あり、参照するリストがあると便利です。以下に、MDNのリファレンスページへのリンクとともに、それらをリストした表を示します。これをリファレンスとして使用して、ターゲットにできるものの種類を確認します。

+ +

疑似クラス

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクタ説明
{{cssxref(":active")}}ユーザーが要素をアクティブ化(たとえばクリック)すると一致します。
{{cssxref(":any-link")}}リンクの :link:visited 状態の両方に一致します。
{{cssxref(":blank")}}入力値が空の<input> 要素に一致します。
{{cssxref(":checked")}}選択状態のラジオボタンまたはチェックボックスに一致します。
{{cssxref(":current")}}現在表示されている要素または要素の祖先と一致します。
{{cssxref(":default")}}類似要素のセットの中でデフォルトである1つ以上のUI要素に一致します。
{{cssxref(":dir")}}方向性(HTML dir 属性またはCSS direction プロパティの値)に基づいて要素を選択します。
{{cssxref(":disabled")}}無効な状態のユーザーインターフェイス要素に一致します。
{{cssxref(":empty")}}オプションの空白以外の子を持たない要素に一致します。
{{cssxref(":enabled")}}有効な状態のユーザーインターフェイス要素に一致します。
{{cssxref(":first")}}ページ媒体では、最初のページと一致します。
{{cssxref(":first-child")}}兄弟の中で最初にある要素に一致します。
{{cssxref(":first-of-type")}}兄弟の中で最初にある特定のタイプの要素に一致します。
{{cssxref(":focus")}}要素にフォーカスがあるときに一致します。
{{cssxref(":focus-visible")}}要素にフォーカスがあり、そのフォーカスがユーザーに表示される場合に一致します。
{{cssxref(":focus-within")}}フォーカスを持つ要素と、フォーカスを持つ子孫を持つ要素に一致します。
{{cssxref(":future")}}現在の要素の後の要素に一致します。
{{cssxref(":hover")}}ユーザーが要素にカーソルを合わせると一致します。
{{cssxref(":indeterminate")}}値が不確定な状態のUI要素、通常はチェックボックスに一致します
{{cssxref(":in-range")}}範囲制限を持つ要素で、要素の値が範囲内にある場合にマッチします。
{{cssxref(":invalid")}}無効な状態の <input> のような要素に一致します。
{{cssxref(":lang")}}言語(HTML lang属性の値)に基づいて要素を照合します。
{{cssxref(":last-child")}}兄弟の中で最後にある要素に一致します。
{{cssxref(":last-of-type")}}兄弟の中で最後にある特定のタイプの要素に一致します。
{{cssxref(":left")}}ページ媒体では、左側のページと一致します。
{{cssxref(":link")}}未訪問のリンクに一致します。
{{cssxref(":local-link")}}現在のドキュメントと同じサイトにあるページを指すリンクに一致します。
{{cssxref(":is", ":is()")}}渡されたセレクターリスト内の任意のセレクターに一致します。
{{cssxref(":not")}}このセレクターに値として渡されるセレクターで一致しないものと一致します。
{{cssxref(":nth-​​child")}}兄弟のリストの要素に一致します — 兄弟はan+bの形式の式で一致します(たとえば、2n + 1は1、3、5、7番目などの要素に一致します。すべてが奇数です)。
{{cssxref(":nth-​​of-type")}}特定のタイプの兄弟( <p> 要素など)のリストの要素に一致します — 兄弟は、an+bという形式の式で一致します(たとえば、2n + 1は、その要素のタイプの1、3、5 、7番目などに一致します。すべて奇数です。)
{{cssxref(":nth-​​last-child")}}兄弟のリストの要素を末尾から逆に数えて一致させます。兄弟はan+bの形式の式で一致します(たとえば、2n + 1はシーケンスの最後の要素、次にその2つ前の要素、次にその2つ前の要素などと一致します。最後から数えてすべての奇数の要素。)
{{cssxref(":nth-​​last-of-type")}}特定のタイプの兄弟のリスト( <p> 要素など)の要素を最後から逆に数えて一致させます。兄弟は、an+bという形式の式で一致します(たとえば、2n + 1は、シーケンス内のそのタイプの最後の要素、次にその2つ前の要素、次にその2つ前の要素などと一致します。最後から数えてすべての奇数の要素。)
{{cssxref(":only-child")}}兄弟がない要素に一致します。
{{cssxref(":only-of-type")}}兄弟間でそのタイプの唯一の要素である要素に一致します。
{{cssxref(":optional")}}不要なフォーム要素に一致します。
{{cssxref(":out-of-range")}}範囲制限を持つ要素で、要素の値が範囲外にある場合にマッチします。
{{cssxref(":past")}}現在の要素より前の要素に一致します。
{{cssxref(":placeholder-shown")}}プレースホルダーテキストを表示しているinput要素に一致します。
{{cssxref(":playing")}}「再生」または「一時停止」できるオーディオ、ビデオ、または類似のリソースを表す要素が「再生中」のときに一致します。
{{cssxref(":paused")}}「再生」または「一時停止」できるオーディオ、ビデオ、または類似のリソースを表す要素が「一時停止」されている場合に一致します。
{{cssxref(":read-only")}}ユーザーが変更できない要素と一致します。
{{cssxref(":read-write")}}ユーザーが変更可能な要素と一致します。
{{cssxref(":required")}}必要なフォーム要素に一致します。
{{cssxref(":right")}}ページ媒体では、右側のページに一致します。
{{cssxref(":root")}}ドキュメントのルートである要素に一致します。
{{cssxref(":scope")}}スコープ要素であるすべての要素に一致します。
{{cssxref(":valid")}}<input> 要素などで要素が有効な状態のときに一致します。
{{cssxref(":target")}}現在のURLのターゲットである場合(つまり、現在のURLフラグメントに一致するIDを持つ場合)、要素に一致します
{{cssxref(":visited")}}訪問したリンクに一致します。
+ +

疑似要素

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクタ説明
{{cssxref("::after")}}元の要素の実際のコンテンツの後に現れるスタイル可能な要素と一致します。
{{cssxref("::before")}}元の要素の実際のコンテンツの前に現れるスタイル可能な要素と一致します。
{{cssxref("::first-letter")}}要素の最初の文字と一致します。
{{cssxref("::first-line")}}含まれている要素の最初の行と一致します。
{{cssxref("::grammar-error")}}ブラウザによってフラグが立てられた文法エラーを含むドキュメントの一部に一致します。
{{cssxref("::marker")}}通常は箇条書きまたは番号が含まれているリストアイテムのマーカーボックスに一致します。
{{cssxref("::selection")}}選択されたドキュメントの部分に一致します。
{{cssxref("::spelling-error")}}ブラウザによってフラグが付けられた、スペルミスを含むドキュメントの一部に一致します。
+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}

+ +

このモジュールでは

+ +
    +
  1. カスケードと継承
  2. +
  3. CSSセレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. 異なるテキスト方向の処理
  10. +
  11. あふれるコンテンツ
  12. +
  13. 値と単位
  14. +
  15. CSSでのアイテムのサイズ変更
  16. +
  17. 画像、メディア、フォーム要素
  18. +
  19. スタイリングテーブル
  20. +
  21. CSSのデバッグ
  22. +
  23. CSSの整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/selectors/type_class_and_id_selectors/index.html b/files/ja/learn/css/building_blocks/selectors/type_class_and_id_selectors/index.html new file mode 100644 index 0000000000..8f1bbbfaad --- /dev/null +++ b/files/ja/learn/css/building_blocks/selectors/type_class_and_id_selectors/index.html @@ -0,0 +1,126 @@ +--- +title: 要素・クラス・ID によるセレクター +slug: Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors +tags: + - Beginner + - CSS + - Class + - Learn + - Selectors + - Syntax + - id + - universal +translation_of: Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks")}}

+ +

このレッスンでは、利用できる最も簡単にみえるセレクタをとりあげます。これは今後あなたが作業でよく使うことになります。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:CSS をドキュメントに適用するためのさまざまな CSS セレクタについて学ぶ。
+ +

タイプセレクタ

+ +

タイプセレクタタグ名セレクタまたは要素セレクタを参照します。これはあなたのドキュメント中のタグまたは要素を選択するからです。次の例で span, em それに strong セレクタを使用します。そのため <span>, <em><strong> の要素はスタイル修飾されます。

+ +

CSS ルールを追加して <h1> 要素を選択してその色を青に変えましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/type.html", '100%', 1100)}}

+ +

ユニバーサルセレクタ

+ +

ユニバーサルセレクタはアステリスク (*) で表します。またこれはドキュメントのすべてまたは親要素に含まれるすべての要素( これはそれが連なっている、他の要素やそれらの子要素に連なっている要素すべて) を選択します。次の例ではすべての要素から margin を削除しています。これはブラウザーによって追加されたデフォルトのスタイルの代りに、章立てやパラグラフの margin を消してそれぞれを近く配置させます。これにより個々のパラグラフが見分けがつかなくなってしまいます。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/universal.html", '100%', 750)}}

+ +

この種類の動作はしばしば「スタイルシートのリセット」と呼び、ブラウザーのスタイル設定を取り消します。ユニバーサルセレクタはグローバルな変更をもたらすため、下記に述べる特定の状況のみに使うべきです。

+ +

ユニバーサルセレクタを使用してセレクタの可読性をあげる

+ +

ユニバーサルセレクタの使用方法のひとつに、セレクタを読みやすくし、その動作を明かにするのものがあります。例えば、<article> 要素の最初の子要素を選択し、それがどんな要素であったとしてもそれを太字にしたいとします。これには{{cssxref(":first-child")}} セレクタを使うことができます。これはあとの疑似クラスと疑似要素のコースで詳細を学びますが、<article> 要素セレクタの後ろで指定します。

+ +
article :first-child {
+
+}
+ +

しかしこれは、article:first-child と混同しかねません。これは他の要素の第一子要素の<article> 要素を選択してしまうのです。

+ +

この混乱を避けるために、:first-child にユニバーサルセレクタを追加します。これで何を選択しているかが明らかです。<article> 要素の第一子要素にあたるすべての要素を選択しています。

+ +
article *:first-child {
+
+} 
+ +

クラスセレクタ

+ +

クラスセレクタの名前はピリオド (.) から始まります。そしてそのクラスが適用されている、ドキュメント内のすべてを選択します。次の例では、.highlight というクラスを作成し、ドキュメントのいくつかの場所に適用します。このクラスが適用されたすべての要素をハイライトします。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/class.html", '100%', 750)}}

+ +

特定の要素のクラスを対象にする

+ +

特定のクラスが適用された特定の要素を対象にするセレクタを作成できます。次の例では、highlight クラスの <span> をハイライトしますが、highlight クラスの <h1> 見出しを異なるようにハイライトします。対象にしたい要素にタイプセレクタを使用して実現できます。ドットの後にクラスを追加しますが、クラスとの間にホワイトスペースをいれません。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/class-type.html", '100%', 750)}}

+ +

このアプローチでは、ルールが特定の要素とクラスの組み合わせにのみ適用されるため、ルールの範囲が狭くなります。そのため、ルールを他の要素にも適用したい場合は、別のセレクタを追加する必要があります。

+ +

複数のクラスが適用された要素を対象にする

+ +

一つの要素に複数のクラスを適用できます。それらを個別に選択することも、すべてのクラスがあるものだけを選択することもできます。これは、サイト上で様々な方法で組み合わせることができるコンポーネントを構築する際に便利です。

+ +

次の例は、ノートのある <div> です。灰色の境界はそのボックスが notebox クラスもっている場合にのみ適用されます。もしそれが warningdanger クラスも持っていた場合 {{cssxref("border-color")}} を変更します。

+ +

ブラウザーに、2 つのクラスが存在する要素だけ一致するように指定するには、それらのクラスをすべて空白を入れずに繋げて指定します。最後の <div> には danger クラスがあるだけなので、適用されるスタイルはありません。

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/class-many.html", '100%', 900)}}

+ +

ID セレクタ

+ +

ID セレクタは ピリオドではなく # で始めますが、それ以外は基本的にクラスセレクタと同じです。しかし ID はそのドキュメントの名にはただ一度しか使用できません。ID セレクタはその id が設定されている要素を選択します。要素と ID の両方に一致するものだけを対象にする場合、ID セレクタをタイプセレクタの前に置くことができます。これを次の例で確認しましょう。:

+ +

{{EmbedGHLiveSample("css-examples/learn/selectors/id.html", '100%', 750)}}

+ +
+

: このレッスンの特例で学んだように ID は非常に特別なもので、他のセレクタを上書きすることがあります。これは対応が難しくなることがあります。多くの場合、ID を使用する代りにクラスを追加するほうが望ましいです。しかしその要素を対象にする方法が ID を使うしかないような場合、例えばそのマークアップにあなたがアクセスできず、編集できないような場合、この方法を使用できます。

+
+ +

次の記事

+ +

属性セレクタ によるセレクタを調べます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクタ + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/sizing_items_in_css/index.html b/files/ja/learn/css/building_blocks/sizing_items_in_css/index.html new file mode 100644 index 0000000000..80909093b3 --- /dev/null +++ b/files/ja/learn/css/building_blocks/sizing_items_in_css/index.html @@ -0,0 +1,139 @@ +--- +title: CSS によるサイズ設定 +slug: Learn/CSS/Building_blocks/Sizing_items_in_CSS +tags: + - Beginner + - CSS + - Intrinsic size + - Learn + - max size + - min size + - percentage + - sizing + - viewport units +translation_of: Learn/CSS/Building_blocks/Sizing_items_in_CSS +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks")}}
+ +

これまでのさまざまなレッスンで、CSS を使用してウェブページ上のアイテムのサイズを調整するいくつかの方法に出会いました。デザイン作業をしていくうえで、それぞれの手法がどれほど大事かを理解することが重要です。このレッスンでは、CSS によって要素のサイズを設定する方法をまとめ、サイジングに役立ついくつかの用語を定義します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:CSS によるさまざまなサイズ設定の方法を理解する。
+ +

要素固有のサイズ

+ +

HTML要素には自然なサイズがあり、CSSの影響を受ける前に設定されます。簡単な例は画像です。画像には、ページに埋め込む画像ファイルで定義された幅と高さがあります。このサイズは固有のサイズと呼ばれ、画像自体に由来します。

+ +

<img> タグまたはCSSの属性を使用してページに画像を配置し、その高さと幅を変更しない場合、その固有のサイズを使用して表示されます。以下の例では、ファイルの範囲を確認できるように画像に境界線を付けています。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/intrinsic-image.html", '100%', 600)}}

+ +

ただし、空の {{htmlelement("div")}} には独自のサイズはありません。コンテンツのないHTMLに {{htmlelement("div")}} を追加し、画像で行ったように境界線を付けると、ページに線が表示されます。これは、要素の折りたたまれた境界線です。開いたままにするコンテンツはありません。以下の例では、その境界線はコンテナの幅まで伸びています。これはブロックレベルの要素であるため、慣れ親しんだ動作になるはずです。コンテンツがないため、高さ(またはブロックディメンションのサイズ)はありません。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/intrinsic-text.html", '100%', 500)}}

+ +

上記の例では、空の要素内にテキストを追加してみてください。要素の高さがコンテンツによって定義されているため、境界線にはそのテキストが含まれています。したがって、<div> ブロックディメンションにおけるこのサイズは、コンテンツのサイズに由来します。繰り返しますが、これは要素の固有のサイズです。そのサイズはコンテンツによって定義されます。

+ +

サイズの指定

+ +

もちろん、デザインの要素に特定のサイズを与えることもできます。要素にサイズが指定されている場合(およびそのコンテンツがそのサイズに収まる必要がある場合)、それを外部サイズと呼びます。上記の例の <div> を見てみます。特定の {{cssxref("width")}} と {{cssxref("height")}} の値を指定できるため、そ コンテンツがどのように配置されても、そのサイズになります。 前のオーバーフローに関するレッスンで見たように、要素の中に収まるスペースよりも多くのコンテンツがある場合、高さを設定するとコンテンツがオーバーフローする可能性があります。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/height.html", '100%', 600)}}

+ +

このオーバーフローの問題のため、要素の高さを長さまたはパーセンテージで固定することは、Web上で非常に注意深く行う必要があります。

+ +

比率指定

+ +

多くの点で、パーセンテージは長さの単位のように機能し、値と単位に関するレッスンで説明したように、多くの場合、長さと同じ意味で使用できます。パーセンテージを使用している場合、あなたはそれが何に対する比率であるかを認識する必要があります。別のコンテナー内のボックスの場合、子ボックスに幅のパーセンテージを与えると、親コンテナーの幅のパーセンテージになります。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/percent-width.html", '100%', 600)}}

+ +

これは、パーセンテージがそれを包含するブロックのサイズに対して解決されるためです。パーセンテージを適用しない <div> 場合、これはブロックレベルの要素であるため、使用可能なスペースの100%を占めます。パーセンテージの幅を指定すると、これは通常埋められるスペースに対するの比率になります。

+ +

マージンとパディングの比率

+ +

パーセンテージとして marginspadding を設定すると、奇妙な動作に気付く場合があります。以下の例では、ボックスがあります。内部ボックスに10%の {{cssxref("margin")}} と10%の {{cssxref("padding")}} を与えました。ボックスの上下の padding と margin は、左右の margin と同じサイズです。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/percent-mp.html", '100%', 700)}}

+ +

例えば、上下のマージンのパーセンテージは要素の高さのパーセンテージであり、左右のマージンのパーセンテージは要素の幅のパーセンテージであると予想するかもしれません。しかし、そうではありません。

+ +

マージンとパディングをパーセンテージで設定する場合、値はインラインサイズから計算されます。したがって横書きの言語で作業するときの幅になります。この例では、マージンとパディングはすべて幅の10%です。つまり、ボックス全体で同じサイズのマージンとパディングを使用できます。この方法でパーセンテージを使用する場合、これは覚えておかなければならない事実です。

+ +

最小サイズ、最大サイズ

+ +

固定サイズを与えることに加えて、要素に最小サイズまたは最大サイズを与えるようCSSに要求できます。さまざまな量のコンテンツを含む可能性のあるボックスがあり、常に特定の高さ以上にしたい場合は、そのボックスに {{cssxref("min-height")}} プロパティを設定できます。ボックスは常にこの高さ以上になりますが、ボックスの最小高さでのスペースよりも多くのコンテンツがある場合は、ボックスの高さが高くなります。

+ +

以下の例では、2つのボックスがあり、どちらも150ピクセルの高さが定義されています。左側のボックスの高さは150ピクセルです。右側のボックスには、より多くのスペースを必要とするコンテンツがあるため、150ピクセルよりも高くなっています。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/min-height.html", '100%', 800)}}

+ +

これは、オーバーフローを回避しながら、可変量のコンテンツを処理するのに非常に役立ちます。

+ +

{{cssxref("max-width")}} の一般的な用途は、固有の幅で表示するための十分なスペースがない場合に画像を縮小し、その幅よりも大きくならないようにすることです。

+ +

例として、画像に width: 100% を設定する場合、その固有の幅がコンテナーよりも小さいと、画像は強制的に引き伸ばされて大きくなり、ピクセル化されたように見えます。固有の幅がコンテナーよりも大きい場合、オーバーフローします。どちらの場合も、あなたが起こりたいことではないでしょう。

+ +

代わりに max-width: 100% を使用すると、画像は本来のサイズよりも小さくなりますが、サイズの100%で止まります。

+ +

以下の例では、同じ画像を2回使用しています。最初の画像には width: 100% が指定されており、それよりも大きいコンテナー内にあるため、コンテナーの幅まで拡大されます。2番目の画像には max-width: 100% が設定されているため、コンテナを埋めるために引き伸ばされることはありません。3番目のボックスにも同じ画像が含まれており、 max-width: 100% も設定されています。この場合、ボックスに収まるように縮小された様子を確認できます。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/max-width.html", '100%', 800)}}

+ +

この手法は、画像をレスポンシブにするために使用されます。そのため、より小さなデバイスで表示すると、適切に縮小されます。ただし、この手法を使用して非常に大きな画像を読み込んでから、ブラウザで縮小するべきではありません。画像は、デザインに表示される最大サイズに必要なサイズよりも大きくならないように適切なサイズにするべきです。大きすぎる画像をダウンロードすると、サイトが遅くなり、ユーザーが従量制の接続を使用している場合は、より多くの費用がかかる可能性があります。

+ +
+

レスポンシブ画像技術の詳細をご覧ください。

+
+ +

ビューポートに関する単位

+ +

ビューポート(サイトの表示に使用しているブラウザーでのページの表示領域)にもサイズがあります。CSSには、ビューポートのサイズに関連する単位(ビューポートの幅 vw とビューポートの高さ vh )があります。これらの単位を使用すると、ユーザーのビューポートを基準にしてサイズを変更できます。

+ +

1vh はビューポートの高さの1%に等しく、1vw はビューポートの幅の1%に等しい。これらの単位を使用して、ボックスだけでなくテキストのサイズも変更できます。以下の例では、20vh と 20vw のサイズのボックスがあります。ボックスには、 {{cssxref("font-size")}} が 10vh の文字 A が含まれています。

+ +

{{EmbedGHLiveSample("css-examples/learn/sizing/vw-vh.html", '100%', 600)}}

+ +

vh との vw 値を変更すると、ボックスまたはフォントのサイズが変更されます。ビューポートに相対的なサイズであるため、ビューポートのサイズを変更しても、サイズが変更されます。ビューポートのサイズを変更したときにサンプルの変更を確認するには、サイズを変更できる新しいブラウザーウィンドウにサンプルを読み込む必要があります(上記の例を含む埋め込み <iframe> がビューポートであるため)。サンプルを開き、ブラウザウィンドウのサイズを変更して、ボックスとテキストのサイズがどうなるかを観察します。

+ +

ビューポートに応じてサイズを調整することは、デザインに役立ちます。例えば、全ページのヒーローセクション(hero section)を他のコンテンツの前に表示させたい場合、ページのその部分を100vhの高さにすると、残りのコンテンツはビューポートの下に押しやられてしまい、ドキュメントがスクロールされたときにのみ表示されます。

+ +

まとめ

+ +

このレッスンでは、Web上のサイズを決定するときに遭遇する可能性があるいくつかの重要な問題の概要を説明しました。CSSレイアウトに移ると、さまざまなレイアウトメソッドを習得する際にサイズ設定が非常に重要になるため、先に進む前に、ここで概念を理解しておくことをお勧めします。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/styling_tables/index.html b/files/ja/learn/css/building_blocks/styling_tables/index.html new file mode 100644 index 0000000000..9d3988ddf7 --- /dev/null +++ b/files/ja/learn/css/building_blocks/styling_tables/index.html @@ -0,0 +1,316 @@ +--- +title: 表のスタイリング +slug: Learn/CSS/Building_blocks/Styling_tables +tags: + - Article + - Beginner + - CSS + - CodingScripting + - Guide + - Styling + - Tables +translation_of: Learn/CSS/Building_blocks/Styling_tables +--- +

{{LearnSidebar}}

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks/Debugging_CSS", "Learn/CSS/Building_blocks")}}

+ +
+ +

HTML 表を装飾することは、世界で最も魅力的な仕事ではありませんが、時にはそれをしなければならないこともあります。 この記事では、これまでに説明した機能のいくつかとともに、HTML 表を見栄え良くするためのガイドを提供します。

+ + + + + + + + + + + + +
前提条件:HTML の基本(HTML 入門)と HTML 表 および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。
目的:HTML 表を効果的に装飾する方法を学ぶ。
+ +

典型的な HTML 表

+ +

典型的な HTML 表を見ることから始めましょう。 まあ、典型的な言い方ですが、ほとんどの HTML 表の例は、靴、天気、あるいは従業員に関するものです。 私達はイギリスの有名なパンクバンドについてそれを作ることで、もっと面白くすることにしました。 マークアップはこんな感じです。

+ +
<table>
+  <caption>A summary of the UK's most famous punk bands</caption>
+  <thead>
+    <tr>
+      <th scope="col">Band</th>
+      <th scope="col">Year formed</th>
+      <th scope="col">No. of Albums</th>
+      <th scope="col">Most famous song</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <th scope="row">Buzzcocks</th>
+      <td>1976</td>
+      <td>9</td>
+      <td>Ever fallen in love (with someone you shouldn't've)</td>
+    </tr>
+    <tr>
+      <th scope="row">The Clash</th>
+      <td>1976</td>
+      <td>6</td>
+      <td>London Calling</td>
+    </tr>
+
+      ... 簡潔にするためにいくつかの行を削除
+
+    <tr>
+      <th scope="row">The Stranglers</th>
+      <td>1974</td>
+      <td>17</td>
+      <td>No More Heroes</td>
+    </tr>
+  </tbody>
+  <tfoot>
+    <tr>
+      <th scope="row" colspan="2">Total albums</th>
+      <td colspan="2">77</td>
+    </tr>
+  </tfoot>
+</table>
+ +

{{htmlattrxref("scope","th")}}、{{htmlelement("caption")}}、{{htmlelement("thead")}}、{{htmlelement("tbody")}} などの機能のおかげで、表はうまくマークアップされ、簡単に装飾を整えられ、アクセスしやすくなりました。 残念なことに、画面に表示したときは見栄えがよくありません(punk-bands-unstyled.html でライブを見る)。

+ +

+ +

それは窮屈に見え、読みにくく、そして退屈です。 これを修正するために CSS を使用する必要があります。

+ +

テーブルのスタイリング

+ +

テーブルの例を一緒にスタイリングしてみましょう。

+ +
    +
  1. まず始めに、サンプルマークアップのローカルコピーを作成し、noiseleopardskin の両方の画像をダウンロードして、3つのファイルをローカルコンピュータのどこかの作業ディレクトリに配置します。
  2. +
  3. 次に、style.css という名前の新しいファイルを作成し、他のファイルと同じディレクトリに保存します。
  4. +
  5. {{htmlelement("head")}} の内側に次の HTML 行を配置して、CSS を HTML にリンクします。 +
    <link href="style.css" rel="stylesheet" type="text/css">
    +
  6. +
+ +

スペーシングとレイアウト

+ +

最初にすべきことは、スペーシングやレイアウトを整理することです — デフォルトの表の装飾はとても窮屈です! これを行うには、style.css ファイルに次の CSS を追加します。

+ +
/* spacing */
+
+table {
+  table-layout: fixed;
+  width: 100%;
+  border-collapse: collapse;
+  border: 3px solid purple;
+}
+
+thead th:nth-child(1) {
+  width: 30%;
+}
+
+thead th:nth-child(2) {
+  width: 20%;
+}
+
+thead th:nth-child(3) {
+  width: 15%;
+}
+
+thead th:nth-child(4) {
+  width: 35%;
+}
+
+th, td {
+  padding: 20px;
+}
+ +

注意すべき最も重要な部分は次のとおりです。

+ + + +

この時点で、表はすでにずっと良く見えています。

+ +

+ +

簡単なタイポグラフィ

+ +

それでは、テキストを少し整理しましょう。

+ +

まず第一に、パンクバンドについての表にふさわしいフォントを Google Fonts で見つけてあります。 望むならそこに行って、別なものを探すことができます。私たちが提供する {{htmlelement("link")}} 要素とカスタムの {{cssxref("font-family")}} 宣言を Google Fonts が与えるものと置き換えるだけです。

+ +

まず、HTML head の既存の {{htmlelement("link")}} 要素のすぐ上に、次の <link> 要素を追加します。

+ +
<link href='https://fonts.googleapis.com/css?family=Rock+Salt' rel='stylesheet' type='text/css'>
+ +

そして、style.css ファイルの以前の追加の下に、次の CSS を追加します。

+ +
/* typography */
+
+html {
+  font-family: 'helvetica neue', helvetica, arial, sans-serif;
+}
+
+thead th, tfoot th {
+  font-family: 'Rock Salt', cursive;
+}
+
+th {
+  letter-spacing: 2px;
+}
+
+td {
+  letter-spacing: 1px;
+}
+
+tbody td {
+  text-align: center;
+}
+
+tfoot th {
+  text-align: right;
+}
+ +

ここに表に固有のものは何もありません。 読みやすくするために、次のようにフォントの装飾を調整しています。

+ + + +

結果は少しきれいに見えます。

+ +

+ +

グラフィックスと色

+ +

今度はグラフィックと色です! 表はパンクとその態度でいっぱいですので、それに合わせていくつかの明るい印象的な装飾を与える必要があります。 心配しないで、表をそんなに騒々しくする必要はありません — もっと微妙で上品な何かを選ぶことができます。

+ +

次の CSS を style.css ファイルの一番下に再び追加してください。

+ +
thead, tfoot {
+  background: url(leopardskin.jpg);
+  color: white;
+  text-shadow: 1px 1px 1px black;
+}
+
+thead th, tfoot th, tfoot td {
+  background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.5));
+  border: 3px solid purple;
+}
+
+ +

繰り返しますが、ここでは表に固有のものは何もありませんが、いくつか注意することは価値があります。

+ +

{{htmlelement("thead")}} と {{htmlelement("tfoot")}} に {{cssxref("background-image")}} を追加し、ヘッダー内とフッター内のすべてのテキストの {{cssxref("color")}} を白に変更して(そして {{cssxref("text-shadow")}} を指定して)読みやすくしています。 読みやすいように、テキストが背景と比べてコントラストがあるようにしてください。

+ +

また、ヘッダー内とフッター内の {{htmlelement("th")}} 要素と {{htmlelement("td")}} 要素に線形グラデーションを追加して、テクスチャをきれいにし、それらの要素に明るい紫色の境界線を付けました。 複数のネストした要素を使用できるようにしておくと、スタイルを重ね合わせることができます。 はい、複数の背景画像を使用して {{htmlelement("thead")}} 要素と {{htmlelement("tfoot")}} 要素に背景画像と線形グラデーションの両方を配置することもできましたが、複数の背景画像や線形グラデーションをサポートしない古いブラウザーの利点のために別々に行うことにしました。

+ +

ゼブラストライピング

+ +

ゼブラストライプ(zebra stripes)を実装する方法を示すために別のセクションを捧げたいと思います — 表のさまざまなデータ行を解析して読みやすくするために、行の色を交互に並べます。 style.css ファイルの一番下に次の CSS を追加します。

+ +
tbody tr:nth-child(odd) {
+  background-color: #ff33cc;
+}
+
+tbody tr:nth-child(even) {
+  background-color: #e495e4;
+}
+
+tbody tr {
+  background-image: url(noise.png);
+}
+
+table {
+  background-color: #ff33cc;
+}
+ + + +

この色の爆発により、以下のような見た目になります。

+ +

+ +

さて、これはあなたの好みではなく、少々限度を超えているかもしれませんが、ここで主張しようとしているのは、表が退屈で学術的である必要はないということです。

+ +

キャプションの装飾

+ +

表でやるべきことがもう一つあります — キャプションの装飾です。 これを行うには、style.css ファイルの一番下に次のコードを追加します。

+ +
caption {
+  font-family: 'Rock Salt', cursive;
+  padding: 20px;
+  font-style: italic;
+  caption-side: bottom;
+  color: #666;
+  text-align: right;
+  letter-spacing: 1px;
+}
+ +

{{cssxref("caption-side")}} プロパティに、bottom の値が与えられている以外に、ここで注目に値するものは何もありません。 これにより、キャプションは表の下に配置され、他の宣言と共にこの最終的な外観が得られます(punk-bands-complete.html でライブで見る)。

+ +

+ +

表の装飾のちょっとした助言

+ +

先に進む前に、上に示した最も有用なポイントの簡単なリストをお送りします。

+ + + +

あなたのスキルをテストしてください!

+ +

この記事では多くの情報を取り上げましたが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストをいくつか見つけることができます。Test your skills: tables を参照してください。

+ +

まとめ

+ +

テーブルのスタイリングも終わりに近づいてきたので、他にも何か時間を割くものが必要になってきました。次の記事では、CSS をデバッグする方法を探ります。レイアウトが思うように見えない、プロパティが適用されないなどの問題を解決する方法です。これには、ブラウザの DevTools を使用して問題を解決する方法についての情報も含まれています。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks/Debugging_CSS", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/the_box_model/index.html b/files/ja/learn/css/building_blocks/the_box_model/index.html new file mode 100644 index 0000000000..aca49d9dd1 --- /dev/null +++ b/files/ja/learn/css/building_blocks/the_box_model/index.html @@ -0,0 +1,343 @@ +--- +title: ボックスモデル +slug: Learn/CSS/Building_blocks/The_box_model +tags: + - Beginner + - CSS + - Learn + - border + - box model + - display + - margin + - padding +translation_of: Learn/CSS/Building_blocks/The_box_model +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks")}}
+ +

CSS にはボックスの概念があり、これを理解することは CSS でレイアウトを作成したりアイテム同士を揃えたりするためのコツとなります。このレッスンでは CSS ボックスモデルを詳しく解説し、その仕組みと関連する用語を理解することでより複雑なレイアウトができるようにします。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本 (HTML 入門) および CSS に関するアイデア (CSS の第一歩) に関する基本的な知識を得ている。
目的:CSS のボックスモデルとその構成要素、代替モデルへの切り替えについて学ぶ。
+ +

ブロックボックスとインラインボックス

+ +

CSS には、ブロックボックスインラインボックスの 2 種類のボックスがあります。これらの特性は、ページフローの観点から、およびページ上の他のボックスとの関係でボックスがどのように動作するかを示します。

+ +

ボックスがブロックとして定義されている場合、次のように動作します:

+ + + +

表示タイプをインラインに変更することを決定しない限り、デフォルトでは見出し (例: <h1>) や <p> などの要素はすべて外部表示タイプとして block を使用します。

+ +

ボックスの外側の表示タイプが inline の場合:

+ + + +

リンクに使用される <a> 要素や、<span><em> および <strong> はすべて、デフォルトではインラインで表示される要素の例です。

+ +

要素に適用されるボックスのタイプは、blockinline などの {{cssxref("display")}} プロパティ値によって定義され、display外側の値に関連します。

+ +

余談: 内側と外側の表示タイプ

+ +

この時点で、内側外側の表示タイプについても説明するべきでしょう。上記のように、CSS のボックスには外側の表示タイプがあり、ボックスがブロックかインラインかを詳細に示します。

+ +

ただし、ボックスには内部表示タイプもあり、これにより、そのボックス内の要素のレイアウト方法が決まります。デフォルトでは、ボックス内の要素は通常のフローでレイアウトされます。つまり、他のブロック要素やインライン要素と同じように動作します(上記で説明したように)。

+ +

ただし、flex などの display の値を使用して、内部の表示タイプを変更できます。要素に display: flex; を設定する場合、外側の表示タイプは block ですが、内側の表示タイプは flex に変更されます。このボックスの直接の子要素はすべてフレックスアイテムになり、Flexbox 仕様で規定されているルールに従ってレイアウトされます。これについては後で学習します。

+ +
+

注:ディスプレイの値、およびブロックおよびインラインレイアウトでのボックスの動作の詳細については、ブロックおよびインラインレイアウトに関する MDN ガイドを参照してください。  

+
+ +

CSS レイアウトについてさらに詳しく学習すると、flex や、例えば grid のようなボックスに設定できる他のさまざまな内部の値と出会うでしょう。

+ +

ただし、ブロックおよびインラインレイアウトは、ウェブ上のデフォルトの動作です。前述のように、通常のフローと呼ばれることもあります。他の指示がない場合、ボックスはブロックまたはインラインボックスとしてレイアウトされるためです。

+ +

さまざまな表示タイプの例

+ +

次に進み、いくつかの例を見てみましょう。以下に、3 つの異なる HTML 要素があります。これらはすべて、外部表示タイプの block を持っています。1 つ目は段落で、CSS で border が追加されています。ブラウザーはこれを block box としてレンダリングするため、段落は新しい行で始まり、利用可能な全幅に拡張されます。

+ +

2 番目はリストで、これは display:flex を使用してレイアウトされます。これにより、コンテナ内のアイテムのフレックスレイアウトが確立されますが、リスト自体は block boxであり、段落と同様に、container の幅いっぱいに拡張され、新しい行に分割されます。

+ +

この下にブロックレベルの段落があり、その中に 2 つの <span> 要素があります。通常、これらの要素は inline ですが、要素の 1 つにブロックのクラスがあり、display: block に設定しました。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/block.html", '100%', 1000)}}

+ +

この次の例では、inline 要素の動作を確認できます。最初の段落の <span> はデフォルトではインラインのため、強制的に改行しません。

+ +

また、display: inline-flex に設定された <ul> 要素があり、一部の flex アイテムの周りにインラインボックスを作成します。

+ +

最後に、display: inline に設定された 2 つの段落があります。inline flex container と段落はすべて、ブロックレベルの要素として表示されている場合のように新しい行に分割されるのではなく、1 行で一緒に実行されます。

+ +

この例では、display: inlinedisplay: block に、またはdisplay: inline-flexdisplay: flex に変更して、これらの表示モードの間を切り替えられます。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/inline.html", '100%', 1000)}}

+ +

これらのレッスンの後半では、フレックスレイアウトなどの問題と出会います。現時点で覚えておくべき重要な点は、display プロパティの値を変更すると、ボックスの外側の表示タイプがブロックかインラインかを変更できるため、レイアウト内の他の要素と一緒に表示する方法が変わることです。

+ +

レッスンの残りの部分では、外側のディスプレイタイプに集中します。

+ +

CSS のボックスモデルとは?

+ +

完全な CSS ボックスモデルはブロックボックスに適用され、インラインボックスはボックスモデルで定義された動作の一部のみを使用します。 モデルは、ボックスのさまざまな部分 (マージン、ボーダー、パディング、コンテンツ) がどのように連携してページに表示できるボックスを作成するかを定義します。 さらに複雑さを追加するために、標準および代替ボックスモデルがあります。

+ +

ボックスの構成

+ +

CSSでブロックボックスを構成するには、次のものがあります。

+ + + +

以下の図は、これらのレイヤーを示しています:Diagram of the box model

+ +

CSS ボックスモデルの標準

+ +

標準のボックスモデルでは、ボックスに widthheight を指定すると、コンテンツボックスの幅と高さが定義されます。 次に、すべての padding と border がその幅と高さに追加され、ボックスが占める合計サイズが取得されます。 これを下の画像に示します。

+ +

ボックスに widthheightmarginborder および padding を定義する次の CSS があると仮定した場合:

+ +
.box {
+  width: 350px;
+  height: 150px;
+  margin: 25px;
+  padding: 25px;
+  border: 5px solid black;
+}
+
+ +

標準のボックスモデルを使用してボックスが占めるスペースは、実際には 410px (350 + 25 + 25 + 5 + 5) で、高さは 210px (150 + 25 + 25 + 5 + 5) であり、padding と border は コンテンツボックスに使用される幅に追加されます。Showing the size of the box when the standard box model is being used.

+ +
+

注: マージンは、ボックスの実際のサイズにはカウントされません。確かに、ボックスがページ上で占める合計スペースに影響しますが、ボックスの外側のスペースにのみ影響します。ボックスの領域は境界線で停止します—マージンまでは達しません。

+
+ +

CSS ボックスモデルの代替

+ +

ボックスの実際のサイズを取得するために border と padding を追加する必要があるのはかなり不便だと思うかもしれませんが、正しい感覚でしょう!このため、CSS には、標準ボックスモデルのしばらく後に導入された代替ボックスモデルがありました。このモデルを使用すると、幅はページ上の表示ボックスの幅になるため、コンテンツ領域の幅は、その幅からパディングとボーダーの幅を引いたものになります。上記と同じ CSS を使用すると、以下の結果が得られます (幅 = 350px、高さ = 150px)。

+ +

Showing the size of the box when the alternate box model is being used.

+ +

デフォルトでは、ブラウザーは、標準のボックスモデルを使用します。もし要素に対して代替モデルをオンにしたい場合は、box-sizing: border-box を設定することでそうできます。これにより、設定した任意のサイズで定義された領域として境界ボックスを取るようにブラウザーに指示しています。

+ +
.box {
+  box-sizing: border-box;
+} 
+ +

すべての要素で代替ボックスモデルを使用することを望み、かつこれが開発者の間で一般的な選択である場合、以下のスニペットで見られるように、<html> 要素で box-sizing プロパティを設定して、他のすべての要素でその値を継承するように設定してください。この背景にある考え方を理解したい場合は、ボックスサイズ設定に関する CSS トリックの記事を参照してください。

+ +
html {
+  box-sizing: border-box;
+}
+*, *::before, *::after {
+  box-sizing: inherit;
+}
+ +
+

: 興味深い歴史 — Internet Explorer は以前は代替ボックスモデルにデフォルト設定されていましたが、切り替え可能なメカニズムはありませんでした。

+
+ +

ボックスモデルを試してみる

+ +

以下の例では、2 つのボックスを見ることができます。両方とも .box のクラスを持ち、同じ widthheightmarginborder、およびpadding を提供します。唯一の違いは、2 番目のボックスが代替ボックスモデルを使用するように設定されていることです。

+ +

2 番目のボックスのサイズを変更 (.alternate クラスに CSS を追加) して、幅と高さを最初のボックスに一致させることはできますか?

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/box-models.html", '100%', 1000)}}

+ +
+

: ここでこのタスクの解決策を見つけることができます。

+
+ +

ブラウザーの開発ツールを利用して、ボックスモデルを見てみる

+ +

ブラウザー開発ツールを使用すると、ボックスモデルをとても簡単に理解できます。Firefox の DevTools で要素を調べると、要素のサイズに加えて、margin、padding、border を確認できます。 この方法で要素を検査することは、あなたのボックスが本当にあなたが思っているサイズであるかどうかを知る素晴らしい方法です!

+ +

Inspecting the box model of an element using Firefox DevTools

+ +

Margins、padding および borders

+ +

上記の例では、{{cssxref ("margin") }}、{{cssxref ("padding") }} および{{cssxref ("border") }} のプロパティが動作しているのを見てきました。 この例で使用されるプロパティは shorthands であり、ボックスの 4 辺すべてを一度に設定できます。これらの shorthands には、同等の longhand プロパティもあり、ボックスのさまざまな側面を個別に制御できます。

+ +

これらのプロパティをさらに詳しく見てみましょう。

+ +

マージン

+ +

マージンは、ボックスの周りの見えないスペースです。 他の要素をボックスから遠ざけます。 マージンには正または負の値を設定できます。 ボックスの片側に負のマージンを設定すると、ページ上の他の部分と重なる場合があります。 標準または代替のボックスモデルを使用しているかどうかにかかわらず、表示ボックスのサイズが計算された後、マージンは常に追加されます。

+ +

{{cssxref ("margin") }} プロパティを使用して要素のすべてのマージンを一度に制御するか、同等の longhand properties を使用して各辺を個別に制御できます。

+ + + +

次の例では、マージン値を変更して、この要素と含まれる要素の間のスペース (負のマージンの場合) を作成または削除するマージンのためにボックスがどのように押し出されるかを確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/margin.html", '100%', 1000)}}

+ +

マージンの相殺

+ +

マージンについて理解する重要なことは、マージンの相殺の概念です。 マージンが接する 2 つの要素が あり、両方のマージンが正の場合、それらのマージンは結合して 1 つのマージンになります。これは、個々のマージンのうちの最大サイズです。一方または両方のマージンが負の場合、負の値の量が合計から差し引かれます。

+ +

以下の例では、2 つの段落があります。 上の段落には、50 ピクセルの margin-bottom があります。2 番目の段落の margin-top は 30 ピクセルです。マージンは一緒に折りたたまれているため、ボックス間の実際のマージンは 50 ピクセルであり、2 つのマージンの合計ではありません。

+ +

これをテストするには、第二段落の margin-top を 0 に設定します。2 つの段落間のマージンは変更されません。第一段落の margin-bottom に設定された 50 ピクセルを保持します。-10pxに設定すると、全体のマージンが40pxになることがわかります— 50pxから差し引かれます。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/margin-collapse.html", '100%', 1000)}}

+ +

マージンが相殺される場合と相殺されない場合を規定する多くのルールがあります。 詳細については、マージンの相殺に関する詳細ページをご覧ください。現時点で覚えておくべき主なことは、マージンの相殺が起こることです。マージンによるスペースを作成していて、期待したスペースが得られない場合、おそらくこれが起こっています。

+ +

Borders

+ +

border は、ボックスの margin と padding の間に描かれます。標準ボックスモデルを使用している場合、border のサイズがボックスの widthheight に追加されます。代替ボックスモデルを使用している場合、border のサイズが利用可能な widthheight の一部を占めるため、コンテンツボックスが小さくなります。

+ +

border のスタイル設定には、多数のプロパティがあります。4 つの border があり、各 border には、操作したいスタイル、width、color があります。

+ +

{{cssxref("border")}} プロパティを使用して、4 つすべての border の width、color およびスタイルを一度に設定できます。

+ +

各辺のスタイルを個別に設定するには、次を使用できます:

+ + + +

すべての辺の幅、スタイル、色を設定するには、次を使用します:

+ + + +

片側の色、スタイル、または width を設定するには、最もきめ細かい longhand プロパティのいずれかを使用できます:

+ + + +

以下の例では、さまざまなショートハンドとロングハンドを使用して border を作成しています。 さまざまなプロパティを試して、それらがどのように機能するか理解していることを確認してください。border プロパティの MDN ページには、選択可能なさまざまな border スタイルに関する情報が表示されます。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/border.html", '100%', 1000)}}

+ +

パディング

+ +

padding は、border とコンテンツ領域の間にあります。margin とは異なり、負の量の padding はできないため、値は 0 または正の値でなければなりません。要素に適用された背景は padding の背後に表示され、通常は border からコンテンツ遠ざけるために使用されます。

+ +

{{cssxref("padding")}} プロパティを使用して要素の各側の padding を個別に制御するか、同等のロングハンドプロパティを使用して各側を個別に制御できます。

+ + + +

以下の例で .box クラスの padding の値を変更すると、ボックスに関連してテキストの開始位置が変わることがわかります。

+ +

.container クラスの padding を変更することもできます。これにより、container とボックスの間にスペースができます。padding は任意の要素で変更でき、border と要素内にあるものとの間にスペースを作ります。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/padding.html", '100%', 800)}}

+ +

ボックスモデルとインラインボックス

+ +

上記のすべては、ブロックボックスに完全に適用されます。一部のプロパティは<span> 要素によって作成されたものなどの、インラインボックスにも適用できます。

+ +

以下の例では、段落内に <span> があり、widthheightmarginborder および padding が適用されています。width と height が無視されていることがわかります。マージン、パディング、ボーダーは尊重されますが、他のコンテンツとインラインボックスの関係は変わらないため、パディングとボーダーは段落内の他の単語と重なります。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/inline-box-model.html", '100%', 800)}}

+ +

display: inline-block を使用する

+ +

display には特別な値があり、inlineblock の中間に位置するものを提供します。これは、アイテムを新しい行に分割したくないが、widthheight を尊重し、上記の上書きを避けたい場合に便利です。

+ +

display: inline-block を持つ要素は、私たちがすでに知っているブロックのサブセットを実行します:

+ + + +

ただし、新しい行に分割されることはなく、width プロパティと height プロパティを明示的に追加した場合にのみ、コンテンツよりも大きくなります。

+ +

次の例では、<span> 要素に display: inline-block を追加しました。これを display: block 変更したり、行を完全に削除したりして、表示モデルの違いを確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/inline-block.html", '100%', 800)}}

+ +

これが役立つのは、padding を追加して、リンクのヒット領域を大きくしたい場合です。<a><span> のようなインライン要素です。 display:inline-block を使用して padding を設定できるようにし、ユーザーがリンクをクリックしやすくします。

+ +

これはナビゲーションバーにかなり頻繁に表示されます。以下のナビゲーションは、flexbox を使用して行に表示され、<a> にカーソルを合わせたときに背景色を変更できるように、<a> 要素に padding を追加しました。paddingは、<ul> 要素の border に重なるように見えます。これは、<a>がインライン要素であるためです。

+ +

display: inline-block.links-list a セレクターを使用してルールに追加すると、padding が他の要素によって尊重されるようにすることで、この問題がどのように修正されるかがわかります。

+ +

{{EmbedGHLiveSample("css-examples/learn/box-model/inline-block-nav.html", '100%', 600)}}

+ +

まとめ

+ +

以上が、ボックスモデルについて理解する必要があるほとんどのことです。レイアウト内の大きなボックスの大きさについて混乱している場合は、このレッスンに戻ってください。

+ +

次のレッスンでは背景とボーダーを使用してプレーンボックスをより面白くする方法を見ていきます。

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し (オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/building_blocks/values_and_units/index.html b/files/ja/learn/css/building_blocks/values_and_units/index.html new file mode 100644 index 0000000000..1ebb091ee2 --- /dev/null +++ b/files/ja/learn/css/building_blocks/values_and_units/index.html @@ -0,0 +1,407 @@ +--- +title: CSS の値と単位 +slug: Learn/CSS/Building_blocks/Values_and_units +tags: + - Beginner + - CSS + - Function + - Image + - Learn + - Number + - Position + - color + - length + - percentage + - units + - values +translation_of: Learn/CSS/Building_blocks/Values_and_units +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks")}}
+ +

CSS で使用されるすべてのプロパティには、特定の値または組み合わせのみが許可されており、MDN の各プロパティに関するページでは有効な値を理解するのに役立ちます。このレッスンでは、もっとも一般的な値と単位について見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS の動作概念(CSS の第一歩)に関する基本的な知識を得ている。
目的:CSS プロパティで使用されるさまざまな種類の値と単位について学ぶ。
+ +

CSS での値とは?

+ +

CSS の仕様や MDN のプロパティページでは、<color><length> のような角括弧で囲まれた値を見つけることができます。<color> の値がその特定のプロパティとして妥当なとき、ここではそのプロパティの妥当な色を表していることを意味しています。具体的な値は <color> のリファレンスページを参照してください。

+ +
+

: データタイプ を参照する CSS の値を確認しましょう。これは、基本的に交換可能です — データタイプとして参照する、CSS であなたが見るものは装飾のための値を示しています。

+
+ +
+

:  CSS の値は<>括弧で示すことが多く、CSS のプロパティによって違います(例えば{{cssxref("color")}} プロパティや <color> データタイプがあります)。CSS のデータタイプ型と HTML の要素は違いますので、混乱しないでください。両方とも<>括弧を使います — しかしそれらを使用するコンテキストは全く異なります。

+
+ +

次の例では、キーワードを使用して章立ての色を設定し、かつ背景色を rgb() 関数を使って指定します。:

+ +
h1 {
+  color: black;
+  background-color: rgb(197,93,161);
+} 
+
+ +

CSS の値は指定可能なサブ値の集合を定義します。これは、<color> が妥当な箇所では、異なる種類の色の値、キーワード、16進数、rgb() 関数などで設定できるかどうか考える必要はありません。あなたのブラウザーがサポートしていると仮定できる、あらゆる 利用可能な <color> の値が指定できます。MDN のページはそれぞれのブラウザーがサポートしている値の情報を提供します。例えば、<color> のページには、ブラウザーの互換性のセクションがあり、サポートされているそれぞれの種類を見られます。

+ +

ここでは見ることが多いいくつかのタイプの値や単位を確認しましょう。また例のさまざまな値を変えて試しましょう。

+ +

数値・長さ・割合

+ +

CSS では数値データ型をいくつかみるでしょう。次のものは数値に分類されています。:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
データタイプ説明
<integer><integer> (整数)は、1024-55 のようなすべての整数です。
<number><number> (数)は 10進数です。小数点のあるものとないものがあります。例えば、0.255128-1.2 です。
<dimension><dimension> (寸法)は <number> に付属するものです。例えば、45deg, 5s, それに 10px です。<dimension> には <length> (長さ), <angle> (角度), <time> (時間), さらに <resolution> (解像度)型があります。.
<percentage><percentage> (パーセント)は他の値との割合を表します。例えば、50%. この値は常に他の量との相対比です。例えば、ある要素の長さは、その親要素の長さが関連しています。
+ +

Lengths(長さ)

+ +

数値型でもっともよく遭遇するのは、<length>です。例えば、10px (ピクセル) や 30em です。CSS で使用される長さの種類は二つに分けられます。relative(相対)と absolute(絶対)です。この違いを理解することは非常に重大です。

+ +

絶対長の単位

+ +

次の単位はすべて absolute length units(絶対的な長さの単位) です。この単位は、他の長さとの関係で決まりません。一般的にこの単位は常に同じサイズと考えられます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Unit名前換算
cmCentimeters センチメートル1cm = 96px/2.54
mmMillimeters ミリメートル1mm = 1/10 cm
QQuarter-millimeters 1/4 ミリメートル1Q = 1/40 1cm
inInches インチ1in = 2.54cm = 96px
pcPicas パイカ1pc = 1in の 1/6
ptPoints ポイント1pt = 1in の 1/72
pxPixels ピクセル1px =  1in の 1/96
+ +

これらの値は印刷には便利ですが、画面出力には向いていません。私たちは、スクリーン上の長さに、例えば cm (センチメートル)を使いません。よく使用するのは px (pixels/ピクセル)になります。

+ +

相対長の単位

+ +

Relative length units (相対的な長さの単位) は、何かとの比較によってサイズが決まります。それは、例えば、親要素のフォントサイズかもしれませんし、ビューポート(画面幅)かもしれません。この相対的な長さ単位はが便利なのは、それを作成するときにいくつかの点に注意して、そのページ内のテキストのサイズや他の要素の相対的なサイズで作成したときです。次の表にウェブ開発で便利な単位を紹介します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Unit関係先
em親要素のフォントサイズ.
exその要素のフォントの文字 "x" の高さ
chその要素のフォントの文字 "0" の幅
remルート要素のフォントサイズ
lhその要素の line-hight プロパティと同じ
vwビューポート幅の 1%
vhビューポート高さの 1%
vminビューポート幅と高さの小さい方の 1%
vmaxビューポート幅と高さの大きい方の 1%
+ +

試してみる

+ +

次の例で、絶対的な長さの単位と相対的な長さの単位の振る舞いの違いを確認しましょう。最初のボックスには {{cssxref("width")}} がピクセル単位で指定されています。 絶対単位なので、この幅は他の何が変わっても同じままです。

+ +

二番目のボックスは相対的な長さの単位の、ビューポート幅に関連した vw を使用しています。この値は、ビューポート幅と関連しており、10vw は ビューポート幅の 10% にあたります。もしブラウザー幅を変化させた場合、このボックスのサイズは変化します。しかし、このページは <iframe> に埋め込んであるため、次の例は動作しません。この動作を確認するには、このリンクをブラウザーの別タブで開いて、例を確認してください。

+ +

三番目のボックスは em 単位を使います。この単位はフォントサイズに関連しています。1em にあたるフォントサイズ設定は {{htmlelement("div")}}で指定してあります。これは.wrapper クラスがあります。 この値を1.5emに変更すると、すべての要素のフォントサイズが増加しますが、最後の項目のみ width がフォントサイズに相対的であるため、最後の項目のみが広くなります。

+ +

上の手順を行った後で、これらの値を変更してどのようにふるまうかを確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/length.html", '100%', 820)}}

+ +

em と rem

+ +

emrem は開発者がボックスやテキストまですべてのサイズを変更するときによく遭遇する相対的な長さの単位です。これらがどのように動作するか、どのように違いがあるかを理解しましょう。特にスタイルテキストCSS レイアウトのようなより複雑なテーマを扱うようになったときに価値があります。以下の例は、デモを提供しています。

+ +

この HTML はネストしたリストの組です。全部で 3 つのリストがあり、どちらも同じ HTML です。唯一異なるのは、最初のものは ems クラスを持っており、二つ目のものは rems クラスを持っていることです。

+ +

始めるにあたって、<html> 要素のフォントサイズを 16px に指定しました。

+ +

要約すると、em 単位は活字で言えば「私の親要素のフォントサイズ」を意味します。emsclass を持つ {{htmlelement("ul")}} 内の {{htmlelement("li")}} 要素は、親要素からサイズを受け取ります。そのため、入れ子の各レベルは、それぞれのフォントサイズが 1.3em (親のフォントサイズの1.3倍)に設定されているため、徐々に大きくなっていきます。

+ +

要約すると、この rem 単位は活字でいえば、「ルート要素のフォントサイズ」を意味します。(rem は"root em"を意味します) この remsclass を持つ {{htmlelement("ul")}} の内部の {{htmlelement("li")}} 要素はルート要素(<html>)からサイズ情報を取得します。 これは、ネストの各レベルが大きくなり続けないことを意味します。

+ +
ただし、CSSで <html>font-size を変更すると、その他のすべて( rem サイズと em サイズの両方のテキスト)が相対的に変更されることがわかります。
+ +
+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/em-rem.html", '100%', 1000)}} 

+ +

Percentages(パーセント)

+ +

多くの場合、percentage (パーセント)は length(長さ)と同じ方法で使用します。percentages のあるものは、ある他の値との相対的な値を設定します。例えば、あなたがある要素の font-size に percentage を設定した場合、その親要素の font-size のパーセントを意味します。もしある width の値に percentage を使用した場合、その親要素の width のパーセントに設定されます。

+ +

次の例では二つのパーセントでサイズ指定したボックスと、ピクセルでサイズ指定したボックスがあり、これらはそれぞれ同じクラス名を持っています。これは、それぞれ 200px と 40% の幅に設定されています。

+ +

ここで異なるのは、二番目のボックスは 400 ピクセル幅のラッパーの内側にあることです。200px で指定したボックスは、一番目と二番目が同じ幅になっています。しかし、二番目の 40%指定したボックスは違います。二番目のボックスは 400 ピクセルの 40% の幅になります。最初のものよりかなり狭くなっています。

+ +

ラップするボックスの幅またはパーセントの値を変更してその影響を確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/percentage.html", '100%', 850)}} 

+ +

次の例はフォントサイズをパーセントで指定しています。それぞれの <li> は 80% の font-size です。そのため、ネストしたリストはその親のサイズを継承するため、徐々にフォントサイズが小さくなっています。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/percentage-fonts.html", '100%', 650)}} 

+ +

注意: 多くの値には length(長さ) と percentage(パーセント)の両方を受け付けますが、中には length しか受け付けないものもあります。どのような値が受け付けられるかを確認するには、MDN プロパティリファレンスページを参照してください。許可される値が <length-percentage> の場合は length と percentage の両方を使用できます。しかし許可される値が <length> の場合、percentage は使用できません。

+ +

Numbers(数)

+ +

一部の値は、単位のない数値を受け入れます。 単位のない数値を受け入れるプロパティの例は、要素の不透明度(透明度)を制御する opacity プロパティです。 このプロパティは、0(完全に透明)〜 1(完全に不透明)の数値を受け入れます。

+ +

この下の例を見てください。opacity0 から 1 までの間の数に変えて、この箱とそのコンテンツがどのよう表示されるかを確認してください。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/opacity.html", '100%', 500)}} 

+ +
+

: CSS で値として数を使用する場合、その値を引用符で囲んではなりません。

+
+ +

+ +

CSS で色を指定する方法はたくさんありますが、その中には最近実装されたものもあります。テキストの色を指定する場合でも、背景の色を指定する場合でも、CSSではどこでも同じ色の値を使うことができます。

+ +

最近のコンピューターで利用できる標準的な色のシステムは 24 ビットです。これは赤、緑、青のチャンネルでそれぞれ 256 の値を持てるため、およそ 1670万色 (256 x 256 x 256 = 16,777,216) の色を指定できることになります。CSS で色を指定するさまざまな方法を見てみましょう。

+ +
+

: このチュートリアルでは、普通のブラウザーがサポートしている、標準的な色の指定方法を見ていきます。他にも方法がありますが、それらはサポートされていないこともあり、標準的な方法ではありません。

+
+ +

カラーキーワード

+ +

この学習の章や MDN でもよく例を見る方法にカラーキーワードがあります。これは色を指定する方法で非常に単純で理解しやすいものです。カラーキーワードは、その色の名前そのものを入力するだけです。このカラーキーワードのリストは <color> の値のページで確認できます。

+ +

下の練習で別のカラーキーワードを試して、それがどのように作用するのか確認してください。

+ +

16進数 RGB

+ +

次のカラーの値の種類は、あたながよく遭遇する 16進数を使うものです。それぞれの 16進数の値には、ハッシュ記号(#) に続いて、6 個の 16進数の数が続きます。この数には、0 から f までの 16 個の文字を使用します。(ここで f は 15 に相当) — つまり 0123456789abcdef を使用します。この値の二文字はそれぞれ赤、緑、青のカラーチャンネルの値を表しています。そのため、16 x 16 = 256 つまり、それぞれのチャンネルに 256通りの値を指定できます。

+ +

これらの値は少し複雑で、わかりにくいものです。しかし、16進数はキーワードより多くの用途で使用されます。あなたのカラースキームで表す、好きな色を 16進数で表現できるのです。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/color-hex.html", '100%', 700)}} 

+ +

もう一度、値を変更させてどのように色が変化するか確認しましょう。

+ +

RGB と RGBA

+ +

第三の方法として、RGB を説明します。RGB の値は関数 rgb() に渡して使います。この関数は、3 つのパラメータを受け取り、それぞれ、赤、緑、青のチャンネルの色の値として扱います。ちょうど 16進数での表記とよく似ています。RGB は 2 つの 16進数で表すのと違い 0 から 255 の 10進数の数で指定します。こちらの方が少しわかりやすいです。

+ +

最後の表記を書き直して、RGB で表現してみましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/color-rgb.html", '100%', 700)}} 

+ +

また、RGBA カラー方式もあります。これは、RGB カラー方式とまったく同じ方法で、RGB で表すすべての値を使用できます。しかし、RGBA は 4 つのパラメータをとり、4番目のパラメータは色のアルファチャンネル、つまり色の不透明度(または透明度)を表します。この 4番目のパラメータの値が  0 のとき完全な透明を表し、1 のとき完全な不透明を表します。その間の値を指定してさまざまなレベルの透明度を指定できます。

+ +
+

: 色でアルファチャンネルを設定することと、より前に学んだ、{{cssxref("opacity")}} プロパティで設定することの違いに注意しましょう。opacity プロパティで設定した場合、その要素と要素内のすべてが透明になります。一方、RGBA カラーを指定した場合、透明になるのはそのカラーだけです。

+
+ +

下記の例では、色付きの箱に含まれる背景画像を追加しました。そして箱にいろいろな透過値をセットしました — アルファチャンネルが小さくなるときに背景がどう表示されるか注意してみてください。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/color-rgba.html", '100%', 770)}}

+ +

この例では、アルファチャンネル値を変更してみて、色の出力にどう影響するのかを見ています。

+ +
+

: ある時点で、最新のブラウザが更新され、rgba() と rgb()、そして hsl() と hsla() (後述) がお互いの純粋なエイリアスとなり、全く同じ動作をするようになりました。このため rgba()rgb() の両方はアルファチャンネル値のある/ない色を受け入れています。上記の例の rgba() 関数を rgb() に変更して色が動作するのを見てください! どのスタイルを使うのかはあなた次第ですが、不透明と透明の色定義に別の関数を使うのは (とても) 少しブラウザーサポートが良くなって、コード内のどこで透明色を使っているかの目印になります。

+
+ +

HSL と HSLA

+ +

RGB よりサポートがちょっと少ないのが HSL 色モデルです (IE の古いバージョンではサポートされません)、これはデザイナーの関心から実装されました。赤、緑、青の代わりに、hsl() 関数は 色相(hue), 彩度(saturation), 輝度(lightness) の値を取り、これは約 1670 万色を、別の方法で分別するのに使われます。

+ + + +

RGB の例を HSL の色に更新すると次のようになります:

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/color-hsl.html", '100%', 700)}} 

+ +

RGB に RGBA があるように、HSL には同様な HSLA があり、アルファチャンネルの指定が同様にできます。デモとして RGBA の例を HSLA 色を使うようにしたものは次の通りです。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/color-hsla.html", '100%', 770)}} 

+ +

プロジェクトでどの色の値を使っても良いです。たいていのプロジェクトではカラーパレットを決めてから、この色(と決定した色指定の方法)を、プロジェクト全体を通して使います。色モデルを混用することもできますが、一貫させるために通常はプロジェクト全体で同じものを使うのがベストです!

+ +

画像

+ +

<image> データタイプは画像が妥当な値となる場合に使われます。これは url() 関数で指定される実際の画像ファイルか、グラデーションです。

+ +

下記の例では画像とグラデーションを CSS background-image プロパティに使っています。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/image.html", '100%', 740)}} 

+ +
+

: <image> がとり得る他の値もありますが、それは新しくてブラウザーサポートが貧弱です。それについて知りたい場合、MDN の <image> データタイプのページを確認してください。

+
+ +

位置

+ +

<position> データタイプは 2次元座標を表しており、背景画像のような項目 (background-position にて)の位置を決めるのに使われます。これは top, left, bottom, rightcenter のようなキーワードを取って、ボックスの上や左の隅からオフセットさせる長さの値とともに、2次元のボックスの特定の境界にアイテムを揃えます。

+ +

典型的な位置の値は 2 つの値を持ち — 最初は水平位置を、2 つ目は垂直位置をセットします。1 つの軸だけの値を指定する場合、もう 1 つはデフォルトで center となります。

+ +

次の例では、背景画像をキーワードを使ってコンテナの右端の上から 40px の位置に配置しています。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/position.html", '100%', 720)}} 

+ +

この値でいろいろ遊んでみて、画像がどう移動するか見てください。

+ +

文字列と識別子

+ +

上記の例を通じて、キーワードが値として使われる場所を見てきました (例えば、<color> キーワードの例として red, black, rebeccapurple, goldenrod)。このキーワードをより正確に述べると、CSS が理解できる特別な値の 識別子 です。このためそれは引用符で囲まれておらず、文字列として扱われません。

+ +

CSS で文字列が使われる場所もあります、例えば、生成されたコンテンツを指定するときです。この場合、値は文字列を示すようクォートで囲まれます。下記の例ではクォートで囲まれていない color キーワードと生成されたコンテンツ文字列を一緒に使っています。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/strings-idents.html", '100%', 550)}} 

+ +

関数

+ +

最後に見る値は関数として知られる値です。プログラミングでは、関数とは、繰り返されるタスクを実行するのに何度も呼ばれる、開発者とコンピューター両方の手間を省いてくれる、再利用できるコードの一部分です。関数は通常 JavaScript, Python, C++のような言語と関連付けられますが、CSS にもプロパティ値として存在しています。私たちはすでに色の節で rgb()hsl() などの関数を見ています。ファイルから画像を返すのに使われた値 — url() — も関数です。

+ +

従来のプログラミング言語にあるような動作をする値は CSS の calc() 関数です。この関数を使うと CSS 内で簡単な計算を行うことができます。特にプロジェクトの CSS を書く際に定義できない値を計算したい場合や、実行時にブラウザに計算させる必要がある場合に便利です。

+ +

例えば、下記では calc() を使って 20% + 100px の幅を出しています。20% は親コンテナである .wrapper の幅から計算され、その幅が変わると変更されます。親の 20% がいくらになるのか分からないので、この計算を事前にすることはできません。そのため代わりにブラウザーに計算してもらうよう calc() を使います。

+ +

{{EmbedGHLiveSample("css-examples/learn/values-units/calc.html", '100%', 450)}}

+ +

スキルをテストしましょう!

+ +

この記事では多くをカバーしましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Values and unit を見てください。

+ +

まとめ

+ +

ここまで最もよく見かける値と単位を一通り見てきました。CSS 値と単位 のリファレンスページで、さまざまなタイプをすべて見ることができます。多くはこのレッスンを進んでいくと出てくるでしょう。

+ +

覚えておくべき重要なことは、各プロパティには許可される値の定義されたリストがあり、各値にはサブ値が何であるかを説明する定義があるということです。詳細は MDN で調べることができます。

+ +

例えば、<image> でもカラーグラデーションを作成できることを理解しておくと便利ですが、たぶん当たり前の知識ではないでしょう!

+ +

{{PreviousMenuNext("Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks")}}

+ +

このモジュール

+ +
    +
  1. カスケードと継承
  2. +
  3. CSS セレクター + +
  4. +
  5. ボックスモデル
  6. +
  7. 背景と枠線
  8. +
  9. テキスト方向の操作
  10. +
  11. 要素のはみ出し(オーバーフロー)
  12. +
  13. CSS の値と単位
  14. +
  15. CSS によるサイズ設定
  16. +
  17. 画像・メディア・フォーム要素
  18. +
  19. 表のスタイリング
  20. +
  21. CSS のデバッグ
  22. +
  23. CSS の整理
  24. +
diff --git a/files/ja/learn/css/css_layout/flexbox/index.html b/files/ja/learn/css/css_layout/flexbox/index.html new file mode 100644 index 0000000000..688db60aec --- /dev/null +++ b/files/ja/learn/css/css_layout/flexbox/index.html @@ -0,0 +1,349 @@ +--- +title: フレックスボックス +slug: Learn/CSS/CSS_layout/Flexbox +tags: + - Article + - Beginner + - CSS + - CSS layouts + - CodingScripting + - Flexible Boxes + - Guide + - Layout + - Layouts + - Learn + - flexbox +translation_of: Learn/CSS/CSS_layout/Flexbox +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}
+ +

フレックスボックス(Flexbox)は、項目を行または列にレイアウトするための1次元のレイアウト方法です。 項目は追加のスペースを埋めるためにたわみ、小さいスペースに収まるように縮小します。 この記事では、すべての基本事項について説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:フレックスボックス・レイアウトシステムを使用してウェブのレイアウトを作成する方法を習得する。
+ +

なぜフレックスボックスなのか?

+ +

長い間、CSS レイアウトを作成するために利用可能な唯一の信頼できるクロスブラウザー互換ツールはフロート位置指定のようなものでした。 これらは問題なく機能しますが、いくつかの点ではかなり限定的でイライラするものです。

+ +

次のような単純なレイアウト要件は、このようなツールを使用しても、便利で柔軟な方法で実現するのが困難または不可能です。

+ + + +

以降のセクションで見るように、フレックスボックスは多くのレイアウト作業をずっと簡単にします。 さあ始めましょう!

+ +

簡単な例の紹介

+ +

この記事では、フレックスボックスがどのように機能するのかを理解するのに役立つ一連の演習を進めていくようにします。 まず始めに、github リポジトリから最初のスターターファイル flexbox0.html のローカルコピーを作成し、最新のブラウザー(Firefox や Chrome など)にロードして、コードエディタでコードを確認してください。 ここでもライブを見ることができます。

+ +

内部に最上位の見出しを持つ {{htmlelement("header")}} 要素と、3つの {{htmlelement("article")}} を含む {{htmlelement("section")}} 要素があります。 これらを使用して、かなり標準的な3列のレイアウトを作成します。

+ +

+ +

柔軟な箱としてレイアウトする要素を指定

+ +

まず最初に、どの要素を柔軟な箱(flexible box)としてレイアウトするかを選択する必要があります。 これを行うために、あなたが影響を与えたい要素の親要素に {{cssxref("display")}} の特別な値を設定します。 この場合、{{htmlelement("article")}} 要素をレイアウトしたいので、これを {{htmlelement("section")}} に設定します(これがフレックスコンテナになります)。

+ +
section {
+  display: flex;
+}
+ +

この結果は次のようになります。

+ +

+ +

それで、このたった一つの宣言が必要なものすべてを与えてくれます — 信じられないでしょ? 同じ幅の列を持つ複数列のレイアウトがあり、列の高さはすべて同じです。 これは、フレックス項目(フレックスコンテナの子)に与えられるデフォルト値が、このような一般的な問題を解決するために設定されているためです。 それらについての詳細は後で。

+ +
+

: インライン項目を柔軟な箱としてレイアウトしたい場合は、inline-flex を {{cssxref("display")}} の値として設定することもできます。

+
+ +

フレックスモデルのさておき

+ +

要素が柔軟な箱として配置されるとき、それらは次のように2つの軸に沿って配置されます。

+ +

flex_terms.png

+ + + +

次のセクションを進むときには、この用語集のことを覚えておいてください。 使用されている用語のいずれかについて混乱した場合は、いつでもここを参照することができます。

+ +

列それとも行?

+ +

フレックスボックスは {{cssxref("flex-direction")}} というプロパティを提供します。 これは主軸が走る方向(フレックスボックスの子がどの方向にレイアウトされるか)を指定します — デフォルトではこれは row に設定されていて、ブラウザーのデフォルト言語が動作する方向(英語のブラウザーの場合は左から右に)にそれらが横一列にレイアウトされます。

+ +

次の宣言を {{htmlelement("section")}})の規則に追加してみてください。

+ +
flex-direction: column;
+ +

これにより、CSS を追加する前と同じように、項目が縦一列のレイアウトに戻されます。 先に進む前に、この宣言を例から削除してください。

+ +
+

: row-reversecolumn-reverse の値を使用して、フレックス項目を逆方向にレイアウトすることもできます。 これらの値も試してみてください!

+
+ +

ラッピング

+ +

レイアウトの幅や高さが決まっているときに発生する問題の1つは、最終的にはフレックスボックスの子がコンテナをオーバーフローさせてレイアウトが壊れることです。 flexbox-wrap0.html の例を見て、それをライブで見てみてください(この例に沿って進めたい場合は、このファイルのローカルコピーを取ってください)。

+ +

+ +

ここで実際に子がコンテナから抜け出しているのを見ます。 これを修正できる1つの方法は、{{htmlelement("section")}})の規則に次の宣言を追加することです。

+ +
flex-wrap: wrap;
+ +

また、{{htmlelement("article")}} の規則に次の宣言を追加します。

+ +
flex: 200px;
+ +

試してみてください。 これが含まれていると次のようにレイアウトがはるかに良く見えることがわかります。

+ +

現在、複数の行があります — 多くのフレックスボックスの子が各行に納められているので、オーバーフローは次のラインに移動します。 article に設定した flex: 200px の宣言は、それぞれが少なくとも 200px 幅になることを意味します。 このプロパティについては後で詳しく説明します。 また、最後の行の最後の数個の子がそれぞれ幅広になっているので、依然として行全体がいっぱいになっていることに気付くかもしれません。

+ +

しかし、ここでできることは他にもあります。 まず最初に、{{cssxref("flex-direction")}} プロパティの値を row-reverse に変更してみてください。 これで、まだ複数行のレイアウトがあることがわかりますが、ブラウザーウィンドウの反対側の隅から開始して逆方向に流れます。

+ +

flex-flow 一括指定

+ +

この時点で、{{cssxref("flex-flow")}} という {{cssxref("flex-direction")}} と {{cssxref("flex-wrap")}} の一括指定が存在することに注目する価値があります。 例えば、次のように置き換えることができます。

+ +
flex-direction: row;
+flex-wrap: wrap;
+ +

+ +
flex-flow: row wrap;
+ +

フレックス項目の柔軟なサイズ変更

+ +

それでは、最初の例に戻って、フレックス項目の占めるスペースの割合を制御する方法を見てみましょう。 ローカルコピーの flexbox0.html を起動するか、新しい出発点として flexbox1.html のコピーを入手してください(ライブで見る)。

+ +

まず、CSS の一番下に次の規則を追加します。

+ +
article {
+  flex: 1;
+}
+ +

これは、各フレックス項目が主軸に沿って使用可能なスペースのうちどれだけを占めるかを決定する、無単位の割合値です。 この場合、各 {{htmlelement("article")}} 要素に 1 の値を与えています。 つまり、パディングやマージンなどを設定した後の残りの予備スペースのうちから、すべてが同じ量を占めます。 これは割合であり、各フレックス項目に 400000 の値を指定してもまったく同じ効果があることを意味します。

+ +

それでは、前の規則の下に次の規則を追加します。

+ +
article:nth-of-type(3) {
+  flex: 2;
+}
+ +

リフレッシュすると、3番目の {{htmlelement("article")}} が他の2つの幅の2倍の幅を占めます。 合計で 4 割合単位が使用可能です。 最初の2つのフレックス項目はそれぞれ 1 単位ずつ持つため、それぞれ使用可能なスペースの 1/4 を占めます。 3つ目は 2 単位を持っているので、それは使用可能なスペースの 2/4(または 1/2)を占めます。

+ +

flex の値内に最小サイズ値を指定することもできます。 既存の article の規則を次のように更新してみてください。

+ +
article {
+  flex: 1 200px;
+}
+
+article:nth-of-type(3) {
+  flex: 2 200px;
+}
+ +

これは基本的に「各フレックス項目には最初に 200px の使用可能なスペースが与えられます。 その後、残りの使用可能なスペースは割合単位に従って共有されます。」と述べています。 リフレッシュしてみると、スペースの共有方法に違いが見られます。

+ +

+ +

フレックスボックスの真の価値は、その柔軟性/応答性に見ることができます — ブラウザーウィンドウのサイズを変更したり、別の {{htmlelement("article")}} 要素を追加したりしても、レイアウトは問題なく機能します。

+ +

flex: 一括指定対個別指定

+ +

{{cssxref("flex")}} は、最大3つの異なる値を指定できる{{cssxref("Shorthand_properties","一括指定プロパティ")}}です。

+ + + +

本当に必要な場合以外は、個別指定の flex プロパティを使用しないことをお勧めします(例えば、以前に設定したものを上書きする場合など)。 それらは多くの余分なコードが書かれることにつながり、多少混乱するかもしれません。

+ +

水平方向と垂直方向の配置

+ +

フレックスボックスの機能を使用して、主軸または交差軸に沿ってフレックス項目を整列させることもできます。 新しい例である flex-align0.html を見て(ライブも見る)、これを調べてみましょう。 これは、きちんとした柔軟なボタン/ツールバーに変わります。 現時点では、いくつかのボタンが左上隅に詰まった水平のメニューバーが表示されます。

+ +

+ +

まず、この例のローカルコピーを取ります。

+ +

それでは、例の CSS の最後に次のものを追加してください。

+ +
div {
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+}
+ +

ページをリフレッシュすると、ボタンが横方向と縦方向に中央揃えになっていることがわかります。 これを2つの新しいプロパティを介して行いました。

+ +

{{cssxref("align-items")}} は、フレックス項目が交差軸上のどこに配置されるかを制御します。

+ + + +

{{cssxref("align-self")}} プロパティを適用することで、個々のフレックス項目の {{cssxref("align-items")}} のふるまいを上書きできます。 例えば、CSS に次のコードを追加してみてください。

+ +
button:first-child {
+  align-self: flex-end;
+}
+ +

これがどのような影響を与えるのかを見て、終了したらもう一度削除します。

+ +

{{cssxref("justify-content")}} は、フレックス項目が主軸上のどこに配置されるかを制御します。

+ + + +

続ける前に、これらの値を使用してそれらがどのように機能するかを確認することをお勧めします。

+ +

フレックス項目の順序付け

+ +

フレックスボックスには、ソース順に影響を与えずにフレックス項目のレイアウトの順序を変更する機能もあります。 これも従来のレイアウト方法では不可能なことです。

+ +

このコードは簡単です。 ボタンバーのサンプルコードに次の CSS を追加してみてください。

+ +
button:first-child {
+  order: 1;
+}
+ +

リフレッシュすると、[Smile] ボタンが主軸の終点に移動したことがわかります。 これがどのように機能するかについてもう少し詳しく説明しましょう。

+ + + +

負の order の値を設定して、0 が設定されている項目よりも早く項目を表示することができます。 例えば、次の規則を使用して、[Blush] ボタンを主軸の始点に表示させることができます。

+ +
button:last-child {
+  order: -1;
+}
+ +

ネストしたフレックスボックス

+ +

フレックスボックスを使ってかなり複雑なレイアウトを作成することは可能です。 フレックス項目をフレックスコンテナとしても設定して、その子も柔軟な箱のようにレイアウトできるようにしてもまったく問題ありません。 complex-flexbox.html を見てください(ライブも見る)。

+ +

+ +

このための HTML はかなり単純です。 3つの {{htmlelement("article")}} を含む {{htmlelement("section")}} 要素があります。 3番目の {{htmlelement("article")}} には3つの {{htmlelement("div")}} が含まれています。

+ +
section - article
+          article
+          article - div - button
+                    div   button
+                    div   button
+                          button
+                          button
+ +

レイアウトに使用したコードを見てみましょう。

+ +

まず、{{htmlelement("section")}} の子を柔軟な箱として配置するように設定します。

+ +
section {
+  display: flex;
+}
+ +

次に、{{htmlelement("article")}} 自体にいくつかの flex の値を設定します。 ここで2番目の規則に特に注意してください — 3番目の {{htmlelement("article")}} は、その子もフレックス項目のようにレイアウトするように設定していますが、今回はそれらを column のようにレイアウトしています。

+ +
article {
+  flex: 1 200px;
+}
+
+article:nth-of-type(3) {
+  flex: 3 200px;
+  display: flex;
+  flex-flow: column;
+}
+
+ +

次に、最初の {{htmlelement("div")}} を選択します。 最初に flex: 1 100px; を使用して効果的にそれの最小の高さを 100px にしてから、その子({{htmlelement("button")}} 要素)もフレックス項目のように配置されるように設定します。 ここでそれらをラッピングする行にレイアウトし、先ほど見た個々のボタンの例で行ったように、それらを使用可能なスペースの中央に配置します。

+ +
article:nth-of-type(3) div:first-child {
+  flex: 1 100px;
+  display: flex;
+  flex-flow: row wrap;
+  align-items: center;
+  justify-content: space-around;
+}
+ +

最後に、ボタンのサイズを設定しましたが、もっとおもしろいことに、1 autoflex の値を設定しています。 これは非常に興味深い効果があり、ブラウザーウィンドウの幅を変更してみるとわかります。 ボタンは可能な限り多くのスペースを占有し、できるだけ同じラインに配置できますが、同じラインに収まりきらなくなった場合は、ドロップダウンして新しいラインを作成します。

+ +
button {
+  flex: 1 auto;
+  margin: 5px;
+  font-size: 18px;
+  line-height: 1.5;
+}
+ +

クロスブラウザー互換性

+ +

フレックスボックスのサポートは、Firefox、Chrome、Opera、Microsoft Edge、IE 11、Android / iOS の新しいバージョンなど、ほとんどの新しいブラウザーで利用できます。 ただし、フレックスボックスをサポートしていない古いブラウザーもまだあります(または、しますが、本当に古い、時代遅れのバージョンをサポートします)。

+ +

あなたがただ学んで実験している間、これはあまり重要ではありません。 ただし、実際のウェブサイトでフレックスボックスを使用することを検討している場合は、テストを行い、できるだけ多くのブラウザーでユーザーエクスペリエンスが許容範囲内であることを確認する必要があります。

+ +

フレックスボックスはいくつかの CSS 機能よりも少しトリッキーです。 例えば、ブラウザーに CSS ドロップシャドウがない場合でも、そのサイトは引き続き使用可能です。 ただし、フレックスボックス機能をサポートしていないと、レイアウトが完全に壊れて使用できなくなる可能性があります。

+ +

クロスブラウザーテストのモジュールでは、クロスブラウザーのサポートの問題を解決するための戦略について説明します。

+ +

スキルをテストしましょう!

+ +

この記事では多くをカバーしましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Flexbox を見てください。

+ +

まとめ

+ +

これで、フレックスボックスの基本についてのツアーは終了です。 私たちはあなたが楽しみを持って、学習と共に前進するにつれてそれと一緒に良い遊びがあることを願っています。 次に、CSS レイアウトのもう1つの重要な側面、CSS グリッドについて見ていきます。

+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}
+ +
+

このモジュール内の文書

+ + +
diff --git a/files/ja/learn/css/css_layout/floats/index.html b/files/ja/learn/css/css_layout/floats/index.html new file mode 100644 index 0000000000..8de6f5367f --- /dev/null +++ b/files/ja/learn/css/css_layout/floats/index.html @@ -0,0 +1,528 @@ +--- +title: フロート +slug: Learn/CSS/CSS_layout/Floats +tags: + - Article + - Beginner + - CSS + - Clearing + - CodingScripting + - Floats + - Guide + - Layout + - columns + - multi-column +translation_of: Learn/CSS/CSS_layout/Floats +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout")}}
+ +

{{cssxref("float")}} プロパティは、もともとはテキストブロック内の浮動画像のためのものでしたが、ウェブページ上に複数列レイアウトを作成するために最も一般的に使われるツールの1つになりました。 この記事で説明しているように、フレックスボックスとグリッドの出現により、今は当初の目的に戻っています。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:ウェブページ上に浮動の特長を作成する方法と、clear プロパティおよびその他のフロートのクリア方法の使い方を習得します。
+ +

フロートの背景

+ +

画像の左や右を包み込むテキストにより、テキストの列内に浮かぶ画像を含む単純なレイアウトをウェブ開発者が実装できるようにするために {{cssxref("float")}} プロパティが導入されました。 あなたが新聞のレイアウトで得るかもしれない種類のものです。

+ +

しかしウェブ開発者はすぐに画像だけでなく何でも浮かべることができることに気づいたので、フロートの使用は広がりました。 例えば、drop-caps のような楽しいレイアウト効果です。

+ +

フロートは一般に、互いに並ぶように浮動する複数列の情報を含むウェブサイト全体のレイアウトを作成するために使用されてきました(デフォルトのふるまいでは、列はソースに表れる順序と同じ順序で上下に配置されます)。 より新しくより良いレイアウトテクニックが利用可能なので、このようにフロートを使うことは過去のテクニックとみなされるべきです。

+ +

この記事では、フロートの正しい使い方に集中します。

+ +

簡単なフロートの例

+ +

フロートの使い方を探りましょう。 要素の周りにテキストのブロックを浮かべることを含む本当に簡単な例から始めましょう。 コンピュータ上に新しい index.html ファイルを作成し、簡単な HTML テンプレートを使ってそれを埋め、適切な場所に以下のコードを挿入することで、フォローすることができます。 セクションの一番下では、最終的なコードがどのようになるべきかの実例を見ることができます。

+ +

まず、簡単な HTML から始めましょう。 HTML の body に次のコードを追加し、それまでの内部にあるものはすべて削除します。

+ +
<h1>Simple float example</h1>
+
+<div class="box">Float</div>
+
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. </p>
+
+<p>Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
+
+<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
+ +

次の CSS を HTML に適用します({{htmlelement("style")}} 要素を使用するか、{{htmlelement("link")}} を使用して別の .css ファイルを作成するか、選択します)。

+ +
body {
+  width: 90%;
+  max-width: 900px;
+  margin: 0 auto;
+  font: .9em/1.2 Arial, Helvetica, sans-serif
+}
+
+.box {
+  width: 150px;
+  height: 100px;
+  border-radius: 5px;
+  background-color: rgb(207,232,220);
+  padding: 1em;
+}
+ +

保存してリフレッシュすると予想していたものとよく似たものが表示されます — box が通常フローでテキストの上側に表示されます。 テキストをそれの周囲に浮かべるには、次のように .box 規則に {{cssxref("float")}} と {{cssxref("margin-right")}} プロパティを追加します。

+ +
.box {
+  float: left;
+  margin-right: 15px;
+  width: 150px;
+  height: 100px;
+  border-radius: 5px;
+  background-color: rgb(207,232,220);
+  padding: 1em;
+}
+ +

保存してリフレッシュすると、次のようになります。

+ +
+ +
+ +

{{ EmbedLiveSample('Float_1', '100%', 500) }}

+ +

フロートがどのように機能するかを考えてみましょう。 float が設定されている要素(この場合は {{htmlelement("div")}} 要素)は、文書の通常のレイアウトフローから除かれ、その親コン​​テナ(この場合は {{htmlelement("body")}})の左側に固定されます。 通常のレイアウトフローで浮動要素の下側に来るコンテンツは、それを包み込み、浮動要素の最上部まで、その右側のスペースを埋めます。 そこで、それは止まるでしょう。

+ +

コンテンツを右に浮かべるとまったく同じ効果が得られますが、逆になります。 つまり、浮動要素は右に固定され、コンテンツはその左側を包み込みます。 float の値を right に変更し、最後のルールセットで {{cssxref("margin-right")}} を {{cssxref("margin-left")}} に置き換えて、結果がどうなるかを確認してください。

+ +

テキストを押しのけるためにフロートにマージン(margin、余白)を追加することはできますが、テキストをフロートから遠ざけるためにテキストにマージンを追加することはできません。 これは、浮動要素は通常フローから外され、後続項目のボックスが実際にはフロートの背後にあるためです。 例にいくつかの変更を加えることによってこれを実証することができます。

+ +

テキストの最初の段落、つまり浮動ボックスの直後の段落に special のクラスを追加してから、CSS に次の規則を追加します。 これらは後続段落に背景色を与えます。

+ +
.special {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  color: #fff;
+}
+
+ +

効果を見やすくするために、フロートの margin-rightmargin に変更すると、フロートの全周にマージンができます。 以下の例のように、浮動ボックスの真下にある段落の背景を見ることができます。

+ +
+ +
+ +

{{ EmbedLiveSample('Float_2', '100%', 500) }}

+ +

後続要素の行ボックスは短くなっているのでテキストはフロートの周りを囲みますが、フロートは通常フローから除かれるため、段落の周りのボックスは依然として全幅のままです。

+ +

フロートのクリア

+ +

フロートは通常フローから除かれ、他の要素がその横に表示されることを見てきました。 したがって、後続要素の上方向への移動を止めたい場合は、それをクリアする必要があります; これは {{cssxref("clear")}} プロパティによって達成されます。

+ +

前の例の HTML では、浮動項目の下の2番目の段落に cleared のクラスを追加します。 次に、CSS に以下を追加してください。

+ +
.cleared {
+  clear: left;
+}
+
+ +
+ +
+ +

{{ EmbedLiveSample('Float_3', '100%', 600) }}

+ +

後続段落で、浮動要素がクリアされ、並んで現れなくなったことがわかります。 clear プロパティは次の値を受け入れます。

+ + + +

フロートを包み込むボックスのクリア

+ +

浮動要素に後続するものをクリアする方法はわかりましたが、背の高いフロートと短い段落があり、その両方の要素の周りをボックスが包む場合はどうなるか見てみましょう。 最初の段落と浮動ボックスが wrapper のクラスの {{htmlelement("div")}} に囲まれるように文書を変更します。

+ +
<div class="wrapper">
+  <div class="box">Float</div>
+
+  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate.</p>
+</div>
+
+ +

CSS で、.wrapper クラスに次の規則を追加してからページをリロードします。

+ +
.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  color: #fff;
+}
+ +

加えて、元の .cleared クラスを削除します。

+ +
.cleared {
+    clear: left;
+}
+ +

段落に背景色を与えた例と同じように、背景色がフロートの背後にあることがわかります。

+ +
+ +
+ +

{{ EmbedLiveSample('Float_4', '100%', 600) }}

+ +

前と同じように、これもまた、フロートが通常フローから外されたためです。 コンテンツが短い場合でも、ボックスの底に浮動項目とラッピングコンテンツを包む必要がある場合には、後続要素のクリアでは、このボックスのクリアの問題を解決することはできません。 これに対処する方法は3つあります。 そのうちの2つはすべてのブラウザーで機能します — それでもやや厄介です — そしてこの状況に適切に対処する3番目の新しい方法です。

+ +

clearfix ハック

+ +

この状況に伝統的に対処してきた方法は、「clearfix ハック」として知られているものを使うことです。 これはフロートとラッピングコンテンツを含むボックスの後に生成したコンテンツを挿入し、両方をクリアするように設定することを含みます。

+ +

例に次の CSS を追加します。

+ +
.wrapper::after {
+  content: "";
+  clear: both;
+  display: block;
+}
+ +

ページをリロードすると、ボックスはクリアされます。 これは、項目の下に <div> などの HTML 要素を追加して clear: both に設定した場合と基本的に同じです。

+ +
+ +
+ +

{{ EmbedLiveSample('Float_5', '100%', 600) }}

+ +

オーバーフローを使用する

+ +

別の方法は、wrapper の {{cssxref("overflow")}} プロパティを visible 以外の値に設定することです。

+ +

前のセクションで追加した clearfix の CSS を削除し、代わりに wrapper の規則に overflow: auto を追加してください。 前と同じように、ボックスはクリアされます。

+ +
.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  color: #fff;
+  overflow: auto;
+}
+ +
+ +
+ +

{{ EmbedLiveSample('Float_6', '100%', 600) }}

+ +

この例は、ブロック整形コンテキストblock formatting context、BFC)と呼ばれるものを作成することによって機能します。 これはページの中にあるミニレイアウトのようなもので、その中にすべてが含まれているので、浮動要素は BFC の中に含まれ、背景は両方の項目の背後にあります。 これは通常はうまくいきますが、場合によっては、オーバーフローを使用することによる意図しない結果が原因で、不要なスクロールバーや切り取られた影が見つかることがあります。

+ +

display: flow-root

+ +

この問題を解決する現代的な方法は、display プロパティの flow-root という値を使うことです。 これはハックを使用せずに BFC を作成するためだけに存在します — それを使用しても意図しない結果が生じることはありません。 .wrapper 規則から overflow: auto を削除し、display: flow-root を追加してください。 これをサポートするブラウザーを持っていると仮定すると、ボックスはクリアされます。

+ +
.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  color: #fff;
+  display: flow-root;
+}
+ +
+ +
+ +

{{ EmbedLiveSample('Float_7', '100%', 600) }}

+ +

スキルをテストしましょう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Floats を見てください。

+ +

まとめ

+ +

あなたは今、現代のウェブ開発でフロートについて知っておくべきことがすべてわかっています。 過去のレイアウト方法の使用方法については、過去のレイアウト方法に関する記事を参照してください。 古いプロジェクトで作業している場合に便利です。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/fundamental_layout_comprehension/index.html b/files/ja/learn/css/css_layout/fundamental_layout_comprehension/index.html new file mode 100644 index 0000000000..42e19361bc --- /dev/null +++ b/files/ja/learn/css/css_layout/fundamental_layout_comprehension/index.html @@ -0,0 +1,91 @@ +--- +title: 基礎的なレイアウトの理解 +slug: Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension +tags: + - Assessment + - Beginner + - CSS + - Layout + - Learn +translation_of: Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}
+ +

このモジュールを乗り越えてきたならば、今日 CSS レイアウトを行うために知っておくべきことや、より古い CSS を使って作業するために必要なことの基本についてはすでに説明しているはずです。 このタスクでは、さまざまなテクニックを使用して簡単なウェブページレイアウトを作成することによって、あなたの知識の一部をテストします。

+ + + + + + + + + + + + +
前提知識:この評価を試みる前に、このモジュールのすべての記事を読んでおくべきです。
学習目標:このモジュールで説明してきた基本的なレイアウトスキルの理解をテストすること。
+ +

プロジェクトの概要

+ +

生の HTML、基本的な CSS、そして画像が提供されています — これで、次の画像にそっくりなデザインのレイアウトを作成する必要があります。

+ +

+ +

基本設定

+ +

HTML、CSS、および6枚の画像をここからダウンロードできます。

+ +

HTML ドキュメントとスタイルシートをコンピュータ上のディレクトリに保存し、画像を images という名前のフォルダに追加します。 ブラウザーで index.html ファイルを開くと、次の画像のような基本的なスタイルは設定されているがレイアウトが設定されていないページが表示されます。

+ +

この出発点には、通常フローでブラウザーに表示されるレイアウトのすべての内容が含まれています。

+ +

+ +

あなたのタスク

+ +

あなたは今レイアウトを実装する必要があります。 達成する必要があるタスクは次のとおりです。

+ +
    +
  1. ナビゲーション項目を、項目間に等間隔のスペースを置いて、1行に並べて表示します。
  2. +
  3. ナビゲーションバーはコンテンツと一緒にスクロールし、ビューポートの上部に到達するとそこに固定されるべきです。
  4. +
  5. 記事の中にある画像は、それを囲むテキストを持つべきです。
  6. +
  7. {{htmlelement("article")}} 要素と {{htmlelement("aside")}} 要素は、2列のレイアウトとして表示するべきです。 ブラウザーウィンドウが小さくなると列が狭くなるように、列は柔軟なサイズにするべきです。
  8. +
  9. 写真は、画像間に1ピクセルの間隔を空けて2列のグリッドとして表示するべきです。
  10. +
+ +

このレイアウトを実現するために HTML を編集する必要はなく、使用するべきテクニックは次のとおりです。

+ + + +

これらのタスクのいくつかを達成することができるいくつかの方法があり、物事を行うための唯一の正しい方法も間違った方法も、多くの場合ありません。 いくつかの異なる方法を試して、どれが最もうまくいくかを確かめてください。 実験しながらメモを取ってください。 この演習のディスカッションスレッドまたは #mdn IRC チャンネルで、自分のアプローチについて常に議論することができます。

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合は、採点のために作品を教師や指導者に渡すことができるはずです。 自己学習をしている場合は、この演習についてのディスカッションスレッドMozilla IRC#mdn IRC チャンネルで尋ねることで、かなり簡単に採点の手引きを得ることができます。 まず演習を試してみてください — 不正行為によって得られるものは何もありません!

+ +
{{PreviousMenu("Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}
+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/grids/index.html b/files/ja/learn/css/css_layout/grids/index.html new file mode 100644 index 0000000000..d7ca3601c3 --- /dev/null +++ b/files/ja/learn/css/css_layout/grids/index.html @@ -0,0 +1,722 @@ +--- +title: グリッド +slug: Learn/CSS/CSS_layout/Grids +tags: + - Article + - Beginner + - CSS + - CSS Grids + - CodingScripting + - Grids + - Guide + - Layout + - Learn + - Tutorial + - grid design + - grid framework + - grid system +translation_of: Learn/CSS/CSS_layout/Grids +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout")}}
+ +

CSS グリッドレイアウト(Grid Layout)は、ウェブ用の2次元レイアウトシステムです。 これにより、コンテンツを行と列にレイアウトすることができ、複雑なレイアウトを簡単に構築できるようにする多くの機能があります。 この記事では、ページレイアウトを始めるために知っておくべきことをすべて説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門ボックスの装飾を学ぶ)。
学習目標:グリッドレイアウトシステムの背後にある基本概念と、CSS グリッドを使用してグリッドレイアウトを実装する方法を理解すること。
+ +

グリッドレイアウトとは?

+ +

グリッドとは、水平方向と垂直方向のラインを集めたもので、デザイン要素を並べて表示することができます。 ページ間を移動するときに要素が跳び回ったり幅が変わったりしないようなデザインを作成するのに役立ちます。 これにより、ウェブサイトの一貫性が向上します。

+ +

グリッドには通常、列(column)、行(row)、そしてそれぞれの行と列の間のギャップ(通常はガター(gutter)と呼ばれます)があります。

+ +

+ +

CSS でグリッドを作りましょう

+ +

デザインに必要なグリッドを決定したら、CSS グリッドレイアウトを使用して CSS でそのグリッドを作成し、その上に項目を配置できます。 最初にグリッドレイアウトの基本機能を見てから、プロジェクト用のシンプルなグリッドシステムを作成する方法を探ります。

+ +

The following video provides a nice visual explanation of using CSS Grid:

+ +

{{EmbedYouTube("KOvGeFUHAC0")}}

+ +

グリッドを定義する

+ +

出発点として、テキストエディタとブラウザーで出発点ファイルをダウンロードして開きます(ここでライブを見ることもできます)。 いくつかの子項目を持つコンテナの例が表示されます。 デフォルトではこれらは通常フローで表示されるので、ボックスは上下に表示されます。 このレッスンの最初の部分でこのファイルを使用して、グリッドのふるまいを確認するための変更を加えます。

+ +

グリッドを定義するために、{{cssxref("display")}} プロパティに grid の値を使います。 フレックスボックスと同様に、これによりグリッドレイアウトがオンになり、コンテナの直接の子すべてがグリッド項目になります。 次のものをファイル内の CSS に追加してください。

+ +
.container {
+    display: grid;
+}
+ +

フレックスボックスとは異なり、項目はすぐには違ったようには見えません。 display: grid を宣言すると1列のグリッドになるので、項目は通常フローで表示されるように上下に表示され続けます。

+ +

よりグリッドらしく見せるには、グリッドにいくつかの列を追加する必要があります。 ここに 200 ピクセルの列を3つ追加しましょう。 これらの列トラックを作成するために、任意の長さの単位やパーセントを使用できます。

+ +
.container {
+    display: grid;
+    grid-template-columns: 200px 200px 200px;
+}
+ +

CSS 規則に2番目の宣言を追加してからページをリロードすると、作成したグリッドの各セルに項目が1つずつ再配置されていることがわかります。

+ +
+ +
+ +

{{ EmbedLiveSample('Grid_1', '100%', 400) }}

+ +

fr 単位での柔軟なグリッド

+ +

長さとパーセントを使用してグリッドを作成するだけでなく、fr 単位を使用して柔軟にグリッドの行と列のサイズを変更できます。 この単位は、グリッドコンテナ内の使用可能スペースの割合を表します。

+ +

トラックのリストを次の定義に変更し、1fr のトラックを3つ作成します。

+ +
.container {
+    display: grid;
+    grid-template-columns: 1fr 1fr 1fr;
+}
+ +

あなたは今、柔軟なトラックを持っているのを見るべきです。 fr 単位はスペースを比例して配分するので、トラックには異なる正の値を指定できます。 例えば次のように定義を変更したとします。

+ +
.container {
+    display: grid;
+    grid-template-columns: 2fr 1fr 1fr;
+}
+ +

最初のトラックの使用可能スペースは 2fr になり、他の2つのトラックの使用可能スペースは 1fr になり、最初のトラックのサイズが大きくなります。 fr 単位と固定長トラックを混在させることができます — そのような場合、固定長トラックに必要なスペースは、スペースが他のトラックに分配される前に取り除かれます。

+ +
+ +
+ +

{{ EmbedLiveSample('Grid_2', '100%', 400) }}

+ +
+

: fr 単位は、すべてのスペースではなく、使用可能なスペースを分配します。 あなたのトラックの1つがその中に大きな何かを持っているならば、共有する空きスペースは少なくなります。

+
+ +

トラック間のギャップ

+ +

トラック間のギャップを作成するには、列間のギャップには {{cssxref("grid-column-gap")}} プロパティ、行間のギャップには {{cssxref("grid-row-gap")}} プロパティ、両方を同時に設定するには {{cssxref("grid-gap")}} プロパティを使用します。

+ +
.container {
+    display: grid;
+    grid-template-columns: 2fr 1fr 1fr;
+    grid-gap: 20px;
+}
+ +

これらのギャップは、長さの単位またはパーセントのいずれでもかまいませんが、fr 単位ではありません。

+ +
+ +
+ +

{{ EmbedLiveSample('Grid_3', '100%', 400) }}

+ +
+

: *gap プロパティは以前は grid- という接頭辞を付けていましたが、これは仕様変更されています。 その意図はそれらを複数のレイアウト方法で使えるようにすることです。 接頭辞の付いたバージョンはエイリアスとして保持されるため、しばらくの間は安全に使用できます。 安全のために、コードをより万全にするために、両方のプロパティを倍増して追加することができます。

+
+ +
.container {
+  display: grid;
+  grid-template-columns: 2fr 1fr 1fr;
+  grid-gap: 20px;
+  gap: 20px;
+}
+ +

トラックリストの繰り返し

+ +

反復記法を使用して、トラックリストの全部または一部を繰り返すことができます。 トラックリストを次のように変更します。

+ +
.container {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    grid-gap: 20px;
+}
+ +

今までと同じ3つの 1fr のトラックが手に入ります。 repeat 関数に渡す最初の値はリストを繰り返す回数で、2番目の値はトラックリストで、1つ以上のトラックを繰り返すことができます。

+ +

暗黙的グリッドと明示的グリッド

+ +

ここまでは列トラックのみを指定しましたが、コンテンツを保持するために行が作成されています。 これは明示的グリッド対暗黙的グリッドの例です。 明示的グリッドは、grid-template-columns または grid-template-rows を使用して作成したものです。 暗黙的グリッドは、コンテンツがそのグリッドの外側、例えば行に配置されたときに作成されます。 明示的グリッドと暗黙的グリッドは、フレックスボックスの主軸および交差軸と類似しています。

+ +

デフォルトでは、暗黙的グリッドに作成されたトラックは auto でサイズ調整されます。 これは一般に、コンテンツに合わせて十分に大きいことを意味します。 暗黙的グリッドのトラックにサイズを指定したい場合は、{{cssxref("grid-auto-rows")}} プロパティと {{cssxref("grid-auto-columns")}} プロパティを使用できます。 CSS に 100px の値で grid-auto-rows を追加すると、作成された行の高さは 100 ピクセルになります。

+ +
+ + +
.container {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  grid-auto-rows: 100px;
+  grid-gap: 20px;
+}
+
+ +

{{ EmbedLiveSample('Grid_4', '100%', 400) }}

+ +

minmax() 関数

+ +

100 ピクセルより高いコンテンツを追加する場合、100 ピクセルの高さのトラックはあまり役に立ちません。 その場合、オーバーフローが発生します。 トラックの高さは最低 100 ピクセルで、さらに多くのコンテンツがトラックに入る場合は拡大できると良いでしょう。 ウェブについてのかなり基本的な事実は、あなたが実際に何かがどれほど高くなるかを本当に知らないということです。 追加のコンテンツや大きなフォントサイズは、あらゆる次元でピクセルパーフェクトになろうとするデザインに問題を引き起こす可能性があります。

+ +

{{cssxref("minmax")}} 関数を使用すると、トラックの最小サイズと最大サイズ、例えば minmax(100px, auto) を設定できます。 最小サイズは 100 ピクセルですが、最大サイズは auto で、コンテンツに合わせて拡大されます。 次のように minmax の値を使用するように grid-auto-rows を変更してみてください。

+ +
.container {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    grid-auto-rows: minmax(100px, auto);
+    grid-gap: 20px;
+}
+ +

追加のコンテンツを追加すると、それが収まるようにトラックが拡大されます。 拡張は行に沿って行われることに注意してください。

+ +

収まる限り多くの列

+ +

トラックリスト、反復記法、{{cssxref("minmax")}} について学んだことのいくつかを組み合わせて、便利なパターンを作成できます。 グリッドに、コンテナに収まるだけの数の列を作成するように依頼できると便利な場合があります。 これを行うには、{{cssxref("repeat")}} 記法を使用して grid-template-columns の値を設定しますが、数値を渡す代わりにキーワード auto-fill を渡します。 関数の2番目のパラメータには、minmax() を使用し、最小値は、必要な最小トラックサイズに等しく、最大値は 1fr です。

+ +

以下の CSS を使用して、今すぐあなたのファイルで次を試してください。

+ +
+ + +
.container {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+  grid-auto-rows: minmax(100px, auto);
+  grid-gap: 20px;
+}
+
+ +

{{ EmbedLiveSample('Grid_5', '100%', 400) }}

+ +

これは、グリッドがコンテナに収まるだけの数の 200 ピクセルの列を作成し、その後すべての列の間で残っているスペースを共有するためです — 最大は 1fr で、すでにご存じのとおり、トラック間でスペースを均等に配分するためのものです。

+ +

ラインベースの配置

+ +

グリッドの作成から、グリッド上に物を配置することに移ります。 グリッドは常にラインを持っていて、そのラインは 1 から始まり、文書の書字方向モード(Writing Mode)に関連しています。 したがって、英語では、桁の1ライン目がグリッドの左側にあり、行の1ライン目が一番上にあります。 アラビア語では、アラビア語は右から左に書かれているので、桁の1ライン目が右側になります。

+ +

開始ラインと終了ラインを指定することで、これらのラインに従って物を配置できます。 次のプロパティを使用してこれを行います。

+ + + +

これらのプロパティはすべて値としてライン番号を持つことができます。 次の一括指定プロパティを使用することもできます。

+ + + +

これにより、開始ラインと終了ラインを / (スラッシュ文字)で区切って一度に指定できます。

+ +

出発点としてこのファイルをダウンロードするか、ここにあるライブを見てください。 それはすでに定義されたグリッドを持ち、そして簡単な記事が概説されています。 自動配置により、作成したグリッドの各セルに項目を1つずつ配置していることがわかります。

+ +

代わりに、グリッドラインを使用して、サイトのすべての要素をグリッドに配置します。 CSS の最後に次の規則を追加してください。

+ +
header {
+  grid-column: 1 / 3;
+  grid-row: 1;
+}
+
+article {
+  grid-column: 2;
+  grid-row: 2;
+}
+
+aside {
+  grid-column: 1;
+  grid-row: 2;
+}
+
+footer {
+  grid-column: 1 / 3;
+  grid-row: 3;
+}
+ +
+ +
+ +

{{ EmbedLiveSample('Grid_6', '100%', 400) }}

+ +
+

: 終点の列または行のラインをターゲットとして値 -1 を使用し、負の値を使用して終点から内側に向かって数えることもできます。 しかしこれは明示的グリッドに対してのみ有効です。 値 -1 は、暗黙的グリッドの終点のラインをターゲットにしません。

+
+ +

grid-template-areas での配置

+ +

項目をグリッドに配置する別の方法は、{{cssxref("grid-template-areas")}} プロパティを使用して、デザインのさまざまな要素に名前を付けることです。

+ +

最後の例からラインベースの配置を削除して(またはファイルを再ダウンロードして新しい出発点にして)、次の CSS を追加します。

+ +
.container {
+  display: grid;
+  grid-template-areas:
+      "header header"
+      "sidebar content"
+      "footer footer";
+  grid-template-columns: 1fr 3fr;
+  grid-gap: 20px;
+}
+
+header {
+  grid-area: header;
+}
+
+article {
+  grid-area: content;
+}
+
+aside {
+  grid-area: sidebar;
+}
+
+footer {
+  grid-area: footer;
+}
+ +

ページをリロードすると、ライン番号を使用しなくても項目が以前と同じように配置されたことがわかります!

+ +
+ +
+ +

{{ EmbedLiveSample('Grid_7', '100%', 400) }}

+ +

grid-template-area の規則は次のとおりです。

+ + + +

あなたは私たちのレイアウトで遊ぶことができます。 例えば、フッターをコンテンツの下にだけあるように変更し、サイドバーをずっと下に広げるように変更できます。 これは、何が起こっているのかが CSS から明らかなので、レイアウトを記述するためのとても良い方法です。

+ +

CSS グリッド、グリッドフレームワーク

+ +

グリッドの「フレームワーク」は、12列または16列のグリッドと CSS グリッドを基にし、そのようなフレームワークを提供するためにサードパーティ製ツールを必要としません — すでに仕様にあります。

+ +

出発点ファイルをダウンロードしてください。 これには、12列のグリッドが定義されたコンテナと、前の2つの例で使用したのと同じマークアップが含まれています。 ラインベースの配置を使用して、次のようにコンテンツを12列のグリッドに配置できます。

+ +
header {
+  grid-column: 1 / 13;
+  grid-row: 1;
+}
+
+article {
+  grid-column: 4 / 13;
+  grid-row: 2;
+}
+
+aside {
+  grid-column: 1 / 4;
+  grid-row: 2;
+}
+
+footer {
+  grid-column: 1 / 13;
+  grid-row: 3;
+}
+ +
+ +
+ +

{{ EmbedLiveSample('Grid_8', '100%', 400) }}

+ +

Firefox のグリッドインスペクタを使用してデザイン上のグリッドラインをオーバーレイすると、12列グリッドがどのように機能するかがわかります。

+ +

私たちのデザインの上に重ねられた12列のグリッド。

+ +

スキルをテストしましょう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Grids を見てください。

+ +

まとめ

+ +

この概要では、CSS グリッドレイアウトの主な機能について説明しました。 あなたのデザインでそれを使い始めることができるはずです。 仕様をさらに深く掘り下げるには、以下にあるグリッドレイアウトのガイドを読んでください。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/index.html b/files/ja/learn/css/css_layout/index.html new file mode 100644 index 0000000000..419de7d135 --- /dev/null +++ b/files/ja/learn/css/css_layout/index.html @@ -0,0 +1,80 @@ +--- +title: CSS レイアウト +slug: Learn/CSS/CSS_layout +tags: + - Beginner + - CSS + - Floating + - Grids + - Guide + - Landing + - Layout + - Learn + - Module + - Multiple column + - Positioning + - alignment + - flexbox + - float + - table +translation_of: Learn/CSS/CSS_layout +--- +
{{LearnSidebar}}
+ +

現段階で、すでに CSS の基本、テキストの装飾方法、コンテンツを格納するボックスの装飾方法と操作方法を見てきました。 今度は、ビューポートや互いを基準にしてボックスを適切な場所に配置する方法を検討します。 必要な前提知識をカバーしているので、さまざまな display の設定、フレックスボックス・CSS グリッド・位置指定などの最新のレイアウトツール、そしてまだ知っておきたいと思うかもしれない過去のテクニックのいくつかを見ながら、CSS レイアウトについて深く掘り下げることができます。

+ +

前提知識

+ +

このモジュールを始める前に、次のことを理解しているべきです。

+ +
    +
  1. HTML 入門で説明したように、HTML についての基本的な知識があること。
  2. +
  3. CSS 入門で説明したように、CSS の基本を容易にこなせること。
  4. +
  5. ボックスを装飾する方法を理解していること。
  6. +
+ +
+

注: 使用しているコンピューター/タブレット/その他のデバイスで自分のファイルを作成できない場合は、JSBinThimble などのオンラインコーディングプログラムで(ほとんどの)コードサンプルを試すことができます。

+
+ +

ガイド

+ +

これらの記事では、CSS で利用可能な基本的なレイアウトのツールとテクニックについての教育を提供します。 レッスンの最後には、ウェブページをレイアウトすることによって、レイアウト方法の理解を確認するのに役立つ評価試験があります。

+ +
+
CSS レイアウト入門
+
この記事では、以前のモジュールで既に触れた CSS レイアウト機能のいくつか(さまざまな {{cssxref("display")}} の値など)を要約し、このモジュール全体で取り上げるいくつかの概念を紹介します。
+
通常フロー
+
ウェブページ上の要素は、通常フローを変えるために何かをするまで、通常フローに従ってレイアウトされます。 この記事では、通常フローを変える方法を学ぶための基礎として、通常フローの基本について説明します。
+
フレックスボックス
+
+

フレックスボックスは、項目を行または列にレイアウトするための1次元のレイアウト方法です。 項目は追加のスペースを埋めるためにたわみ、小さいスペースに収まるように縮小します。 この記事では、すべての基本事項について説明します。

+
+
グリッド
+
CSS グリッドレイアウトは、ウェブ用の2次元レイアウトシステムです。 これにより、コンテンツを行と列にレイアウトすることができ、複雑なレイアウトを簡単に構築できるようにする多くの機能があります。 この記事では、ページレイアウトを始めるために知っておくべきことをすべて説明します。
+
フロート
+
{{cssxref("float")}} プロパティは、もともとはテキストブロック内の浮動画像のためのものでしたが、ウェブページ上に複数列レイアウトを作成するために最も一般的に使われるツールの1つになりました。 この記事で説明しているように、フレックスボックスとグリッドの出現により、今は当初の目的に戻っています。
+
位置指定
+
位置指定を使用すると、通常のドキュメントレイアウトフローから要素を取り出して異なるふるまいをさせることができます。 例えば、互いの上に重なったり、常にブラウザーのビューポート内の同じ場所に留まったりします。 この記事では、さまざまな {{cssxref("position")}} の値とその使い方について説明します。
+
段組みレイアウト
+
段組みレイアウトの仕様では、新聞に見られるような、コンテンツを段にレイアウトする方法が提供されています。 この記事では、この機能の使い方について説明します。
+
レスポンシブデザイン
+
Web 対応デバイスでより多様な画面サイズが登場するにつれて、レスポンシブ Web デザイン(RWD)の概念が登場しました。 これは、さまざまな画面幅、解像度などに合わせて Web ページがレイアウトと外観を変更できるようにする一連の実践です。 これは、マルチデバイス Web 向けのデザイン方法を変更したアイデアであり、この記事では、それをマスターするために知っておくべき主なテクニックを理解するのに役立ちます。
+
メディアクエリーの初心者向けガイド
+
CSS メディアクエリーを使用すると、例えば、「ビューポートは 480 ピクセルよりも広い」というような、ブラウザーとデバイスの環境が指定した規則に一致する場合にのみ CSS を適用できます。 メディアクエリーは、ビューポートのサイズに応じて異なるレイアウトを作成できるため、レスポンシブ Web デザイン(responsive web design、RWD)の重要な部分ですが、例えば、ユーザーはマウスではなくタッチスクリーンを使用しているというような、サイトが実行されている環境に関する他のものを検出するためにも使用できます。 このレッスンでは、最初にメディアクエリーで使用される構文について学習し、次に単純なデザインでどのようにレスポンシブにするかを示す実際の例で使用してみます。
+
過去のレイアウト方法
+
グリッドシステムは CSS レイアウトで使用される非常に一般的な機能で、CSS グリッドレイアウト以前はフロートや他のレイアウト機能を使用して実装される傾向がありました。 あなたはレイアウトをいくつかの列(例えば 4、6、または 12)として想像し、そしてコンテンツの列をこれらの想像上の列の内側に合わせます。 この記事では、古いプロジェクトで作業した場合に、それらがどう使われたかを理解するために、これらの古い方法がどのように機能するのかを説明します。
+
古いブラウザのサポート
+
+

このモジュールでは、フレックスボックスとグリッドをデザインの主なレイアウト方法として使用することをお勧めしています。 しかしながら、サイトへの訪問者には、古いブラウザーや、使用している方法をサポートしていないブラウザーを使用している人がいます。 これはウェブ上で常に当てはまります — 新しい機能が開発されると、ブラウザーによって異なるものが優先されます。 この記事では、古い技術のユーザーを締め出すことなく最新のウェブテクニックを使用する方法について説明します。

+
+
評価試験: 基礎的なレイアウトの理解
+
ウェブページをレイアウトすることによって、さまざまなレイアウト方法に関する知識をテストするための評価試験です。
+
+ +

関連情報

+ +
+
実用的な位置指定の例
+
この記事では、位置指定でどのようなことができるかを説明するために、実際に使用されるいくつかの例を作成する方法を示します。
+
diff --git a/files/ja/learn/css/css_layout/introduction/index.html b/files/ja/learn/css/css_layout/introduction/index.html new file mode 100644 index 0000000000..3425a29729 --- /dev/null +++ b/files/ja/learn/css/css_layout/introduction/index.html @@ -0,0 +1,720 @@ +--- +title: CSS レイアウト入門 +slug: Learn/CSS/CSS_layout/Introduction +tags: + - Article + - Beginner + - CSS + - Floats + - Grids + - Introduction + - Layout + - Learn + - Positioning + - Tables + - flexbox + - flow +translation_of: Learn/CSS/CSS_layout/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}
+ +

この記事では、以前のモジュールで既に触れた CSS レイアウト機能のいくつか(さまざまな {{cssxref("display")}} の値など)を要約し、このモジュール全体で取り上げるいくつかの概念を紹介します。

+ + + + + + + + + + + + +
前提知識:HTML の基礎(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:CSS ページレイアウトのテクニックの概要を説明します。 各テクニックは、以降のチュートリアルで詳細に学ぶことができます。
+ +

CSS のページレイアウト技術によって、ウェブページに含まれる要素の位置を制御できます。通常のレイアウトフローによる初期配置、隣接する要素、それらの親コンテナ、またはメインビューポート、ウィンドウの位置、といったものが位置を制御する基準になりえます。 このモジュールでは次に挙げるページレイアウト技術の詳細について説明します。

+ + + +

どの技術にも、それぞれ用途、長所、短所があり、単独で使用するようには設計されていません。 ひとつひとつの技術がどのように設計されているかを理解することは、それぞれのタスクに最適なレイアウト方法を判断するための基礎になるでしょう。

+ +

通常フロー

+ +

通常フロー(Normal flow)は、ページレイアウトの制御を何もしない場合に、ブラウザーがデフォルトで HTML ページをレイアウトする方法です。 次の簡単な HTML の例を見てみましょう。

+ +
<p>I love my cat.</p>
+
+<ul>
+  <li>Buy cat food</li>
+  <li>Exercise</li>
+  <li>Cheer up friend</li>
+</ul>
+
+<p>The end!</p>
+ +

デフォルトでは、ブラウザーはこのコードを次のように表示します。

+ +

{{ EmbedLiveSample('Normal_flow', '100%', 200) }}

+ +

ここでは、HTML がソースコードに現れる順序どおりに表示されていることに注意してください — 最初の段落の後に番号なしリストが続き、その後に2番目の段落が続きます。

+ +

上下に並んで表示される要素はブロック要素と呼ばれています。段落内の個々の単語と同じように横に並んで表示されるインライン要素とは対照的です。

+ +
+

: ブロック要素のコンテンツがレイアウトされる方向は、ブロック方向(Block Direction)と呼ばれます。 ブロック方向は、英語などの横書きモード(Horizontal Writing Mode)の言語では垂直に走ります。 日本語のような縦書きモード(Vertical Writing Mode)では、どの言語でも水平に走ります。 対応するインライン方向(Inline Direction)は、インラインコンテンツ(文など)が走る方向です。

+
+ +

CSSで何かをレイアウトするとその要素を通常フローから遠ざけることになりますが、ページ上の多くの要素は通常フローにしたがって適宜レイアウトされます。これが、構造化された HTML 文書から始めることが非常に重要である理由です。 なぜなら、多くの要素のレイアウトに一から悪戦苦闘するかわりに、あらかじめ多くのものがレイアウトされている現状で作業できるからです。

+ +

CSS で要素をどのように配置するかを変更できる方法は次のとおりです。

+ + + +

display プロパティ

+ +

CSS でページレイアウトを実現するための主な方法は、display プロパティのすべての値です。 このプロパティにより、デフォルトの表示方法を変更することができます。 通常フローに属するすべての要素には display の値が設定されており、この値によって要素のデフォルトのふるまいが決まります。 例えば、英語の文書内で{{htmlelement("p", "段落")}}が上から下へ表示されるのは、display: block でスタイルが設定されているためです。 段落内のテキストの周囲にリンクを作成しても、そのリンクは残りのテキストとインラインのままで、改行しません。 これは、{{htmlelement("a")}} 要素がデフォルトで display: inline であるためです。

+ +

このような display のデフォルトのふるまいは変更できます。 例えば、{{htmlelement("li")}} 要素はデフォルトで display: block です。 つまり、英語の文書ではリスト項目は上下に表示されます。 display の値を inline に変更した場合、単語が文中で行うように、それらは互いに隣接して表示されます。 任意の要素に対して display の値を変更できるということは、どのように見えるかについて心配することなく、意味論的(semantic)な視点で HTML 要素を選択できるということです。 見た目はあなたが変えることができるものです。

+ +

ひとつの項目を block から inline に、またはその逆に切り替えてデフォルトの表示方法を変更することに加えて、より大きい単位で作用するいくつかのレイアウト手法を display の値を通じて使い始めることができます。 ただし、これらを使用するときは、通常、追加のプロパティを指定する必要があります。 要素のレイアウトを検討する目的において最も重要な値は display: flexdisplay: grid の2つです。

+ +

フレックスボックス

+ +

フレックスボックス(Flexbox)は Flexible Box Layout Module の略称で、行または列のいずれかとして、物を1次元にレイアウトすることを容易にするように設計されています。 フレックスボックスを使うには、display: flex をレイアウトしたい要素の親要素に適用します。 その直接の子はすべてフレックス項目になります。これは簡単な例で見ることができます。

+ +

以下の HTML マークアップは、3つの {{htmlelement("div")}} 要素が入っている wrapper クラスを持つ包含要素を示しています。 デフォルトでは、これらは英語の文書では上下にブロック要素として表示されます。

+ +

ただし、display: flex を親に追加すると、3つの項目は列に配置されます。 これは、それらがフレックス項目になり、フレックスボックスがそれらに与えるいくつかの初期値を使用するためです。 {{cssxref("flex-direction")}} の初期値は row なので、行として表示されます。 {{cssxref("align-items")}} プロパティの初期値は stretch であるため、それらはすべて最も高い項目の高さまで伸びているように見えます。 これは、項目がフレックスコンテナの高さまで伸びることを意味します。 この場合、項目は最も高い項目によって定義されます。 項目はすべてコンテナの先頭に配置され、行の末尾に余分なスペースが残ります。

+ +
+ + +
.wrapper {
+  display: flex;
+}
+
+ +
<div class="wrapper">
+  <div class="box1">One</div>
+  <div class="box2">Two</div>
+  <div class="box3">Three</div>
+</div>
+
+
+ +

{{ EmbedLiveSample('Flex_1', '300', '200') }}

+ +

フレックスコンテナに適用できる上記のプロパティに加えて、フレックス項目に適用できるプロパティがあります。 これらのプロパティは、とりわけ、項目のたわみ方を変えることができ、利用可能なスペースに収まるように項目を拡大および縮小することを可能にします。

+ +

この単純な例として、すべての子項目に 1 の値の {{cssxref("flex")}} プロパティを追加できます。 これにより、末尾にスペースを残すのではなく、すべての項目が拡大してコンテナがいっぱいになります。 より多くのスペースがあるならば、項目はより広くなり、スペースが少ないと狭くなります。 さらに、マークアップに別の要素を追加すると、項目はすべてスペースを空けるために小さくなります — サイズに関係なく、同じ大きさのスペースを占めるようにサイズが調整されます。

+ +
+ + +
.wrapper {
+    display: flex;
+}
+
+.wrapper > div {
+    flex: 1;
+}
+
+ +
<div class="wrapper">
+    <div class="box1">One</div>
+    <div class="box2">Two</div>
+    <div class="box3">Three</div>
+</div>
+
+
+ +

{{ EmbedLiveSample('Flex_2', '300', '200') }}

+ +
+

: これはフレックスボックスで可能なことの非常に短い紹介です。 詳細については、フレックスボックスの記事を参照してください。

+
+ +

グリッドレイアウト

+ +

フレックスボックスは1次元レイアウト用に設計されていますが、グリッドレイアウト(Grid Layout)は2次元用に設計されています — 行と列に物を並べます。

+ +

繰り返しになりますが、display: grid という特定の display の値でグリッドレイアウト(Grid Layout)をオンにすることができます。 以下の例では、コンテナといくつかの子要素とともに、flex の例と同様のマークアップを使用しています。 display: grid の使用に加えて、{{cssxref("grid-template-rows")}} プロパティと {{cssxref("grid-template-columns")}} プロパティをそれぞれ使用して、親の行と列のトラックをいくつか定義します。 それぞれ 1fr の3列と 100px の2行を定義しました。 子要素に規則を置く必要はなく、自動的にグリッドが作成したセルに配置されます。

+ +
+ + +
.wrapper {
+    display: grid;
+    grid-template-columns: 1fr 1fr 1fr;
+    grid-template-rows: 100px 100px;
+    grid-gap: 10px;
+}
+
+ +
<div class="wrapper">
+    <div class="box1">One</div>
+    <div class="box2">Two</div>
+    <div class="box3">Three</div>
+    <div class="box4">Four</div>
+    <div class="box5">Five</div>
+    <div class="box6">Six</div>
+</div>
+
+
+ +

{{ EmbedLiveSample('Grid_1', '300', '330') }}

+ +

グリッドを作成したら、上記の自動配置のふるまいに頼らずに、明示的に項目を配置できます。 以下の2番目の例では、同じグリッドを定義しましたが、今回は3つの子項目を使用しています。 {{cssxref("grid-column")}} プロパティと {{cssxref("grid-row")}} プロパティを使用して各項目の開始ラインと終了ラインを設定しました。 これにより、項目が複数のトラックにまたがるようになります。

+ +
+ + +
.wrapper {
+    display: grid;
+    grid-template-columns: 1fr 1fr 1fr;
+    grid-template-rows: 100px 100px;
+    grid-gap: 10px;
+}
+
+.box1 {
+    grid-column: 2 / 4;
+    grid-row: 1;
+}
+
+.box2 {
+    grid-column: 1;
+    grid-row: 1 / 3;
+}
+
+.box3 {
+    grid-row: 2;
+    grid-column: 3;
+}
+
+ +
<div class="wrapper">
+    <div class="box1">One</div>
+    <div class="box2">Two</div>
+    <div class="box3">Three</div>
+</div>
+
+
+ +

{{ EmbedLiveSample('Grid_2', '300', '330') }}

+ +
+

: これら2つの例は、グリッドレイアウトの機能のほんの一部です。 詳細については、グリッドレイアウトの記事を参照してください。

+
+ +

このガイドの残りの部分では、他のレイアウト方法について説明します。 これは、ページの主なレイアウト構造にとってはそれほど重要ではありませんが、それでも特定のタスクを達成するのに役立ちます。 各レイアウトタスクの性質を理解することで、デザインの特定の構成要素を見たときに、それに最も適したレイアウトの種類が明らかになることがすぐにわかります。

+ +

フロート

+ +

要素を浮動すると、その要素とそれに通常フローで続くブロックレベル要素のふるまいが変わります。 要素が左または右に移動されて通常フローから除かれ、囲むコンテンツが浮動項目の周囲に浮かびます。

+ +

{{cssxref("float")}} プロパティには次の4つの可能な値があります。

+ + + +

以下の例では、<div> を左に浮かべ、テキストを要素から遠ざけるために右に {{cssxref("margin")}} を与えます。 これはそのボックスの周りに巻かれたテキストの効果を与え、そしてあなたが最新のウェブデザインで使用されるフロート(Floats)について知る必要があるものの大部分です。

+ +
+ + +
<h1>Simple float example</h1>
+
+<div class="box">Float</div>
+
+<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
+
+
+ +
+.box {
+    float: left;
+    width: 150px;
+    height: 150px;
+    margin-right: 30px;
+}
+
+
+ +

{{ EmbedLiveSample('Float_1', '100%', 600) }}

+ +
+

: フロートについては、float と clear のプロパティに関するレッスンで詳しく説明しています。 フレックスボックスやグリッドレイアウトなどのテクニックの前は、列レイアウトの作成方法としてフロートが使用されていました。 あなたはまだウェブ上でこれらの方法に出くわすかもしれません。 これらについては、過去のレイアウト方法に関するレッスンで説明します。

+
+ +

位置指定のテクニック

+ +

位置指定(Positioning)を使用すると、通常フローのときに要素を配置されていた場所から別の場所に移動できます。 位置指定はメインページのレイアウトを作成するための方法ではなく、ページ上の特定の項目の位置を管理および微調整することを目的としています。

+ +

ただし、{{cssxref("position")}} プロパティに依存する特定のレイアウトパターンには便利なテクニックがあります。 位置指定を理解することは、通常フローを理解し、項目を通常フローから移動させることとは何かを理解するのに役立ちます。

+ +

あなたが知っておくべき、次の5種類の位置指定があります。

+ + + +

簡単な位置指定の例

+ +

これらのページレイアウトのテクニックに慣れるために、いくつかの簡単な例を紹介します。 例はすべて同じ HTML を特徴とするでしょう。 それは以下の通りです。

+ +
<h1>Positioning</h1>
+
+<p>I am a basic block level element.</p>
+<p class="positioned">I am a basic block level element.</p>
+<p>I am a basic block level element.</p>
+ +

この HTML はデフォルトで次の CSS を使ってスタイルされます。

+ +
body {
+  width: 500px;
+  margin: 0 auto;
+}
+
+p {
+    background-color: rgb(207,232,220);
+    border: 2px solid rgb(79,185,227);
+    padding: 10px;
+    margin: 10px;
+    border-radius: 5px;
+}
+
+ +

レンダリングされた出力は次のとおりです。

+ +

{{ EmbedLiveSample('Simple_positioning_example', '100%', 300) }}

+ +

相対位置指定

+ +

相対位置指定(Relative positioning)を使用すると、デフォルトで設定されている通常フローの位置から項目をずらすことができます。 これは、アイコンをテキストラベルに合わせるためにアイコンを少し下に移動するなどのタスクを実行できることを意味します。 これを行うには、相対位置指定を追加するために次の規則を追加します。

+ +
.positioned {
+  position: relative;
+  top: 30px;
+  left: 30px;
+}
+ +

ここで私たちは真ん中の段落に relative の {{cssxref("position")}} の値を与えます — これはそれ自身では何もしませんので、{{cssxref("top")}} プロパティと {{cssxref("left")}} プロパティも追加します。 これらは影響を受けた要素を右下に動かすのに役立ちます — これはあなたが期待していたのとは反対のように思えるかもしれませんが、要素の左側と上側を押されていると考える必要があり、その結果として右下に移動します。

+ +

このコードを追加すると、次のようになります。

+ +
+ + +
.positioned {
+  position: relative;
+  background: rgba(255,84,104,.3);
+  border: 2px solid rgb(255,84,104);
+  top: 30px;
+  left: 30px;
+}
+
+ +

{{ EmbedLiveSample('Relative_1', '100%', 300) }}

+ +

絶対位置指定

+ +

絶対位置指定(Absolute positioning)は、通常フローから要素を完全に除き、包含ブロックの端からのオフセットを使用して配置するために使用されます。

+ +

元の位置指定のない例に戻ると、絶対位置指定を実装するために次の CSS 規則を追加できます。

+ +
.positioned {
+  position: absolute;
+  top: 30px;
+  left: 30px;
+}
+ +

ここでは、真ん中の段落に absolute の {{cssxref("position")}} の値と、前と同じ {{cssxref("top")}} プロパティと {{cssxref("left")}} プロパティを与えます。 ただし、このコードを追加すると、次のようになります。

+ +
+ + +
.positioned {
+    position: absolute;
+    background: rgba(255,84,104,.3);
+    border: 2px solid rgb(255,84,104);
+    top: 30px;
+    left: 30px;
+}
+
+ +

{{ EmbedLiveSample('Absolute_1', '100%', 300) }}

+ +

これはとても違います! 位置指定要素は、ページレイアウトの残りの部分から完全に分離され、その上に配置されています。 他の2つの段落は、配置された兄弟が存在しないかのように一緒にいます。 {{cssxref("top")}} プロパティと {{cssxref("left")}} プロパティは、絶対位置指定要素に対しては、相対位置指定要素とは異なる効果があります。 この場合、オフセットはページの上側と左側から計算されています。 このコンテナになる親要素を変更することは可能で、位置指定のレッスンでそれを見ます。

+ +

固定位置指定

+ +

固定位置指定(Fixed positioning)は、絶対位置指定と同じ方法で、ドキュメントフローから要素を除きます。 ただし、コンテナからのオフセットが適用されるのではなく、ビューポートからのオフセットが適用されます。 項目がビューポートに対して固定されたままであるので、ページがその下でスクロールするときに固定されたままであるメニューのような効果を作成することができます。

+ +

この例では、HTML を3段落のテキストにして、ページをスクロールさせます。 また、position: fixed を指定したボックスもあります。

+ +
<h1>Fixed positioning</h1>
+
+<div class="positioned">Fixed</div>
+
+<p>Paragraph 1.</p>
+<p>Paragraph 2.</p>
+<p>Paragraph 3.</p>
+
+ +
+ + +
.positioned {
+    position: fixed;
+    top: 30px;
+    left: 30px;
+}
+
+ +

{{ EmbedLiveSample('Fixed_1', '100%', 200) }}

+ +

粘着位置指定

+ +

粘着位置指定(Sticky positioning)は、私たちが自由に使える最後の位置指定方法です。 デフォルトの静的位置指定に固定位置指定を組み合わせたものです。 項目に position: sticky があるとき、それは定義したビューポートからのオフセットにぶつかるまで通常フローでスクロールします。 その時点で、position:fixed が適用されているかのように「動かなくなります」。

+ +
+ + +
.positioned {
+  position: sticky;
+  top: 30px;
+  left: 30px;
+}
+
+ +

{{ EmbedLiveSample('Sticky_1', '100%', 200) }}

+ +
+

: 位置指定の詳細については、位置指定の記事をご覧ください。

+
+ +

表レイアウト

+ +

HTML 表は表形式のデータを表示するのに適していますが、何年も前に — 基本的な CSS でさえブラウザー間で確実にサポートされる前に — ウェブ開発者はウェブページ全体のレイアウトにも表を使用していました — ヘッダー、フッター、異なる列などを、いろいろな表の行と列に配置します。 これは当時はうまくいきましたが、多くの問題を抱えています — 表レイアウトは柔軟性がなく、マークアップが非常に重く、デバッグが難しく、意味論的に間違っています(例えば、スクリーンリーダーのユーザーは表レイアウトをナビゲートするのに問題があります)。

+ +

表のマークアップを使用したときに表がウェブページ上で表示される方法は、表レイアウトを定義する CSS プロパティのセットによるものです。 これらのプロパティは、表ではない要素をレイアウトするために使用することができ、その使用法は「CSS 表の使用」として説明されることがあります。

+ +

以下の例はそのような使い方の1つを示しています。 フレックスボックスやグリッドをサポートしていない非常に古いブラウザーを使用しているような状況では、レイアウトに CSS 表を使用することをこの時点では過去の方法と見なすべきです。

+ +

例を見てみましょう。 まず、HTML フォームを作成する簡単なマークアップです。 各入力要素にはラベルがあり、段落内にキャプションも含まれています。 各ラベル/入力ペアは、レイアウトのために {{htmlelement("div")}} で囲まれています。

+ +
<form>
+  <p>First of all, tell us your name and age.</p>
+  <div>
+    <label for="fname">First name:</label>
+    <input type="text" id="fname">
+  </div>
+  <div>
+    <label for="lname">Last name:</label>
+    <input type="text" id="lname">
+  </div>
+  <div>
+    <label for="age">Age:</label>
+    <input type="text" id="age">
+  </div>
+</form>
+ +

今、私たちの例のための CSS。 {{cssxref("display")}} プロパティの使用方法を除いて、ほとんどの CSS はかなり普通のものです。 {{htmlelement("form")}}、{{htmlelement("div")}}、{{htmlelement("label")}} と {{htmlelement("input")}} は、それぞれ表、表の行、表のセルのように表示されるように指示しています — 基本的に、それらは HTML 表のマークアップのようにふるまい、デフォルトでラベルと入力がうまく並ぶようにします。 あとは、サイズやマージンなどを少し追加するだけで、すべてが少し見栄えよくなります。

+ +

あなたは、キャプションの段落に  display:table-caption; が与えられていることに気付くでしょう — これは表の {{htmlelement("caption")}} のようにふるまいます — そして caption-side: bottom; により、マークアップがソースの <input> 要素の前にある場合でも、スタイル設定の目的でキャプションが表の下部に表示されるようにします。 これにより、かなりの柔軟性が得られます。

+ +
html {
+  font-family: sans-serif;
+}
+
+form {
+  display: table;
+  margin: 0 auto;
+}
+
+form div {
+  display: table-row;
+}
+
+form label, form input {
+  display: table-cell;
+  margin-bottom: 10px;
+}
+
+form label {
+  width: 200px;
+  padding-right: 5%;
+  text-align: right;
+}
+
+form input {
+  width: 300px;
+}
+
+form p {
+  display: table-caption;
+  caption-side: bottom;
+  width: 300px;
+  color: #999;
+  font-style: italic;
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('Table_layout', '100%', '170') }}

+ +

この例は css-tables-example.html でもライブで見ることができます(ソースコードも見る)。

+ +

段組みレイアウト

+ +

段組みレイアウトモジュール(Multi-column layout module)は、新聞のテキストの流れと同じように、コンテンツを列にレイアウトする方法を提供します。 ユーザーに強制的に上下にスクロールさせたくない場合は、列を上下に読むことはウェブのコンテキストではあまり役に立ちませんが、コンテンツを列に配置することは便利なテクニックです。

+ +

ブロックを段組みコンテナに変えるには、次のどちらかを使います。 {{cssxref("column-count")}} プロパティは、ブラウザーにいくつの列を持たせたいかを指示します。 {{cssxref("column-width")}} プロパティは、ブラウザーにその幅以上の列をコンテナに入れるように指示します。

+ +

以下の例では、container クラスを持つ <div> 要素を含む HTML ブロックから始めます。

+ +
<div class="container">
+    <h1>Multi-column layout</h1>
+
+    <p>Paragraph 1.</p>
+    <p>Paragraph 2.</p>
+
+</div>
+
+ +

このコンテナでは 200 ピクセルの column-width を使用しているため、ブラウザーはコンテナに収まるだけの数の 200 ピクセルの列を作成し、作成された列間で残りのスペースを共有します。

+ +
+ + +
    .container {
+        column-width: 200px;
+    }
+
+ +

{{ EmbedLiveSample('Multicol_1', '100%', 200) }}

+ +

まとめ

+ +

この記事では、知っておくべきすべてのレイアウト技術について簡単に説明しました。 個々の技術の詳細については、続けて読んでください!

+ +

{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/legacy_layout_methods/index.html b/files/ja/learn/css/css_layout/legacy_layout_methods/index.html new file mode 100644 index 0000000000..8c1c318e6f --- /dev/null +++ b/files/ja/learn/css/css_layout/legacy_layout_methods/index.html @@ -0,0 +1,588 @@ +--- +title: 過去のレイアウト方法 +slug: Learn/CSS/CSS_layout/Legacy_Layout_Methods +tags: + - Beginner + - CSS + - Floats + - Guide + - Layout + - Learn + - grid system + - legacy +translation_of: Learn/CSS/CSS_layout/Legacy_Layout_Methods +--- +
{{LearnSidebar}}
+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}

+ +

グリッドシステムは CSS レイアウトで使用される非常に一般的な機能で、CSS グリッドレイアウト以前はフロートや他のレイアウト機能を使用して実装される傾向がありました。 あなたはレイアウトをいくつかの列(例えば 4、6、または 12)として想像し、そしてコンテンツの列をこれらの想像上の列の内側に合わせます。 この記事では、古いプロジェクトで作業した場合に、それらがどう使われたかを理解するために、これらの古い方法がどのように機能するのかを説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門ボックスの装飾を学ぶ)。
学習目標:CSS グリッドレイアウトがブラウザーで利用可能になる前に使用されていたグリッドレイアウトシステムの背後にある基本概念を理解すること。
+ +

CSS グリッドレイアウト以前のレイアウトとグリッドシステム

+ +

CSS がごく最近まで内蔵されたグリッドシステムを持っていなかったことを、デザインをやってきた誰かは驚くかもしれません。 そして代わりにグリッドのようなデザインを作成するためにさまざまな次善の方法を用いていたようです。 今これらを「過去の」方法と呼んでいます。

+ +

新しいプロジェクトでは、ほとんどの場合、CSS グリッドレイアウトを他の1つ以上の最新のレイアウト方法と組み合わせて使用​​して、任意のレイアウトの基礎とします。 しかし、時々、これらの過去の方法を使用している「グリッドシステム」に遭遇するでしょう。 それらがどのように機能するのか、そしてなぜそれらが CSS グリッドレイアウトと異なるのかを理解するのは価値があります。

+ +

このレッスンでは、フロートとフレックスボックスに基づいたグリッドシステムとグリッドフレームワークの仕組みについて説明します。 グリッドレイアウトを勉強してきたので、おそらくこれがどれほど複雑であるかに驚くことでしょう! この種のシステムを使用する既存のプロジェクトで作業できるようにすることに加えて、新しい方法をサポートしないブラウザー用の代替コードを作成する必要がある場合に、この知識は役に立ちます。

+ +

これらのシステムを検討する際には、それらのどれも実際には CSS グリッドレイアウトがグリッドを作成する方法でグリッドを作成しないことに、留意する価値があります。 それらは項目にサイズを与え、グリッドのように見えるように一列に並べることによって機能します。

+ +

2列レイアウト

+ +

最も簡単な例として、2列のレイアウトから始めましょう。 コンピュータ上に新しい index.html ファイルを作成し、それを単純な HTML テンプレートで埋め、適切な場所に以下のコードを挿入することで、従うことができます。 このセクションの一番下には、最終的なコードがどのようになっているべきかの実例があります。

+ +

まず最初に、列に入れるためにいくつかのコンテンツが必要です。 次のもので body の中に現在あるものはすべて置き換えます。

+ +
<h1>2 column layout example</h1>
+<div>
+  <h2>First column</h2>
+  <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
+</div>
+
+<div>
+  <h2>Second column</h2>
+  <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
+</div>
+ +

それぞれの列はそのコンテンツを含むために外側の要素が必要です。 この例では {{htmlelement("div")}} を選択しましたが、{{htmlelement("article")}}、{{htmlelement("section")}}、{{htmlelement("aside")}} など、より意味論的に適切なものを選択することもできます。

+ +

今 CSS に対して、まず最初に、HTML に従うため、いくつかの基本的な設定を提供するために次を適用します。

+ +
body {
+  width: 90%;
+  max-width: 900px;
+  margin: 0 auto;
+}
+ +

body の幅が 900px になるまで、body はビューポートの幅の 90% になります。 この場合、body はこの幅に固定され、ビューポートの中央に配置されます。 デフォルトでは、その子({{htmlelement("h1")}} と2つの {{htmlelement("div")}})は body の幅の 100% にわたります。 2つの {{htmlelement("div")}} を互いに並べてフロートしたい場合は、それらの幅の合計をその親要素の幅の 100% 以下に設定して、互いに並んで収まるようにする必要があります。 CSS の最後に次を追加してください。

+ +
div:nth-of-type(1) {
+  width: 48%;
+}
+
+div:nth-of-type(2) {
+  width: 48%;
+}
+ +

ここでは、両方とも親の幅の 48% に設定しました — これは合計 96% で、2列の間のガターのために 4% の空きを残し、コンテンツに余裕を持たせることができます。 さらに次のようにして、列をフロートにする必要があります。

+ +
div:nth-of-type(1) {
+  width: 48%;
+  float: left;
+}
+
+div:nth-of-type(2) {
+  width: 48%;
+  float: right;
+}
+ +

これらすべてをまとめると、次のような結果が得られます。

+ +
+ +
+ +

{{ EmbedLiveSample('Floated_Two_Col', '100%', 520) }}

+ +

ここでは、すべての幅にパーセントを使用していることに気付くでしょう。 これは、さまざまな画面サイズに合わせて調整し、小さい画面サイズで列幅に同じ比率を維持する、リキッドレイアウト(liquid layout)を作成するため、非常に良い戦略です。 ブラウザーウィンドウの幅を調整して確認してください。 これはレスポンシブウェブデザインのための貴重なツールです。

+ +
+

: この例は 0_two-column-layout.html で実行できます(ソースコードも見る)。

+
+ +

単純な過去のグリッドフレームワークを作成する

+ +

過去のフレームワークの大部分は、グリッドのように見えるものを作成するために、{{cssxref("float")}} プロパティのふるまいを使用して、ある列を別の列の隣にフロートします。 フロートによるグリッドを作成するプロセスを通して、これがどのように機能するかを説明し、フロートとクリアのレッスンで学んだことを基にしてさらに高度な概念を紹介します。

+ +

作成する最も簡単な種類のグリッドフレームワークは固定幅のものです — デザインに必要な合計幅、列数、およびガター幅と列幅を求める必要があります。 ブラウザーの幅に合わせて増減する列を含むグリッドにデザインをレイアウトすることにした場合は、列とそれらの間のガターに対してパーセント幅を計算する必要があります。

+ +

次のセクションでは、両方を作成する方法を見ていきます。 12列のグリッドを作成します — 12 が 6、4、3、および 2 で割り切れることを考えると、さまざまな状況に非常に適応できると見られる非常に一般的な選択です。

+ +

単純な固定幅グリッド

+ +

最初に固定幅の列を使用するグリッドシステムを作成しましょう。

+ +

サンプルの simple-grid.html ファイルのローカルコピーを作成することから始めます。 このファイルには、body に次のマークアップが含まれています。

+ +
<div class="wrapper">
+  <div class="row">
+    <div class="col">1</div>
+    <div class="col">2</div>
+    <div class="col">3</div>
+    <div class="col">4</div>
+    <div class="col">5</div>
+    <div class="col">6</div>
+    <div class="col">7</div>
+    <div class="col">8</div>
+    <div class="col">9</div>
+    <div class="col">10</div>
+    <div class="col">11</div>
+    <div class="col">12</div>
+  </div>
+  <div class="row">
+    <div class="col span1">13</div>
+    <div class="col span6">14</div>
+    <div class="col span3">15</div>
+    <div class="col span2">16</div>
+  </div>
+</div>
+ +

目的は、これを 12 列 2 行のグリッドのデモ用グリッドに変換することです — 一番上の行は個々の列のサイズを示し、2番目の行はグリッド上のいくつかの異なるサイズの領域です。

+ +

+ +

{{htmlelement("style")}} 要素に、次のコードを追加します。 これにより、wrapper コンテナの幅は 980 ピクセルになり、右側のパディングは 20 ピクセルになります。 これにより、列幅とガター幅の合計が 960 ピクセルになります — この場合、サイト上のすべての要素で {{cssxref("box-sizing")}} を border-box に設定しているため、パディングはコンテンツの幅の合計から差し引かれます(詳細については、ボックスモデルの完全な変更を参照)。

+ +
* {
+  box-sizing: border-box;
+}
+
+body {
+  width: 980px;
+  margin: 0 auto;
+}
+
+.wrapper {
+  padding-right: 20px;
+}
+ +

次に、グリッドの各行を囲む row コンテナを使用して、ある行を別の行からクリアします。 前の規則の下に次の規則を追加します。

+ +
.row {
+  clear: both;
+}
+ +

このクリアを適用すると、各行を12列の要素で完全に埋める必要がなくなります。 行は分離されたままになり、互いに干渉しません。

+ +

列の間のガターは 20 ピクセル幅です。 最初の列を含め、各列の左側にマージンとしてこれらのガターを作成して、コンテナの右側にある 20 ピクセルのパディングとのバランスを取ります。 だから全部で12のガターを持っています — 12 x 20 = 240。

+ +

これを 960 ピクセルの合計幅から差し引いて、列に 720 ピクセルを与える必要があります。 これを 12 で割ると、各列の幅は 60 ピクセルになるはずです。

+ +

次のステップは、.col クラスの規則を作成し、それを左にフロートして、ガターを形成する 20 ピクセルの {{cssxref("margin-left")}} と、60 ピクセルの {{cssxref("width")}} を与えることです。 CSS の最後に次の規則を追加してください。

+ +
.col {
+  float: left;
+  margin-left: 20px;
+  width: 60px;
+  background: rgb(255, 150, 150);
+}
+ +

これで、一番上の単一列の行がグリッドとしてきちんとレイアウトされます。

+ +
+

: また、各列に薄い赤色を指定したので、各列がどれだけのスペースを占めているかを正確に確認できます。

+
+ +

複数列にまたがるコンテナのレイアウトには、必要な列数(足す、その間のガター)に合わせて {{cssxref("width")}} の値を調整するための特別なクラスを指定する必要があります。 コンテナが2〜12列にまたがるようにするために、追加のクラスを作成する必要があります。 それぞれの幅は、その列数の列幅にガター幅を加えた結果です。 ガター幅は常に列数より1つ少なくなります。

+ +

CSS の最後に次を追加してください。

+ +
/* Two column widths (120px) plus one gutter width (20px) */
+.col.span2 { width: 140px; }
+/* Three column widths (180px) plus two gutter widths (40px) */
+.col.span3 { width: 220px; }
+/* And so on... */
+.col.span4 { width: 300px; }
+.col.span5 { width: 380px; }
+.col.span6 { width: 460px; }
+.col.span7 { width: 540px; }
+.col.span8 { width: 620px; }
+.col.span9 { width: 700px; }
+.col.span10 { width: 780px; }
+.col.span11 { width: 860px; }
+.col.span12 { width: 940px; }
+ +

これらのクラスを作成したら、グリッド上にさまざまな幅の列を配置できます。 効果を確認するには、ページを保存してブラウザーでロードします。

+ +
+

: 上記の例がうまくいかない場合は、GitHub の完成版と比較してみてください(ライブでも見られます)。

+
+ +

要素のクラスを変更したり、コンテナを追加したり削除したりして、レイアウトの変更方法を確認してください。 例えば、2行目を次のようにすることができます。

+ +
<div class="row">
+  <div class="col span8">13</div>
+  <div class="col span4">14</div>
+</div>
+ +

これで、グリッドシステムが機能したので、単純に行と各行の列数を定義してから、各コンテナに必要なコンテンツを埋めるだけです。 すばらしいです!

+ +

フルードグリッドを作成する

+ +

私たちのグリッドはうまく機能しますが、幅は固定されています。 ブラウザーの{{Glossary("viewport","ビューポート")}}で利用可能なスペースに応じて拡大縮小する柔軟な(フルード(fluid、流動的な))グリッドが本当に必要です。 これを実現するために、参照するピクセル幅をパーセントに変えることができます。

+ +

固定幅を柔軟なパーセントベースのものに変換する式は次のとおりです。

+ +
target / context = result
+ +

列幅については、目標の幅(target width)は 60 ピクセル、コンテキスト(context)は 960 ピクセルの wrapper です。 パーセントを計算するために次のようにします。

+ +
60 / 960 = 0.0625
+ +

次に小数点を2桁移動して、6.25% のパーセントを得ます。 したがって、私たちの CSS では、60 ピクセルの列幅を 6.25% に置き換えることができます。

+ +

ガター幅についても次のように同じことをする必要があります。

+ +
20 / 960 = 0.02083333333
+ +

そのため、.col 規則の 20 ピクセルの {{cssxref("margin-left")}} と、.wrapper 規則の 20 ピクセルの {{cssxref("padding-right")}} を 2.08333333% に置き換える必要があります。

+ +

グリッドを更新する

+ +

このセクションで始めるには、前のサンプルページの新しいコピーを作成するか、または出発点として使用するために simple-grid-finished.html コードのローカルコピーを作成してください。

+ +

次のように(.wrapper セレクターの)2番目の CSS 規則を更新します。

+ +
body {
+  width: 90%;
+  max-width: 980px;
+  margin: 0 auto;
+}
+
+.wrapper {
+  padding-right: 2.08333333%;
+}
+ +

パーセントの {{cssxref("width")}} を指定しただけでなく、レイアウトが広くなり過ぎるのを防ぐために {{cssxref("max-width")}} プロパティも追加しました。

+ +

次に、(.col セレクターの)4番目の CSS 規則を次のように更新します。

+ +
.col {
+  float: left;
+  margin-left: 2.08333333%;
+  width: 6.25%;
+  background: rgb(255, 150, 150);
+}
+ +

もう少し面倒な部分があります。 ピクセル幅ではなくパーセントを使用するようにすべての .col.span 規則を更新する必要があります。 これは電卓で少し時間がかかります。 あなたの努力を節約するために、それを下に用意しました。

+ +

次のように CSS 規則の一番下のブロックを更新します。

+ +
/* Two column widths (12.5%) plus one gutter width (2.08333333%) */
+.col.span2 { width: 14.58333333%; }
+/* Three column widths (18.75%) plus two gutter widths (4.1666666) */
+.col.span3 { width: 22.91666666%; }
+/* And so on... */
+.col.span4 { width: 31.24999999%; }
+.col.span5 { width: 39.58333332%; }
+.col.span6 { width: 47.91666665%; }
+.col.span7 { width: 56.24999998%; }
+.col.span8 { width: 64.58333331%; }
+.col.span9 { width: 72.91666664%; }
+.col.span10 { width: 81.24999997%; }
+.col.span11 { width: 89.5833333%; }
+.col.span12 { width: 97.91666663%; }
+ +

コードを保存してブラウザーにロードし、ビューポートの幅を変更してみます — 列の幅は適切に調整されるはずです。

+ +
+

: 上記の例がうまくいかない場合は、GitHub の完成版と比較してみてください(ライブでも見られます)。

+
+ +

calc() 関数を使ったより簡単な計算

+ +

CSS のすぐ内側で {{cssxref("calc","calc()")}} 関数を使って数学を行うことができます — これは CSS の値に簡単な数学の方程式を挿入して、値が何であるべきかを計算することを可能にします。 複雑な計算が必要な場合に特に便利です。 例えば、「この要素の高さは、常に親の高さの 100% から 50px を引いた値です」など、さまざまな単位を使用した計算も計算できます。 MediaRecorder API のチュートリアルからこの例を参照してください。

+ +

とにかく、私たちのグリッドに戻りましょう! グリッドの複数の列にまたがる列は、合計幅が 6.25% x またがる列の数 + 2.08333333% x ガターの数(常に列の数 - 1)になります。 calc() 関数を使用すると、width の値の内側でこの計算を実行できます。 そのため、例えば、4列にまたがる項目であれば、次のようにします。

+ +
.col.span4 {
+  width: calc((6.25%*4) + (2.08333333%*3));
+}
+ +

規則の一番下のブロックを次のように置き換えてから、ブラウザーにリロードして、同じ結果になるかどうかを確認します。

+ +
.col.span2 { width: calc((6.25%*2) + 2.08333333%); }
+.col.span3 { width: calc((6.25%*3) + (2.08333333%*2)); }
+.col.span4 { width: calc((6.25%*4) + (2.08333333%*3)); }
+.col.span5 { width: calc((6.25%*5) + (2.08333333%*4)); }
+.col.span6 { width: calc((6.25%*6) + (2.08333333%*5)); }
+.col.span7 { width: calc((6.25%*7) + (2.08333333%*6)); }
+.col.span8 { width: calc((6.25%*8) + (2.08333333%*7)); }
+.col.span9 { width: calc((6.25%*9) + (2.08333333%*8)); }
+.col.span10 { width: calc((6.25%*10) + (2.08333333%*9)); }
+.col.span11 { width: calc((6.25%*11) + (2.08333333%*10)); }
+.col.span12 { width: calc((6.25%*12) + (2.08333333%*11)); }
+ +
+

: fluid-grid-calc.html で完成版を見ることができます(ライブでも見られます)。

+
+ +
+

: これがうまくいかない場合は、ブラウザーが calc() 関数をサポートしていないことが考えられます。 ブラウザー間ではかなりよくサポートされています — IE9 までさかのぼります。

+
+ +

意味論的グリッドシステム対「意味論的でない」グリッドシステム

+ +

マークアップにクラスを追加してレイアウトを定義するということは、コンテンツとマークアップが視覚的表現に結び付くことを意味します。 この CSS クラスの使い方は、コンテンツを説明するクラスの意味論的な使い方ではなく、「意味論的でない」(コンテンツがどのように見えるかを説明する)ものとして説明されることがあります。 これは、span2span3 などのクラスの場合です。

+ +

これらが唯一のアプローチではありません。 代わりにグリッドを決定してから、サイズ情報を既存の意味論的クラスの規則に追加することができます。 例えば、8列にまたがる content のクラスが {{htmlelement("div")}} にある場合は、span8 のクラスから width をコピーして、次のような規則を指定できます。

+ +
.content {
+  width: calc((6.25%*8) + (2.08333333%*7));
+}
+ +
+

: Sass などのプリプロセッサを使用する場合は、単純な mixin を作成してその値を挿入することができます。

+
+ +

グリッドでオフセットしたコンテナを使えるようにする

+ +

作成したグリッドは、すべてのコンテナをグリッドの左側から始めてぴったり重ねる限り、うまく機能します。 最初のコンテナの前(または、コンテナ間)に空の列スペースを残したい場合は、視覚的にグリッドを横切って押すための左マージンを追加するためのオフセットクラスを作成する必要があります。 もっと数学!

+ +

これを試してみましょう。

+ +

以前のコードから始めるか、出発点として fluid-grid.html ファイルを使用してください。

+ +

CSS でコンテナ要素を1列幅だけオフセットするクラスを作成しましょう。 CSS の最後に次を追加してください。

+ +
.offset-by-one {
+  margin-left: calc(6.25% + (2.08333333%*2));
+}
+ +

パーセントを自分で計算したい場合は、こちらを使用してください。

+ +
.offset-by-one {
+  margin-left: 10.41666666%;
+}
+ +

これで、このクラスを左側に1列幅の空きスペースに残したいコンテナに追加できます。 例えば、HTML に次のものがあるとします。

+ +
<div class="col span6">14</div>
+ +

これを次に置き換えてみてください。

+ +
<div class="col span5 offset-by-one">14</div>
+ +
+

: オフセット用のスペースを確保するために、またがる列の数を減らす必要があることに注意してください!

+
+ +

違いを確認するには、ロードとリフレッシュを試してみるか、fluid-grid-offset.html の例を確認してください(ライブでも見られます)。 完成した例は次のようになります。

+ +

+ +
+

: 特別な演習として、offset-by-two クラスを実装できますか?

+
+ +

フロートのグリッドの制限

+ +

このようなシステムを使用するときは、合計幅が正しく加算され、行に含むことができるよりも多くの列にまたがる要素を行に含めないように注意する必要があります。 フロートの機能のために、グリッドの列の数がグリッドに対して広くなりすぎると、最後の要素が次のラインにドロップダウンされ、グリッドが壊れます。

+ +

また、要素のコンテンツがそれらが占める行よりも広くなると、オーバーフローしてだらしなく見えることも覚えておいてください。

+ +

このシステムの最大の制限は、それが本質的に一次元であるということです。 私たちは列を扱っていて、要素は列にまたがっていますが、行には及んでいません。 これらの古いレイアウト方法では、高さを明示的に設定せずに要素の高さを制御することは非常に困難で、これも非常に柔軟性のない方法です — コンテンツが一定の高さになることを保証できる場合にのみ機能します。

+ +

フレックスボックスのグリッド?

+ +

以前のフレックスボックスに関する記事を読んだことがあれば、フレックスボックスがグリッドシステムを作成するための理想的な解決策であると考えるかもしれません。 利用可能な多くのフレックスボックスベースのグリッドシステムがあり、フレックスボックスは上記のグリッドを作成するときに私たちがすでに発見した問題の多くを解決することができます。

+ +

ただし、フレックスボックスはグリッドシステムとして設計されたことはなく、その1つとして使用すると新しい一連の問題が発生します。 この簡単な例として、上記で使用したのと同じマークアップ例を使用し、次の CSS を使用して wrapperrowcol クラスをスタイルすることができます。

+ +
body {
+  width: 90%;
+  max-width: 980px;
+  margin: 0 auto;
+}
+
+.wrapper {
+  padding-right: 2.08333333%;
+}
+
+
+.row {
+  display: flex;
+}
+
+.col {
+  margin-left: 2.08333333%;
+  margin-bottom: 1em;
+  width: 6.25%;
+  flex: 1 1 auto;
+  background: rgb(255,150,150);
+}
+ +

あなた自身の例でこれらの置き換えをすることを試みるか、または flexbox-grid.html の例のコードを見ることができます(ライブでも見られます)。

+ +

ここで各行をフレックスコンテナに変えています。 フレックスボックスベースのグリッドでは、合計が 100% 未満の要素を持つことができるようにするために、まだ行が必要です。 そのコンテナを display: flex に設定します。

+ +

.col では、{{cssxref("flex")}} プロパティの最初の値({{cssxref("flex-grow")}})を 1 に設定して項目を大きくできるようにし、2番目の値({{cssxref("flex-shrink")}})を 1 にして項目を縮小できるようにし、3番目の値({{cssxref("flex-basis")}})を auto に設定します。 この要素には {{cssxref("width")}} が設定されているので、auto はその幅を flex-basis の値として使用します。

+ +

一番上のラインでは、グリッド上に12個のきちんとしたボックスが表示され、ビューポートの幅を変更すると、それらは均等に拡大および縮小されます。 しかし、次のラインでは、4つの項目しかなく、これらも基本の 60px から増減しています。 それらのうちの4つだけで、それらは上の行の項目よりもはるかに大きく成長することができ、その結果、それらはすべて2番目の行で同じ幅を占めます。

+ +

+ +

これを修正するには、その要素に対して flex-basis によって使用される値を置き換える幅を提供するために、span クラスを含める必要があります。

+ +

それらは、直上の項目について何も知らないので、直上の項目によって使用されるグリッドを尊重もしません。

+ +

フレックスボックスは設計上一次元です。 それは単一の次元、つまり行または列の次元を扱います。 列と行に厳密なグリッドを作成することはできません。 つまり、グリッドにフレックスボックスを使用する場合でも、フロートのレイアウトの場合と同様にパーセントを計算する必要があります。

+ +

プロジェクトでは、フレックスボックスがフロートを介して提供する追加の位置合わせとスペース分配機能のために、フレックスボックスの「グリッド」を使用することを選択することもできます。 しかし、設計されたもの以外の何かのためのツールを使っているのだということを知っているべきです。 だからあなたは望む最終結果を得るために、それが追加の輪くぐりの輪を飛び越えさせているように感じているかもしれません。

+ +

サードパーティのグリッドシステム

+ +

グリッド計算の背後にある数学を理解したので、一般的に使用されているサードパーティのグリッドシステムのいくつかを検討するのに適した状況です。 ウェブ上で「CSS Grid framework」を検索すると、膨大な選択肢のリストが見つかるでしょう。 BootstrapFoundation などの人気のあるフレームワークには、グリッドシステムが含まれています。 CSS やプリプロセッサを使用して開発されたスタンドアロンのグリッドシステムもあります。

+ +

グリッドフレームワークを扱うための一般的なテクニックを説明しているので、これらのスタンドアロンシステムの1つを見てみましょう。これから使用するグリッドは、単純な CSS フレームワークである Skeleton の一部です。

+ +

はじめに Skeleton のウェブサイトにアクセスし、「Download」を選択して ZIP ファイルをダウンロードします。 これを解凍し、skeleton.css ファイルと normalize.css ファイルを新しいディレクトリにコピーします。

+ +

html-skeleton.html ファイルのコピーを作成し、それを skeleton.cssnormalize.css と同じディレクトリに保存します。

+ +

その head に次を追加することによって、skeleton.cssnormalize.css を HTML ページに含めます。

+ +
<link href="normalize.css" rel="stylesheet">
+<link href="skeleton.css" rel="stylesheet">
+ +

Skeleton にはグリッドシステム以上のものが含まれています — タイポグラフィや、出発点として使用できるその他のページ要素の CSS も含んでいます。 ただし、これらはデフォルトのままにします — ここで本当に関心があるのはグリッドです。

+ +
+

: Normalize は Nicolas Gallagher によって書かれた本当に便利で小さな CSS ライブラリです。 これは基本的ないくつかの基本的なレイアウトの修正を自動的に行い、ブラウザー間でデフォルトの要素のスタイル設定をより一貫させます。

+
+ +

前の例と同様の HTML を使用します。 HTML の body に次を追加してください。

+ +
<div class="container">
+  <div class="row">
+    <div class="col">1</div>
+    <div class="col">2</div>
+    <div class="col">3</div>
+    <div class="col">4</div>
+    <div class="col">5</div>
+    <div class="col">6</div>
+    <div class="col">7</div>
+    <div class="col">8</div>
+    <div class="col">9</div>
+    <div class="col">10</div>
+    <div class="col">11</div>
+    <div class="col">12</div>
+  </div>
+  <div class="row">
+    <div class="col">13</div>
+    <div class="col">14</div>
+    <div class="col">15</div>
+    <div class="col">16</div>
+  </div>
+</div>
+ +


+ Skeleton を使い始めるためには、ラッパーの {{htmlelement("div")}} に container クラスを与える必要があります — これは既に HTML に含まれています。 これにより、最大幅 960 ピクセルのコンテンツが中央に配置されます。 ボックスが 960 ピクセルよりも広くならないことがわかります。

+ +

このクラスを適用するときに使用される CSS を見るために skeleton.css ファイルを見ることができます。 <div>auto の左右のマージンで中央に配置され、左右に 20 ピクセルのパディングが適用されます。 Skeleton はまた、先ほど行ったように {{cssxref("box-sizing")}} プロパティを border-box に設定するので、この要素のパディングとボーダーは合計幅に含まれます。

+ +
.container {
+  position: relative;
+  width: 100%;
+  max-width: 960px;
+  margin: 0 auto;
+  padding: 0 20px;
+  box-sizing: border-box;
+}
+ +

要素が行内にある場合にのみ要素をグリッドの一部にすることができます。 前の例と同様に、content <div> と実際のコンテンツコンテナの <div> の間にネストした row クラスを持つ追加の <div> またはその他の要素が必要です。 これも既に行ってあります。

+ +

それではコンテナボックスをレイアウトしましょう。 Skeleton は12列グリッドに基づいています。 一番上のラインのボックスはすべて、1列にまたがるようにするために one column クラスが必要です。

+ +

次のスニペットに示すように、これらを追加します。

+ +
<div class="container">
+  <div class="row">
+    <div class="one column">1</div>
+    <div class="one column">2</div>
+    <div class="one column">3</div>
+    /* and so on */
+  </div>
+</div>
+ +

次に、2番目の row クラスのコンテナに、それらがまたがるべき列数を説明します。

+ +
<div class="row">
+  <div class="one column">13</div>
+  <div class="six columns">14</div>
+  <div class="three columns">15</div>
+  <div class="two columns">16</div>
+</div>
+ +

HTML ファイルを保存してブラウザーにロードして、効果を確認してください。

+ +
+

: この例がうまく動作しない場合は、html-skeleton-finished.html ファイルと比較してみてください(ライブでも見られます)。

+
+ +

skeleton.css ファイルを見ると、これがどのように機能するかがわかります。 例えば、Skeleton には、「three columns」クラスを追加して要素をスタイルするための次の定義があります。

+ +
.three.columns { width: 22%; }
+ +

Skeleton(または他のグリッドフレームワーク)が行っていることはすべて、マークアップに追加することで使用できる定義済みクラスを設定することだけです。 これらのパーセントを自分で計算する作業を行ったのとまったく同じです。

+ +

ご覧のとおり、Skeleton を使用するときには、CSS をほとんど書く必要がありません。 マークアップにクラスを追加すると、すべてのフロートが処理されます。 グリッドシステムのフレームワークを使用することを説得力のある選択にしたのは、レイアウトに対する責任を他に引き継ぐ、この能力です! しかし最近では、CSS グリッドレイアウトを使用して、多くの開発者がこれらのフレームワークから CSS が提供する内蔵されたネイティブグリッドを使用するように移行しています。

+ +

まとめ

+ +

これで、さまざまなグリッドシステムの作成方法が理解できました。 これは、古いサイトでの作業や、CSS グリッドレイアウトのネイティブグリッドとこれらの古いシステムとの違いの理解に役立ちます。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout/Supporting_Older_Browsers", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/media_queries/index.html b/files/ja/learn/css/css_layout/media_queries/index.html new file mode 100644 index 0000000000..6cfb1366b1 --- /dev/null +++ b/files/ja/learn/css/css_layout/media_queries/index.html @@ -0,0 +1,445 @@ +--- +title: メディアクエリーの初心者向けガイド +slug: Learn/CSS/CSS_layout/Media_queries +tags: + - Beginner + - CSS + - Layout + - Learn + - media query +translation_of: Learn/CSS/CSS_layout/Media_queries +--- +

{{learnsidebar}}{{PreviousMenuNext("Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout/Legacy_Layout_Methods", "Learn/CSS/CSS_layout")}}

+ +

CSS メディアクエリー(CSS Media Query)を使用すると、例えば、「ビューポートは 480 ピクセルよりも広い」というような、ブラウザーとデバイスの環境が指定した規則に一致する場合にのみ CSS を適用できます。 メディアクエリーは、ビューポートのサイズに応じて異なるレイアウトを作成できるため、レスポンシブ Web デザイン(responsive web design、RWD)の重要な部分ですが、例えば、ユーザーはマウスではなくタッチスクリーンを使用しているというような、サイトが実行されている環境に関する他のものを検出するためにも使用できます。 このレッスンでは、最初にメディアクエリーで使用される構文について学習し、次に単純なデザインでどのようにレスポンシブにするかを示す実際の例で使用してみます。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS の第一歩CSS の構成要素を学ぶ)。
学習目標:メディアクエリーの使用方法、およびそれらを使用してレスポンシブデザインを作成するための最も一般的なアプローチを理解する。
+ +

メディアクエリーの基本

+ +

最も単純なメディアクエリーの構文は次のようになります。

+ +
@media media-type and (media-feature-rule) {
+  /* CSS 規則をここに */
+}
+ +

これは、次のもので構成されます。

+ + + +

メディアタイプ

+ +

指定できるメディアの種類は次のとおりです。

+ + + +

次のメディアクエリーは、ページが印刷される場合にのみ body12pt に設定します。 ページがブラウザーにロードされるときは適用されません。

+ +
@media print {
+    body {
+        font-size: 12pt;
+    }
+}
+ +
+

: ここでのメディアタイプは、いわゆる {{glossary("MIME type","MIME タイプ")}}とは異なります。

+
+ +
+

: レベル3のメディアクエリー仕様には、他にも多くのメディアタイプが定義されています。 これらは非推奨であり、避けるべきです。

+
+ +
+

: メディアタイプはオプションです。 メディアクエリーでメディアタイプを指定しない場合、メディアクエリーはデフォルトですべてのメディアタイプ用になります。

+
+ +

メディア特性の規則

+ +

タイプを指定したら、規則を使用してメディア特性(media feature)を対象にできます。

+ +

幅と高さ

+ +

レスポンシブデザインを作成するために最も頻繁に検出される特性(そして広範なブラウザーサポートを備えた特性)は、ビューポートの幅で、ビューポートが特定の幅よりも上または下にある(または正確な幅の)場合に、CSS を適用できます。 これには、min-widthmax-widthwidth のメディア特性を使用します。

+ +

これらの特性は、さまざまな画面サイズに対応するレイアウトを作成するために使用されます。 例えば、ビューポートが正確に 600 ピクセルの場合に body のテキストの色を赤に変更するには、次のメディアクエリーを使用します。

+ +
@media screen and (width: 600px) {
+    body {
+        color: red;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

width(および height)のメディア特性は範囲として使用でき、min- または max- を前に付けて、指定された値が最小または最大であることを示します。 例えば、ビューポートが 600 ピクセルより狭い場合に色を青にするには、次のように max-width を使用します。

+ +
@media screen and (max-width: 600px) {
+    body {
+        color: blue;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

実際には、レスポンシブデザインでは最小値または最大値を使用する方がはるかに便利であるため、width または height を単独で使用することはほとんどありません。

+ +

テストできるメディア特性は他にも多数ありますが、メディアクエリー仕様のレベル4および5で導入された新しい特性の一部は、ブラウザーサポートが制限されています。 各特性は、ブラウザーサポート情報とともに MDN で文書化されていて、完全なリストは、メディアクエリーの使用: メディア特性で見つけることができます。

+ +

オリエンテーション

+ +

よくサポートされているメディア特性の1つはオリエンテーション(orientation)です。 これにより、ポートレートモード(portrait mode、肖像画のような縦長)またはランドスケープモード(landscape mode、風景画のような横長)をテストできます。 デバイスがランドスケープの場合に本文の色を変更するには、次のメディアクエリーを使用します。

+ +
@media (orientation: landscape) {
+    body {
+        color: rebeccapurple;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

標準のデスクトップビューはランドスケープであり、このオリエンテーションで適切に機能するデザインは、ポートレートモードの携帯電話またはタブレットで表示した場合に機能しない場合があります。 オリエンテーションのテストは、ポートレートモードのデバイス用に最適化されたレイアウトの作成に役立ちます。

+ +

ポインティングデバイスの使用

+ +

レベル4仕様の一部として、ホバー(hover)メディア特性が導入されました。 この特性は、ユーザーが要素の上にポインターを乗せることができるかどうかをテストできることを意味します。 つまり、本質的に何らかのポインティングデバイスを使用していることを意味します。 タッチスクリーンとキーボードナビゲーションはホバーしません。

+ +
@media (hover: hover) {
+    body {
+        color: rebeccapurple;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

ユーザーがホバーできないことがわかっている場合、デフォルトでいくつかのインタラクティブ機能を表示できます。 ホバーできるユーザーの場合、リンクの上にポインターを乗せたときにそれらを利用可能にすることを選択できます。

+ +

レベル4には、ポインター(pointer)メディア特性もあります。 これには、none(なし)、fine(細かい)、coarse(粗い)の3つの値があります。 fine ポインターは、マウスやトラックパッドのようなものです。 これにより、ユーザーは狭い領域を正確に対象にすることができます。 coarse ポインターは、タッチスクリーン上の指です。 値 none は、ユーザーにポインティングデバイスがないことを意味し、おそらく、キーボードのみ、または音声コマンドでナビゲートしています。

+ +

pointer を使用すると、ユーザーが画面に対して行っている操作の種類に対応する、より優れたインターフェイスを設計できます。 例えば、ユーザーがタッチスクリーンでデバイスと対話していることがわかっている場合、より大きなヒット領域を作成できます。

+ +

より複雑なメディアクエリー

+ +

考えられるさまざまなメディアクエリーのすべてを使用して、それらを組み合わせたり、いずれにも一致する可能性があるクエリーのリストを作成したりすることができます。

+ +

メディアクエリーの "and" 論理

+ +

メディア特性を組み合わせるには、上記で and を使用してメディアタイプとメディア特性を組み合わせるのとほぼ同じ方法で and を使用できます。 例えば、min-widthorientation をテストする場合があります。 ビューポートの幅が少なくとも 600 ピクセルで、デバイスがランドスケープモードの場合にのみ body のテキストは青色になります。

+ +
@media screen and (min-width: 600px) and (orientation: landscape) {
+    body {
+        color: blue;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

メディアクエリーの "or" 論理

+ +

クエリーのセットがあり、そのいずれかが一致する場合、これらのクエリーをコンマで区切ることができます。 次の例では、ビューポートの幅が少なくとも 600 ピクセルの場合、またはデバイスがランドスケープの場合、テキストは青になります。 これらのいずれかが当てはまる場合、クエリーは一致します。

+ +
@media screen and (min-width: 600px), screen and (orientation: landscape) {
+    body {
+        color: blue;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

メディアクエリーの "not" 論理

+ +

not 演算子を使用して、メディアクエリー全体を否定することができます。 これにより、メディアクエリー全体の意味が逆になります。 したがって、次の例では、オリエンテーションがポートレートの場合にのみテキストが青になります。

+ +
@media not all and (orientation: landscape) {
+    body {
+        color: blue;
+    }
+}
+ +

ブラウザーでこの例を開くか、ソースを表示します。

+ +

ブレークポイントの選択方法

+ +

レスポンシブデザインの初期には、多くのデザイナーが非常に具体的な画面サイズを対象にしようとしました。 人気のある携帯電話やタブレットの画面のサイズのリストは、それらのビューポートにきちんと一致するデザインを作成できるように公開されました。

+ +

現在、非常に多様なサイズのデバイスが多すぎて、それを実現できません。 つまり、すべてのデザインにおいて特定のサイズを対象にするのではなく、コンテンツが何らかの方法で壊れ始める(starts to break)サイズでデザインを変更することをお勧めします。 おそらく、行の長さが非常に長くなるか、枠で囲まれたサイドバーが押しつぶされて読みにくくなります。 これが、メディアクエリーを使用して、使用可能なスペースに合わせてデザインをより良いものに変更するポイントです。 このアプローチは、使用されているデバイスの正確な寸法は問題ではなく、あらゆる範囲に対応できることを意味します。 メディアクエリーが導入されるポイントは、ブレークポイント(breakpoints)と呼ばれます。

+ +

Firefox 開発ツールのレスポンシブデザインモードは、これらのブレークポイントがどこに行くべきかを判断するのに非常に便利です。 メディアクエリーを追加してデザインを微調整しながら、ビューポートを小さくしたり大きくしたりして、コンテンツが改善される場所を簡単に確認できます。

+ +

Firefox 開発ツールのモバイルビューのレイアウトのスクリーンショット。

+ +

能動的学習: モバイルファースト レスポンシブデザイン

+ +

レスポンシブデザインには、大きく分けて2つのアプローチがあります。 デスクトップまたは最も広いビューから始めて、ビューポートが小さくなるにつれて並べ替えるためのブレークポイントを追加するか、最小のビューから始めて、ビューポートが大きくなるにつれてレイアウトを追加することができます。 この2番目のアプローチは、モバイルファースト レスポンシブデザインと呼ばれ、多くの場合、従うべき最善のアプローチです。

+ +

非常に小さなデバイスのビューは、通常フローで見られるように、多くの場合、コンテンツの単純な1列です。 これは、小さなデバイスに対して多くのレイアウトを行う必要がほとんどないことを意味します — ソースを適切な順序にすれば、デフォルトで読みやすいレイアウトになります。

+ +

以下のチュートリアルでは、非常に単純なレイアウトでこのアプローチを説明します。 実稼働サイトでは、メディアクエリー内で調整する必要があるものが多くありますが、アプローチはまったく同じです。

+ +

チュートリアル: 単純なモバイルファーストのレイアウト

+ +

出発点は、レイアウトのさまざまな部分に背景色を追加するために CSS を適用した HTML ドキュメントです。

+ +
* {
+    box-sizing: border-box;
+}
+
+body {
+    width: 90%;
+    margin: 2em auto;
+    font: 1em/1.3 Arial, Helvetica, sans-serif;
+}
+
+a:link,
+a:visited {
+    color: #333;
+}
+
+nav ul,
+aside ul {
+    list-style: none;
+    padding: 0;
+}
+
+nav a:link,
+nav a:visited {
+    background-color: rgba(207, 232, 220, 0.2);
+    border: 2px solid rgb(79, 185, 227);
+    text-decoration: none;
+    display: block;
+    padding: 10px;
+    color: #333;
+    font-weight: bold;
+}
+
+nav a:hover {
+    background-color: rgba(207, 232, 220, 0.7);
+}
+
+.related {
+    background-color: rgba(79, 185, 227, 0.3);
+    border: 1px solid rgb(79, 185, 227);
+    padding: 10px;
+}
+
+.sidebar {
+    background-color: rgba(207, 232, 220, 0.5);
+    padding: 10px;
+}
+
+article {
+    margin-bottom: 1em;
+}
+
+ +

レイアウトの変更は行っていませんが、ドキュメントのソースはコンテンツが読みやすいように並べられています。 これは重要な最初のステップであり、コンテンツがスクリーンリーダーで読み上げられる場合に理解できるようにするものです。

+ +
<body>
+    <div class="wrapper">
+      <header>
+        <nav>
+          <ul>
+            <li><a href="">About</a></li>
+            <li><a href="">Contact</a></li>
+            <li><a href="">Meet the team</a></li>
+            <li><a href="">Blog</a></li>
+          </ul>
+        </nav>
+      </header>
+      <main>
+        <article>
+          <div class="content">
+            <h1>Veggies!</h1>
+            <p>
+              ...
+            </p>
+          </div>
+          <aside class="related">
+            <p>
+              ...
+            </p>
+          </aside>
+        </article>
+
+        <aside class="sidebar">
+          <h2>External vegetable-based links</h2>
+          <ul>
+            <li>
+              ...
+            </li>
+          </ul>
+        </aside>
+      </main>
+
+      <footer><p>&copy;2019</p></footer>
+    </div>
+  </body>
+
+ +

この単純なレイアウトはモバイルでもうまく機能します。 開発ツールのレスポンシブデザインモードでレイアウトを眺めると、サイトのモバイルビューそのものと同じように機能することがわかります。

+ +

ブラウザーでステップ1を開くか、ソースを表示します。

+ +

この例をフォローして実装してみたい場合は、コンピューターに step1.html のローカルコピーを作成します。

+ +

このポイントから、行の長さが非常に長くなり、ナビゲーションのためのスペースが水平線で表示されるまで、レスポンシブデザインモードのビューのドラッグを始めます。 これが、最初のメディアクエリーを追加する場所です。 em を使用すると、ユーザーがテキストのサイズを大きくした場合、テキストのサイズが小さいユーザーよりも、同様の行長で広いビューポートでブレークポイントが発生します。

+ +

step1.html の CSS の下部に以下のコードを追加します。

+ +
@media screen and (min-width: 40em) {
+    article {
+        display: grid;
+        grid-template-columns: 3fr 1fr;
+        column-gap: 20px;
+    }
+
+    nav ul {
+        display: flex;
+    }
+
+    nav li {
+        flex: 1;
+    }
+}
+
+ +

この CSS は、記事(article)内の2列のレイアウトで、記事のコンテンツ(content)および余談(aside)要素の関連(related)情報を提供します。 また、フレックスボックスを使用してナビゲーション(nav)を1行に配置します。

+ +

ブラウザーでステップ2を開くか、ソースを表示します。

+ +

サイドバー(sidebar)が新しい列を形成するのに十分なスペースがあると感じるまで、幅を拡張し続けます。 メディアクエリー内で、主要な(main)要素を2列のグリッドにします。 次に、2つのサイドバーが互いに揃うように article の {{cssxref("margin-bottom")}} を削除する必要があります。 フッター(footer)の上部に {{cssxref("border")}} を追加します。 通常、これらの小さな調整は、各ブレークポイントでデザインをきれいに見せるために行うことです。

+ +

再び、step1.html の CSS の下部に以下のコードを追加します。

+ +
@media screen and (min-width: 70em) {
+    main {
+        display: grid;
+        grid-template-columns: 3fr 1fr;
+        column-gap: 20px;
+    }
+
+    article {
+        margin-bottom: 0;
+    }
+
+    footer {
+        border-top: 1px solid #ccc;
+        margin-top: 2em;
+    }
+}
+
+ +

ブラウザーでステップ3を開くか、ソースを表示します。

+ +

さまざまな幅で最後の例を見ると、デザインがどのように反応し、利用可能な幅に応じて1列、2列、または3列として機能するかを確認できます。 これは、モバイルファースト レスポンシブデザインの非常に単純な例です。

+ +

The viewport meta tag

+ +

If you look at the HTML source in the above example, you'll see the following element included in the head of the document:

+ +
<meta name="viewport" content="width=device-width,initial-scale=1">
+ +

This is the viewport meta tag — it exists as a way control how mobile browsers render content. This is needed because by default, most mobile browsers lie about their viewport width. Non-responsive sites commonly look really bad when rendered in a narrow viewport, so mobile browsers usually render the site with a viewport width wider than the real device width by default (usually 960 pixels), and then shrink the rendered result so that it fits in the display.

+ +

This is all well and good, but it means that responsive sites are not going to work as expected. If the viewport width is reported as 960 pixels, then mobile layouts (for example created using a media query of @media screen and (max-width: 600px) { ... }) are not going to render as expected.

+ +

To remedy this, including a viewport meta tag like the one above on your page tells the browser "don't render the content with a 960 pixel viewport — render it using the real device width instead, and set a default initial scale level for better consistency." The media queries will then kick in as expected.

+ +

There are a number of other options you can put inside the content attribute of the viewport meta tag — see Using the viewport meta tag to control layout on mobile browsers for more details.

+ +

メディアクエリーが本当に必要ですか?

+ +

フレックスボックス、グリッド、および段組みのレイアウトはすべて、メディアクエリーを必要とせずに、柔軟でレスポンシブなコンポーネントを作成する方法を提供します。 これらのレイアウト方法が、メディアクエリーを追加せずに目的を達成できるかどうかを常に検討する価値があります。 例えば、少なくとも 200 ピクセル幅のカードのセットが必要な場合があります。 これらの 200 ピクセルの多くは、mainarticle に収まります。 これは、メディアクエリーをまったく使用せずに、グリッドレイアウトで実現できます。

+ +

これは、次を使用して実現できます。

+ +
<ul class="grid">
+    <li>
+        <h2>Card 1</h2>
+        <p>...</p>
+    </li>
+    <li>
+        <h2>Card 2</h2>
+        <p>...</p>
+    </li>
+    <li>
+        <h2>Card 3</h2>
+        <p>...</p>
+    </li>
+    <li>
+        <h2>Card 4</h2>
+        <p>...</p>
+    </li>
+    <li>
+        <h2>Card 5</h2>
+        <p>...</p>
+    </li>
+</ul>
+ +
.grid {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    display: grid;
+    gap: 20px;
+    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+}
+
+.grid li {
+    border: 1px solid #666;
+    padding: 10px;
+}
+ +

ブラウザーでグリッドレイアウトの例を開くか、ソースを表示します。

+ +

ブラウザーで例を開いた状態で、画面を拡大および縮小して、列トラック数の変更を確認します。 このメソッドの良い点は、グリッドがビューポートの幅ではなく、このコンポーネントで使用可能な幅を見ていることです。 メディアクエリーに関するセクションに、それがまったく必要ないかもしれないという提案をまとめるのは奇妙に思えるかもしれません! しかしながら、実際には、メディアクエリーで強化された最新のレイアウト方法を適切に使用すると、最良の結果が得られることがわかります。

+ +

Test your skills!

+ +

You've reached the end of this article, but can you remember the most important information? You can find a test to verify that you've retained this information before you move on — see Test your skills: Responsive Web Design.

+ +

まとめ

+ +

このレッスンでは、メディアクエリーについて学び、実際にそれらを使用してモバイルファースト レスポンシブデザインを作成する方法もみいだしました。

+ +

作成した開始点を使用して、さらにメディアクエリーをテストできます。 例えば、pointer メディア特性を使用して、訪問者が粗いポインターを持つことを検出した場合、ナビゲーションのサイズを変更できます。

+ +

また、さまざまなコンポーネントを追加して、メディアクエリーを追加するか、フレックスボックスやグリッドなどのレイアウト方法を使用するのがコンポーネントをレスポンシブにするのに最も適切な方法かどうかを試すこともできます。 多くの場合、正しい方法も間違った方法もありません。 あなたのデザインとコンテンツに最適な方法を試してみてください。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout/Legacy_Layout_Methods", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/multiple-column_layout/index.html b/files/ja/learn/css/css_layout/multiple-column_layout/index.html new file mode 100644 index 0000000000..036bb7daf6 --- /dev/null +++ b/files/ja/learn/css/css_layout/multiple-column_layout/index.html @@ -0,0 +1,417 @@ +--- +title: 段組みレイアウト +slug: Learn/CSS/CSS_layout/Multiple-column_Layout +tags: + - Beginner + - CSS + - Guide + - Layout + - Learn + - Learning + - Multi-col + - Multiple columns +translation_of: Learn/CSS/CSS_layout/Multiple-column_Layout +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout")}}
+ +

段組みレイアウトの仕様では、新聞に見られるような、コンテンツを段にレイアウトする方法が提供されています。 この記事では、この機能の使い方について説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:ウェブページ上で、新聞に見られるような、段組みレイアウトを作成する方法を学ぶこと。
+ +

基本的な例

+ +

ここでは、しばしば multicol と呼ばれる、段組みレイアウトの使用方法を探ります。 あなたは、multicol の出発点ファイルをダウンロードして、適切な場所に CSS を追加することによって、従うことができます。 このセクションの一番下には、最終的なコードがどのようになっているかの実例があります。

+ +

出発点にはいくつかの非常に単純な HTML を含んでいます。 container のクラスを持つラッパーに見出しといくつかの段落が入っています 。

+ +

container のクラスを持つ {{htmlelement("div")}} を、 multicol コンテナとします。 2つのプロパティ {{cssxref("column-count")}} または {{cssxref("column-width")}} のいずれかを使用して、multicol をオンにします。 column-count プロパティは与えた値と同じ数の段(column)を作成するので、スタイルシートに次の CSS を加えて、ページをリロードすれば、あなたは3つの段を得るでしょう。

+ +
.container {
+  column-count: 3;
+}
+
+ +

作成した段の幅は可変です — ブラウザーは各段に割り当てるためのスペースを計算します。

+ +
+ + +
<div class="container">
+  <h1>Simple multicol example</h1>
+
+  <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate.
+  Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
+  Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse
+  ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit
+  quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
+
+  <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique
+  elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit
+  cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis
+  dis parturient montes, nascetur ridiculus mus.</p>
+</div>
+
+ +
.container {
+  column-count: 3;
+}
+
+
+ +

{{ EmbedLiveSample('Multicol_1', '100%', 400) }}

+ +

次のように CSS を変更して column-width を使用します。

+ +
.container {
+  column-width: 200px;
+}
+
+ +

ブラウザーは指定したサイズでできる数の段を与えます。 残りのスペースは既存の段間で共有されます。 これは、コンテナがその幅で正確に割り切れない限り、指定した幅と正確には一致しないことを意味します。

+ +
+ + +
.container {
+  column-width: 200px;
+}
+
+
+ +

{{ EmbedLiveSample('Multicol_2', '100%', 400) }}

+ +

段をスタイリングする

+ +

multicol によって作成された段を個別にスタイリングすることはできません。 1つの段を他の段より大きくしたり、単一の段の背景色やテキストの色を変更したりする方法はありません。 段の表示方法を変更する機会は次の2つがあります。

+ + + +

上記の例を使用して、次のように column-gap プロパティを追加してギャップのサイズを変更します。

+ +
.container {
+  column-width: 200px;
+  column-gap: 20px;
+}
+ +

さまざまな値で遊ぶことができます — このプロパティは任意の長さの単位を受け入れます。 今度は column-rule で、段の間に線(rule、罫線)を追加します。 前のレッスンで遭遇した {{cssxref("border")}} プロパティと同様に、column-rule は {{cssxref("column-rule-color")}}、{{cssxref("column-rule-style")}}、{{cssxref("column-rule-width")}} の一括指定で、border と同じ値を受け入れます。

+ +
.container {
+  column-count: 3;
+  column-gap: 20px;
+  column-rule: 4px dotted rgb(79, 185, 227);
+}
+ +

さまざまなスタイルや色の線を追加してみてください。

+ +
+ +
+ +

{{ EmbedLiveSample('Multicol_3', '100%', 400) }}

+ +

注意すべきことは、線がそれ自体の幅を占めることはないということです。 それは column-gap で作ったギャップの向こう側にあります。 線の両側にスペースを増やすには、column-gap のサイズを増やす必要があります。

+ +

段と断片化

+ +

段組みレイアウトのコンテンツは断片化されています。 ウェブページを印刷するときなど、ページ付きメディアでコンテンツがふるまうのと基本的に同じようにふるまいます。 コンテンツを multicol コンテナに入れるとき、それは段に断片化されます。 そして、コンテンツはこれを可能にするために分割されます。

+ +

時々、この分割は良くない読書体験をもたらす場所で起こるでしょう。 以下の実例では、multicol を使用して一連のボックスをレイアウトしました。 各ボックスの中には見出しとテキストがあります。 段がその2つの間で断片化すると、見出しはテキストから分離されます。

+ +
+ + +
<div class="container">
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+    <div class="card">
+      <h2>I am the heading</h2>
+      <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat
+                vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies
+                tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
+                vel, viverra egestas ligula.</p>
+    </div>
+
+</div>
+
+ +
.container {
+  column-width: 250px;
+  column-gap: 20px;
+}
+
+.card {
+  background-color: rgb(207, 232, 220);
+  border: 2px solid rgb(79, 185, 227);
+  padding: 10px;
+  margin: 0 0 1em 0;
+}
+
+ +

{{ EmbedLiveSample('Multicol_4', '100%', 600) }}

+ +

このふるまいを制御するために、CSS 分割の仕様のプロパティを使用できます。 この仕様は、multicol とページ付きメディアでのコンテンツの分割を制御するためのプロパティを提供します。 例えば、.card の規則には、プロパティ {{cssxref("break-inside")}} を avoid の値で追加します。 これは見出しとテキストのコンテナなので、このボックスを断片化したくありません。

+ +

現時点では、ブラウザーを最大限にサポートするために、古いプロパティ page-break-inside: avoid を追加することも価値があります。

+ +
.card {
+  break-inside: avoid;
+  page-break-inside: avoid;
+  background-color: rgb(207,232,220);
+  border: 2px solid rgb(79,185,227);
+  padding: 10px;
+  margin: 0 0 1em 0;
+}
+
+ +

ページをリロードすると、ボックスは一体になっているはずです。

+ +
+ + +
.container {
+  column-width: 250px;
+  column-gap: 20px;
+}
+
+.card {
+  break-inside: avoid;
+  page-break-inside: avoid;
+  background-color: rgb(207, 232, 220);
+  border: 2px solid rgb(79, 185, 227);
+  padding: 10px;
+  margin: 0 0 1em 0;
+}
+
+ +

{{ EmbedLiveSample('Multicol_5', '100%', 600) }}

+ +

まとめ

+ +

これで、構築中のデザインのレイアウト方法を選択するときに、意のままにできるもう一つのツールである段組みレイアウトの基本機能の使用方法がわかりました。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/normal_flow/index.html b/files/ja/learn/css/css_layout/normal_flow/index.html new file mode 100644 index 0000000000..3e9965ce6f --- /dev/null +++ b/files/ja/learn/css/css_layout/normal_flow/index.html @@ -0,0 +1,103 @@ +--- +title: 通常フロー +slug: Learn/CSS/CSS_layout/Normal_Flow +tags: + - Beginner + - CSS + - Layout + - Learn + - float + - grid + - normal flow +translation_of: Learn/CSS/CSS_layout/Normal_Flow +--- +
{{LearnSidebar}}
+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}

+ +

この記事では、通常フロー、つまりレイアウトを変更していない場合のウェブページの要素のレイアウト方法について説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基礎 (HTML 入門を学ぶ)、および CSS の機能の考え方 (CSS 入門を学ぶ)。
学習目標:変更を加える前に、ブラウザーがデフォルトでウェブページをどのようにレイアウトするかを説明します。
+ +

レイアウトを紹介した前回のレッスンで詳しく説明したように、CSS を適用してふるまいを変更していない場合、ウェブページ上の要素は通常フローでレイアウトされます。そして、理解を深め始めるにつれ、その通常フローの中で要素の位置を調整したり、要素を完全に取り除くたりして、要素のふるまいを変更できます。通常フローで読み取り可能な、しっかりとよく構造化された文書から始めることは、どんなウェブページでも始めるための最良の方法です。それは、ユーザーが非常に制限されたブラウザーを使用している場合や、ページのコンテンツを読み上げるスクリーンリーダーなどのデバイスを使用している場合でも、コンテンツを読みやすくすることができます。さらに、通常フローは読み取り可能な文書を作成するように設計されているので、この方法で始めることで、レイアウトを変更するときに文書と戦うのではなく文書とともに作業します。

+ +

さまざまなレイアウト方法を深く掘り下げる前に、以前のモジュールで通常のドキュメントフローに関して検討したことのいくつかを再検討する価値があります。

+ +

要素はデフォルトでどのようにレイアウトされますか?

+ +

まず初めに、個々の要素ボックスは要素のコンテンツを取り、それからそれらの周りにパディング (padding、詰め物)、ボーダー (border、境界線) そしてマージン (margin、余白) を追加することによってレイアウトされます — これはまた以前に見たことがあるボックスモデルのことです。

+ +

デフォルトでは、ブロックレベル要素のコンテンツは、その親要素の幅の 100% で、そのコンテンツと同じ高さです インライン要素は、コンテンツと同じ高さで、コンテンツと同じ幅です。インライン要素に幅や高さを設定することはできません — それらはブロックレベル要素のコンテンツの中にあるだけです。この方法でインライン要素のサイズを制御したい場合は、display: block; を使用してブロックレベル要素のようにふるまうように設定する必要があります (あるいは、display: inline-block; で、両方の特性を混在させます)。

+ +

それは個々の要素を説明していますが、要素がどのように相互作用するかについてはどうでしょうか? 通常のレイアウトフロー (レイアウト入門の記事に記載) は、ブラウザーのビューポート内に要素を配置するシステムです デフォルトでは、ブロックレベル要素は、親の書字方向モード (writing mode、初期 は horizontal-tb) に基づいてブロックのフロー方向 にレイアウトされます — 各要素は、最後の要素の下の新しい行に表示され、それらに設定されたマージンで区切られます したがって英語やその他の横書きで、上から下へ改行する書字方向モードでは、ブロックレベル要素は垂直にレイアウトされます。

+ +

インライン要素は異なるふるまいをします — 新しい行に現れません。代わりに、親ブロックレベル要素の幅の内側にマージンがある限り、それらは互いに同じ行に配置され、隣接する (または折り返された) テキストコンテンツに配置されます。スペースがなければ、あふれているテキストや要素は新しい行に移動します。

+ +

隣接する 2 つの要素の両方にマージンが設定されていて、2 つのマージンが接触している場合、2 つのうち大きい方が残り、小さい方が消えます — これはマージンの相殺 (margin collapsing) と呼ばれます。

+ +

これらすべてを説明する簡単な例を見てみましょう。

+ +
+
<h1>基本的なドキュメントフロー</h1>
+
+<p>これは基本的なブロックレベル要素です。隣接するブロックレベル要素は下の新しい行に配置されています。</p>
+
+<p>デフォルトでは、親要素の幅の 100% にまたがり、子コンテンツと同じ高さになります。幅と高さの合計は、コンテンツ + パディング + ボーダーの幅/高さです。</p>
+
+<p>マージンによって分けられています。マージンの相殺のため、両方ではなく、1 つのマージンの幅で区切られます。</p>
+
+<p><span>これ</span>および<span>これのような</span>インライン要素は、同じ行に配置され、同じ行にスペースがある場合は隣接するテキストノードに配置されます。オーバーフローするインライン要素は<span>可能であれば新しいラインに折り返され (これのようにテキストを含む)</span>、そうでなければ次の画像のように単に新しい行に進むでしょう。<img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p>
+ +
body {
+  width: 500px;
+  margin: 0 auto;
+}
+
+p {
+  background: rgba(255,84,104,0.3);
+  border: 2px solid rgb(255,84,104);
+  padding: 10px;
+  margin: 10px;
+}
+
+span {
+  background: white;
+  border: 1px solid black;
+}
+
+ +

{{ EmbedLiveSample('Normal_Flow', '100%', 500) }}

+ +

まとめ

+ +

通常フロー、およびブラウザーがデフォルトでどのようにレイアウトするかを理解したので、次にこのデフォルトの display を変更してデザインに必要なレイアウトを作成する方法を理解することに進みます。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/positioning/index.html b/files/ja/learn/css/css_layout/positioning/index.html new file mode 100644 index 0000000000..085dce0054 --- /dev/null +++ b/files/ja/learn/css/css_layout/positioning/index.html @@ -0,0 +1,588 @@ +--- +title: 位置指定 +slug: Learn/CSS/CSS_layout/Positioning +tags: + - Article + - Beginner + - CSS + - CodingScripting + - Guide + - Layout + - Positioning + - absolute + - fixed + - relative +translation_of: Learn/CSS/CSS_layout/Positioning +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout")}}
+ +

位置指定を使用すると、通常のドキュメントレイアウトフローから要素を取り出して異なるふるまいをさせることができます。 例えば、互いの上に重なったり、常にブラウザーのビューポート内の同じ場所に留まったりします。 この記事では、さまざまな {{cssxref("position")}} の値とその使い方について説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:CSS 位置指定がどのように機能するのかを学ぶこと。
+ +

可能であれば、あなたのローカルコンピュータでの演習をお願いします — GitHub リポジトリから 0_basic-flow.html のコピーを入手し(ソースコードはここ)、それを出発点として使用します。

+ +

位置指定の紹介

+ +

位置指定(Positioning、ポジショニング)の本来の趣旨は、興味深い効果を生み出すために、上記の基本的なドキュメントフローのふるまいを上書きできるようにすることです。 レイアウト内のいくつかのボックスの位置をデフォルトのレイアウトフローの位置からわずかに変更して、ちょっと風変わりでアンティーク調の感じにしたらどうでしょうか? 位置指定はあなたのツールです。 あるいは、ページの他の部分の上に浮かぶ UI 要素を作成したり、ページをいくらスクロールしても常にブラウザーウィンドウ内の同じ場所に配置したいですか? 位置指定はそのようなレイアウト作業を可能にします。

+ +

HTML 要素に適用できるさまざまな種類の位置指定があります。 特定の種類の位置指定を要素でアクティブにするには、{{cssxref("position")}} プロパティを使用します。

+ +

静的位置指定

+ +

静的位置指定(Static positioning)は、すべての要素が取得するデフォルトです。 これは、「要素をドキュメントレイアウトフロー内の通常の位置に配置する — ここで見るべき特別なことは何もありません」を意味します。

+ +

これを実演し、例をこれからのセクションのために準備するために、最初に HTML の2番目の {{htmlelement("p")}} に positionedclass を次のように追加します。

+ +
<p class="positioned"> ... </p>
+ +

それでは、CSS の最後に次の規則を追加してください。

+ +
.positioned {
+  position: static;
+  background: yellow;
+}
+ +

保存してリフレッシュしても、2段落目の背景色が更新されていることを除けば、まったく違いはありません。 これは問題ありません。 前にも述べたように、静的位置指定はデフォルトのふるまいです!

+ +
+

: この時点でのライブの例は 1_static-positioning.html にあります(ソースコードを見る)。

+
+ +

相対位置指定

+ +

相対位置指定(Relative positioning)は、最初に見ていく position の種類です。 これは静的位置指定と非常によく似ていますが、位置指定要素(positioned element)が通常のレイアウトフローで配置されたら、ページ上の他の要素と重なることも含んで最終的な位置を変更できるという点が異なります。 先に進んで、次のようにコード内の position の宣言を更新してください。

+ +
position: relative;
+ +

この段階で保存してリフレッシュしても、結果にまったく変化はありません。 それでは、どうやって要素の位置を変更するのでしょうか? {{cssxref("top")}}、{{cssxref("bottom")}}、{{cssxref("left")}}、{{cssxref("right")}} の各プロパティを使用する必要があります。 これについては次のセクションで説明します。

+ +

top、bottom、left、right の紹介

+ +

{{cssxref("top")}}(上)、{{cssxref("bottom")}}(下)、{{cssxref("left")}}(左)、{{cssxref("right")}}(右)は {{cssxref("position")}} と一緒に使用され、位置指定要素の移動先を正確に指定します。 これを試すには、CSS の .positioned 規則に次の宣言を追加してください。

+ +
top: 30px;
+left: 30px;
+ +
+

: これらのプロパティの値は、論理的に想定される任意の単位(ピクセル、mm、rem、% など)をとることができます。

+
+ +

保存してリフレッシュすると、次のような結果になります。

+ + + +

{{ EmbedLiveSample('Introducing_top_bottom_left_and_right', '100%', 500) }}

+ +

クールだよね? Ok、おそらくこれはあなたが期待していたものではなかったでしょう — 上と左を指定したのに、なぜ下と右に移動したのでしょうか? 最初は非論理的に聞こえるかもしれませんが、これは相対的位置指定が機能する方法です — 位置指定したボックスの指定した側を反対方向に押す見えない力を考える必要があります。 例えば、top: 30px; と指定した場合、力がボックスの上側を押して、箱の上側が 30px 下向きに移動します。

+ +
+

: この時点でのライブの例は 2_relative-positioning.html にあります(ソースコードを見る)。

+
+ +

絶対位置指定

+ +

絶対位置指定(Absolute positioning)はとても異なる結果をもたらします。 次のようにコード内の position 宣言を変更してみましょう。

+ +
position: absolute;
+ +

保存してリフレッシュすると、次のようになります。

+ + + +

{{ EmbedLiveSample('Absolute_positioning', '100%', 420) }}

+ +

まず最初に、ドキュメントフロー内にあるべき位置指定要素のギャップが存在しないことに注意してください。 1番目と3番目の要素はそれが存在しないので一緒になっています! ある意味、これは事実です。 絶対位置指定要素は、通常のドキュメントレイアウトフローには存在しません。 その代わりに、それは他のすべてのものとは別のそれ自身の層の上にあります。 これは非常に便利です。 つまり、ページ上の他の要素のレイアウトを妨げない独立した UI 機能を作成できるということです。 例えば、ポップアップ情報ボックスやコントロールメニュー、ロールオーバーパネル、ページ上の任意の場所にドラッグアンドドロップできる UI 機能、等々です。

+ +

次に、要素の位置が変更されたことに注意してください。 これは、{{cssxref("top")}}、{{cssxref("bottom")}}、{{cssxref("left")}}、{{cssxref("right")}} の絶対位置指定でのふるまいが異なるためです。 通常のドキュメントレイアウトフロー内での相対的な位置に基づいて要素を配置するのではなく, 要素がそれぞれの包含要素の側からあるべき距離を指定します。 したがって、この場合は、絶対位置指定要素は「包含要素」の上側から30ピクセル、左側から30ピクセルとなるようにします。 (この場合、「包含要素」とは、最初の包含ブロック(initial containing block)のことです。詳細については、以下のセクションを参照してください。)

+ +
+

: 必要に応じて、要素のサイズを変更するために {{cssxref("top")}}、{{cssxref("bottom")}}、{{cssxref("left")}}、{{cssxref("right")}} を使用できます。 位置指定要素に top: 0; bottom: 0; left: 0; right: 0; margin: 0; を設定して、何が起こるか見てください! 後で元に戻します。

+
+ +
+

: はい、マージンはまだ位置指定要素に影響します。 しかしながら、マージンの相殺はそうではありません。

+
+ +
+

: この時点でのライブの例は 3_absolute-positioning.html にあります(ソースコードを見る)。

+
+ +

位置指定コンテキスト

+ +

絶対位置指定要素の「包含要素」はどの要素でしょうか? これは、位置指定要素の先祖の position プロパティに大きく依存します(包含ブロックの識別を参照)。

+ +

明示的に定義された position プロパティを持つ祖先要素がない場合、デフォルトではすべての祖先要素は静的位置を持ちます。 この結果、絶対位置指定要素は最初の包含ブロック(initial containing block)に含まれます。 最初の包含ブロックはビューポートの大きさを持ち、{{htmlelement("html")}} 要素を含むブロックでもあります。 簡単に言うと、絶対位置指定要素は {{htmlelement("html")}} 要素の外側に表示され、最初のビューポートを基準にして配置されます。

+ +

位置指定要素は HTML ソースの {{htmlelement("body")}} 内にネストされていますが、最終的なレイアウトでは、ページの端の左上から30ピクセル離れています。 位置指定コンテキスト(positioning context) — 絶対位置指定要素がどの要素を基準にして配置されているか — を変更することができます。 これは、要素の先祖の1つに位置指定を設定することによって行われます — それを内部にネストしている要素の1つにです(内部にネストしていない要素を基準にしての配置はできません)。 これを実証するために、次の宣言を body 規則に追加してください。

+ +
position: relative;
+ +

これにより、次の結果が得られます。

+ + + +

{{ EmbedLiveSample('Positioning_contexts', '100%', 420) }}

+ +

位置指定要素は、{{htmlelement("body")}} 要素を基準にして配置されます。

+ +
+

: この時点でのライブの例は 4_positioning-context.html にあります(ソースコードを見る)。

+
+ +

z-index の紹介

+ +

この絶対位置指定はすべて楽しいですが、まだ検討していないことがもう1つあります。 要素が重なり合ったときに、どの要素が他のどの要素の上に表われるかを決定するのは何でしょうか? これまで見てきた例では、位置指定コンテキスト内には位置指定要素が1つしかなく、位置指定要素は位置指定されていない要素よりも優先されるため、一番上に表われます。 複数あるときはどうでしょうか?

+ +

最初の段落も絶対位置指定にするために、CSS に次を追加してみてください。

+ +
p:nth-of-type(1) {
+  position: absolute;
+  background: lime;
+  top: 10px;
+  right: 30px;
+}
+ +

この時点で、最初の段落がライム色に着色され、ドキュメントフローの外に移動し、元の位置よりも少し上に配置されていることがわかります。 また、2つが重なったところでは、元の .positioned 段落の下にも重なっています。 これは、.positioned 段落がソース順の2番目の段落であり、ソース順の後ろに配置された要素がソース順の前に配置された要素よりも優先されるためです。

+ +

重ね順を変更できますか? はい、できます。 {{cssxref("z-index")}} プロパティを使うことで可能です。 「z-index」はz軸への参照です。 背景画像やドロップシャドウのオフセットなどを位置指定するために、水平(x軸)座標と垂直(y軸)座標を使用してウェブページについて説明したコースの前のポイントから思い出すことができます。 (0,0) はページ(または要素)の左上にあり、x軸とy軸はページの右下を横切っています(左から右の言語ならば)。

+ +

ウェブページには、z軸もあります。 画面の表面から自分の顔に向かって走る想像上の線(または、画面の前に持ってきたい他の何か)です。 {{cssxref("z-index")}} の値は、位置指定要素がその軸のどこにあるかに影響します。 正の値はそれらを積み重ねの上に移動し、負の値はそれらを積み重ねの下に移動します。 デフォルトでは、位置指定要素はすべて autoz-index を持ち、これは事実上 0 です。

+ +

積み重ね順を変更するには、p:nth-of-type(1) 規則に次の宣言を追加してみてください。

+ +
z-index: 1;
+ +

これで完成した例が表示され、ライム色の段落が一番上になります。

+ + + +

{{ EmbedLiveSample('Introducing_z-index', '100%', 400) }}

+ +

z-index は、無単位のインデックス値のみを受け入れることに注意してください。 1つの要素をz軸の 23 ピクセル上に配置するように指定することはできません — そのようには機能しません。 より大きい値はより小さい値より上になり、どんな値を使うかはあなた次第です。 2 と 3 を使用するのと、300 と 40000 では同じ効果が得られます。

+ +
+

: この時点でのライブの例は 5_z-index.html にあります(ソースコードを見る)。

+
+ +

固定位置指定

+ +

固定位置指定(Fixed positioning)を見てみましょう。 これは絶対位置指定とまったく同じように機能しますが、1つの重要な違いがあります。 絶対位置指定では、要素をその最も近くで位置指定された祖先 (the initial containing block if there isn't one) に対して固定しますが、固定位置指定では、ビューポートの見えている部分に対して常に固定します。 つまり、ページのスクロール量に関係なく常に表示される永続的なナビゲーションメニューのような、固定された便利な UI アイテムを作成できることを意味します。

+ +

簡単な例をまとめて、意味を説明しましょう。 まず最初に、CSS から既存の p:nth-of-type(1) 規則と .positioned 規則を削除します。

+ +

それでは、次のように body 規則を更新して position: relative; 宣言を削除して、固定の高さを追加します。

+ +
body {
+  width: 500px;
+  height: 1400px;
+  margin: 0 auto;
+}
+ +

それでは、{{htmlelement("h1")}} 要素に position: fixed; を与え、ビューポートの中央上部に配置します。 CSS に次の規則を追加してください。

+ +
h1 {
+  position: fixed;
+  top: 0;
+  width: 500px;
+  margin-top: 0;
+  background: white;
+  padding: 10px;
+}
+ +

top: 0; は、画面の上部に貼り付けるために必要です。 見出しにコンテンツ列と同じ幅を指定し、それからそれに白い背景といくらかのパディングとマージンを与えるので、コンテンツはその下に見えないでしょう。

+ +

保存してリフレッシュすると、見出しが固定されたままで、コンテンツはスクロールアップすると見出しの下に消えるように見える、ちょっとした効果があります。 しかし、これをもっと改善することができます — 現時点では、コンテンツの一部は見出しの下から動き始めます。 これは、位置指定された見出しがドキュメントフローに表われなくなり、残りのコンテンツが最上部に移動するためです。 それを少しだけ下げる必要があります。 これを行うには、最初の段落に上部マージンを設定します。 次を追加します。

+ +
p:nth-of-type(1) {
+  margin-top: 60px;
+}
+ +

完成した例を見てください。

+ + + +

{{ EmbedLiveSample('Fixed_positioning', '100%', 400) }}

+ +
+

: この時点でのライブの例は 6_fixed-positioning.html にあります(ソースコードを見る)。

+
+ +

position: sticky

+ +

position: sticky と呼ばれる利用可能な別の position の値があります。 これは他よりもやや新しいです。 これは基本的に相対位置と固定位置のハイブリッドであり、位置指定要素は、特定のしきい値の位置(例えば、ビューポートの上部から 10px)までスクロールされるまで相対位置指定されたように動作し、その後固定されます。 これは、ナビゲーションバーを特定の位置までページと共にスクロールさせ、その後ページの上部に固定するなどの目的で使用できます。

+ +
+ + +
.positioned {
+  position: sticky;
+  top: 30px;
+  left: 30px;
+}
+
+ +

{{ EmbedLiveSample('Sticky_1', '100%', 200) }}

+ +

おもしろくて一般的な position: sticky の使い方はスクロールするインデックスページを作成することです。 そこに到達すると異なる見出しがページの上部に固定されます。 そのような例のマークアップは次のようになります。

+ +
<h1>Sticky positioning</h1>
+
+<dl>
+    <dt>A</dt>
+    <dd>Apple</dd>
+    <dd>Ant</dd>
+    <dd>Altimeter</dd>
+    <dd>Airplane</dd>
+    <dt>B</dt>
+    <dd>Bird</dd>
+    <dd>Buzzard</dd>
+    <dd>Bee</dd>
+    <dd>Banana</dd>
+    <dd>Beanstalk</dd>
+    <dt>C</dt>
+    <dd>Calculator</dd>
+    <dd>Cane</dd>
+    <dd>Camera</dd>
+    <dd>Camel</dd>
+    <dt>D</dt>
+    <dd>Duck</dd>
+    <dd>Dime</dd>
+    <dd>Dipstick</dd>
+    <dd>Drone</dd>
+    <dt>E</dt>
+    <dd>Egg</dd>
+    <dd>Elephant</dd>
+    <dd>Egret</dd>
+</dl>
+
+ +

CSS は次のようになります。 通常フローでは、{{htmlelement("dt")}} 要素はコンテンツとともにスクロールします。 {{htmlelement("dt")}} 要素に position: sticky を 0 の {{cssxref("top")}} の値と共に追加すると、サポートするブラウザーでは、その位置に達すると、見出しをビューポートの一番上に固定します。 それ以降の各見出しは、その位置までスクロールアップするときに、前の見出しを置き換えます。

+ +
dt {
+  background-color: black;
+  color: white;
+  padding: 10px;
+  position: sticky;
+  top: 0;
+  left: 0;
+  margin: 1em 0;
+}
+
+ +
+ +
+ +

{{ EmbedLiveSample('Sticky_2', '100%', 200) }}

+ +
+

: このライブの例は 7_sticky-positioning.html にあります(ソースコードを見る)。

+
+ +

スキルをテストしましょう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Positioning を見てください。

+ +

まとめ

+ +

私はあなたが基本的な位置指定と一緒に遊ぶことができて楽しかったと確信しています。 これは、レイアウト全体に使用する方法ではありませんが、ご覧のとおり、それが適しているタスクはたくさんあります。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout")}}

+ +

関連情報

+ + + +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/practical_positioning_examples/index.html b/files/ja/learn/css/css_layout/practical_positioning_examples/index.html new file mode 100644 index 0000000000..d7c5601202 --- /dev/null +++ b/files/ja/learn/css/css_layout/practical_positioning_examples/index.html @@ -0,0 +1,421 @@ +--- +title: 実用的な位置指定の例 +slug: Learn/CSS/CSS_layout/Practical_positioning_examples +tags: + - Article + - Beginner + - CSS + - CodingScripting + - Guide + - Layout + - Learn + - absolute + - fixed + - relative +translation_of: Learn/CSS/CSS_layout/Practical_positioning_examples +--- +
{{LearnSidebar}}
+ +
+ +

この記事では、位置指定でどのようなことができるかを説明するために、実際に使用されるいくつかの例を作成する方法を示します。

+ + + + + + + + + + + + +
前提知識:HTML の基礎(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門を学ぶ)。
学習目標:位置指定の実用性を理解すること。
+ +

タブ付き情報ボックス

+ +

最初の例は、古典的なタブ付きの情報ボックスです — これは、たくさんの情報を小さな領域にまとめたいときによく使われる機能です。 これには、戦略/戦争ゲームのような情報量の多いアプリ、画面が狭くスペースが限られているモバイル版のウェブサイト、および UI 全体を埋め尽くさずに多くの情報を利用できるようにしたいコンパクトな情報ボックスが含まれます。 これらを単純化した例は、完成すると次のようになります。

+ +

+ +
+

: 完成した例は、info-box.html でライブで確認できます(ソースコード)。 記事のこのセクションで何を構築するのかを理解するために、ぜひチェックしてください。

+
+ +

「別々のタブを別々のウェブページとして作成し、タブをクリックして別々のページに移動させて同様の効果を生み出すだけでよいのではないでしょうか?」と考えるかもしれません。 このコードならもっと簡単なものになりますが、実際には個々の「ページ」ビューは実際には新しくロードされたウェブページになるため、ビュー間で情報を保存し、この機能をより大きな UI デザインに統合するのは難しくなります。 さらに、いわゆる「シングルページアプリ」は、特にモバイルウェブ UI の場合、非常に人気が高まっています。 なぜなら、すべてのコンテンツを表示するために必要な HTTP リクエストの数が減り、パフォーマンスが向上するからです。

+ +
+

: ウェブ開発者の中には、一度に1ページの情報だけをロードし、XMLHttpRequest などの JavaScript 機能を使用して表示される情報を動的に変更することで、さらに問題を解決するものもあります。 しかし、学習の現時点では、物事をできるだけシンプルに保ちたいと思います。 後で JavaScript がいくつかありますが、ほんの少しだけです。

+
+ +

まず始めに、出発点の HTML ファイル info-box-start.html のローカルコピーを作成してください。 これをローカルコンピュータの適当な場所に保存して、テキストエディタで開きます。 body に含まれる HTML を見てみましょう。

+ +
<section class="info-box">
+  <ul>
+    <li><a href="#" class="active">Tab 1</a></li>
+    <li><a href="#">Tab 2</a></li>
+    <li><a href="#">Tab 3</a></li>
+  </ul>
+  <div class="panels">
+    <article class="active-panel">
+      <h2>The first tab</h2>
+
+      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. Vestibulum et orci scelerisque, vulputate tellus quis, lobortis dui. Vivamus varius libero at ipsum mattis efficitur ut nec nisl. Nullam eget tincidunt metus. Donec ultrices, urna maximus consequat aliquet, dui neque eleifend lorem, a auctor libero turpis at sem. Aliquam ut porttitor urna. Nulla facilisi.</p>
+    </article>
+    <article>
+      <h2>The second tab</h2>
+
+      <p>This tab hasn't got any Lorem Ipsum in it. But the content isn't very exciting all the same.</p>
+    </article>
+    <article>
+      <h2>The third tab</h2>
+
+      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. And now an ordered list: how exciting!</p>
+
+      <ol>
+        <li>dui neque eleifend lorem, a auctor libero turpis at sem.</li>
+        <li>Aliquam ut porttitor urna.</li>
+        <li>Nulla facilisi</li>
+      </ol>
+    </article>
+  </div>
+</section>
+ +

それで、ここに {{htmlelement("ul")}} と {{htmlelement("div")}} を含む info-box のクラス(class)を持つ {{htmlelement("section")}} 要素があります。 番号なしリストには3つのリスト項目があり、その中にリンクがあります。 これは、コンテンツパネルを表示するためにクリックする実際のタブになります。 <div> には、各タブに対応するコンテンツパネルを構成する3つの {{htmlelement("article")}} 要素が含まれています。 各パネルにはいくつかのサンプルのコンテンツが含まれています。

+ +

ここでの考え方は、標準の水平ナビゲーションメニューのようにタブをスタイルし、絶対位置指定を使用して互いの上に重なるようにパネルをスタイルするということです。 また、タブが押されたときに対応するパネルを表示し、タブ自体をスタイルするためにページに含める JavaScript も少し用意します。 現段階では JavaScript 自体を理解する必要はありませんが、基本的な JavaScript をできるだけ早く学習することを検討するべきです — UI 機能が複雑になるほど、欲しい機能を実装するために JavaScript が必要になるでしょう。

+ +

一般的な設定

+ +

まず、{{htmlelement("style")}} の開始タグと終了タグの間に次を追加します。

+ +
html {
+  font-family: sans-serif;
+}
+
+* {
+  box-sizing: border-box;
+}
+
+body {
+  margin: 0;
+}
+ +

これは、ページに サンセリフ(sans-serif)フォントを設定し、border-box の {{cssxref("box-sizing")}} モデルを使い、{{htmlelement("body")}} からデフォルトのマージンを取り除くための一般的な設定です。

+ +

次に、前の CSS のすぐ下に次を追加します。

+ +
.info-box {
+  width: 450px;
+  height: 400px;
+  margin: 0 auto;
+}
+ +

これはコンテンツに特定の幅と高さを設定し、古い margin: 0 auto トリックを使用して画面の中央に配置します。 以前のコースでは、可能であればコンテンツのコンテナに固定の高さを設定しないことをお勧めしました。 タブのコンテンツは固定されているので、この状況では問題ありません。 また、異なる高さで異なるタブを表示するのも少々不快です。

+ +

タブのスタイリング

+ +

今度はタブをタブのようにスタイルします — 基本的にこれらは水平ナビゲーションメニューですが、コースで以前見たようにクリックされたときに異なるウェブページをロードする代わりに異なるパネルを同じページに表示します。 まず、CSS の一番下に次の規則を追加して、番号なしリストからデフォルトの {{cssxref("padding-left")}} と {{cssxref("margin-top")}} を削除します。

+ +
.info-box ul {
+  padding-left: 0;
+  margin-top: 0;
+}
+ +
+

: この例では、チェーンの先頭に .info-box を持つ子孫セレクタを使用しています。 これは、他のコンテンツがすでに含まれているページに、ページの他の部分に適用されているスタイルを妨げることなく、この機能を挿入できるようにするためです。

+
+ +

次に、水平方向のタブのスタイルを設定します。 リスト項目は、一列に並ぶようにすべて左にフロートさせ、行頭記号(bullet)を取り除くために {{cssxref("list-style-type")}} を none に設定し、{{cssxref("width")}} を 150px に設定しているので、それらは情報ボックス全体にうまく収まります。 {{htmlelement("a")}} 要素は {{cssxref("display")}}: inline-block に設定されているので、一列に並んでいてもスタイル可能で、他のさまざまなプロパティを使用して、タブボタンに適したスタイルになっています。

+ +

次の CSS を追加してください。

+ +
.info-box li {
+  float: left;
+  list-style-type: none;
+  width: 150px;
+}
+
+.info-box li a {
+  display: inline-block;
+  text-decoration: none;
+  width: 100%;
+  line-height: 3;
+  background-color: red;
+  color: black;
+  text-align: center;
+}
+ +

最後に、このセクションでは、リンク状態にいくつかのスタイルを設定します。 最初に、フォーカス時やホバー時にタブの状態が異なるように {{cssxref(":focus")}} と {{cssxref(":hover")}} の状態を設定し、ユーザーに視覚的なフィードバックを提供します。 次に、タブの1つに active のクラスが存在する場合、それに同じスタイルを設定する規則を設定します。 これをタブがクリックされたときに JavaScript を使用して設定します。 次の CSS を他のスタイルの下に配置します。

+ +
.info-box li a:focus, .info-box li a:hover {
+  background-color: #a60000;
+  color: white;
+}
+
+.info-box li a.active {
+  background-color: #a60000;
+  color: white;
+}
+ +

パネルのスタイリング

+ +

次の仕事はパネルをスタイルすることです。 さあ行きましょう!

+ +

まず最初に、.panels の {{htmlelement("div")}} コンテナをスタイルするために次の規則を追加します。 ここでは、パネルが情報ボックスの内側にぴったり収まるように固定の {{cssxref("height")}} を設定し、{{htmlelement("html")}} ではなくそれに対して相対的に位置指定子要素を配置できるように {{cssxref("position")}}: relative で {{htmlelement("div")}} を位置指定コンテキストとして設定します。 最後にレイアウトに影響を与えないように、最後に上記 CSS で設定したフロートを {{cssxref("clear")}} します。

+ +
.info-box .panels {
+  height: 352px;
+  position: relative;
+  clear: both;
+}
+ +

このセクションの最後に、パネルを構成する個々の {{htmlelement("article")}} 要素をスタイルします。 最初に追加する規則は、パネルを絶対位置指定して、それらがすべて {{htmlelement("div")}} コンテナの {{cssxref("top")}} と {{cssxref("left")}} にぴったり合うように配置することです — これは、パネルを互いの上に重ねて配置するという、このレイアウト機能全体にとって絶対に重要な部分です。 この規則はまた、パネルにコンテナと同じ設定の高さを与え、コンテンツにいくつかの {{cssxref("padding")}}、テキストの {{cssxref("color")}}、および {{cssxref("background-color")}} を与えます。

+ +

ここで追加する2番目の規則は、active-panel のクラスが設定されているパネルに 1 の {{cssxref("z-index")}} が適用されるようにすることです。 これにより、他のパネルの上に重ねて置かれます(位置指定要素はデフォルトで 0 の z-index を持ち、これは他のパネルを下に置きます)。 繰り返しますが、適切なタイミングで JavaScript を使用してこのクラスを追加します。

+ +
.info-box article {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 352px;
+  padding: 10px;
+  color: white;
+  background-color: #a60000;
+}
+
+.info-box .active-panel {
+  z-index: 1;
+}
+ +

JavaScript を追加する

+ +

この機能を動作させるための最後のステップは、JavaScript を追加することです。 {{htmlelement("script")}} の開始タグと終了タグの間に記述されているとおりに、次のコードブロックを挿入します(これらは HTML コンテンツの下方にあります)。

+ +
var tabs = document.querySelectorAll('.info-box li a');
+var panels = document.querySelectorAll('.info-box article');
+
+for(i = 0; i < tabs.length; i++) {
+  var tab = tabs[i];
+  setTabHandler(tab, i);
+}
+
+function setTabHandler(tab, tabPos) {
+  tab.onclick = function() {
+    for(i = 0; i < tabs.length; i++) {
+      tabs[i].className = '';
+    }
+
+    tab.className = 'active';
+
+    for(i = 0; i < panels.length; i++) {
+      panels[i].className = '';
+    }
+
+    panels[tabPos].className = 'active-panel';
+  }
+}
+ +

このコードは次のことを行います。

+ + + +

最初の例はこれで終わりです。 2番目の例で追加しますので、コードを開いたままにしてください。

+ +

固定位置のタブ付き情報ボックス

+ +

2番目の例では、最初の例(情報ボックス)を取り上げて、それをフルウェブページのコンテキストに追加します。 それだけではありません — ブラウザーウィンドウ内で同じ位置に留まるように固定位置を指定します。 メインコンテンツがスクロールしても、情報ボックスは画面上の同じ位置に留まります。 完成した例は次のようになります。

+ +

+ +
+

: 完成した例は、fixed-info-box.html でライブで確認できます(ソースコード)。 記事のこのセクションで何を構築するのかを理解するために、ぜひチェックしてください。

+
+ +

出発点として、記事の最初のセクションで完成させた例を使用するか、Github リポジトリから info-box.html のローカルコピーを作成することができます。

+ +

HTML の追加

+ +

まず第一に、ウェブサイトのメインコンテンツを表すために追加の HTML が必要です。 既存のセクションの直前で、開始 {{htmlelement("body")}} タグのすぐ下に次の {{htmlelement("section")}} を追加します。

+ +
<section class="fake-content">
+  <h1>Fake content</h1>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+  <p>This is fake content. Your main web page contents would probably go here.</p>
+</section>
+ +
+

: お好みにより、本物のコンテンツで偽のコンテンツを自由に変更してもかまいません。

+
+ +

既存の CSS への変更

+ +

次に、情報ボックスを配置して位置指定するために、既存の CSS に若干の変更を加える必要があります。 .info-box の規則を変更して、margin: 0 auto; を取り除き(情報ボックスを中央に配置する必要はもうありません)、{{cssxref("position")}}: fixed; を追加して、ブラウザーのビューポートの {{cssxref("top")}} に貼り付けます。

+ +

これは今、次のようになるはずです。

+ +
.info-box {
+  width: 450px;
+  height: 400px;
+  position: fixed;
+  top: 0;
+}
+ +

メインコンテンツのスタイリング

+ +

この例に残された唯一のことは、メインコンテンツに何らかのスタイルを提供することです。 CSS の残りの部分の下に次の規則を追加します。

+ +
.fake-content {
+  background-color: #a60000;
+  color: white;
+  padding: 10px;
+  height: 2000px;
+  margin-left: 470px;
+}
+ +

まず、情報ボックスパネルと同じ {{cssxref("background-color")}}、{{cssxref("color")}}、および {{cssxref("padding")}} をコンテンツに与えます。 それから、それを右に動かすために大きな {{cssxref("margin-left")}} を与えて、情報ボックスが収まるスペースを作り、他に何も重ならないようにします。

+ +

これで2番目の例は終わりです。 3つ目も同じように面白いと思います。

+ +

スライド式隠しパネル

+ +

ここで紹介する最後の例は、アイコンを押すだけで画面にスライドして現れたり消えたりするパネルです。 これは、前述のように、モバイルレイアウトのような、有用なコンテンツの代わりにメニューや情報パネルを表示して、画面の大部分を使い果たしたくない、使用可能な画面スペースが小さい状況では一般的です。

+ +

完成した例は次のようになります。

+ +

+ +
+

: 完成した例は、hidden-info-panel.html でライブで確認できます(ソースコード)。 記事のこのセクションで何を構築するのかを理解するために、ぜひチェックしてください。

+
+ +

まず始めに、Github リポジトリから hidden-info-panel-start.html のローカルコピーを作成します。 これは前の例から続いていないので、新鮮な出発点ファイルが必要です。 ファイル内の HTML を見てみましょう。

+ +
<label for="toggle">❔</label>
+<input type="checkbox" id="toggle">
+<aside>
+
+  ...
+
+</aside>
+ +

{{htmlelement("label")}} 要素と {{htmlelement("input")}} 要素から始めましょう — <label> 要素は通常、アクセシビリティの目的でテキストラベルをフォーム要素に関連付けるために使用します(スクリーンリーダーのユーザーが、どの説明がどのフォーム要素に対応しているかを確認できるようにします)。 ここでは、for 属性と id 属性を使用して <input> チェックボックスに関連付けられています。

+ +
+

: 情報アイコンとして機能するために、HTML に特別な疑問符文字を入れました。 これは、パネルを表示/非表示にするために押されるボタンを表します。

+
+ +

ここでは、これらの要素を少し異なる目的で使用します — <label> 要素のもう1つの便利な副作用は、チェックボックス自体だけでなく、チェックボックスのラベルをクリックしてチェックボックスをチェックできることです。 これはよく知られたチェックボックスハック(英語)をもたらしました。 それはボタンを切り替えることによって要素を制御する JavaScript フリーの方法を提供します。 制御する要素は、他の2つに続く {{htmlelement("aside")}} 要素です(簡潔にするために、上記のコードリストからそのコンテンツを省略しました)。

+ +

以下のセクションでは、これがどのように機能するのかを説明します。

+ +

フォーム要素のスタイリング

+ +

まずフォーム要素を扱いましょう — {{htmlelement("style")}} タグの間に次の CSS を追加します。

+ +
label[for="toggle"] {
+  font-size: 3rem;
+  position: absolute;
+  top: 4px;
+  right: 5px;
+  z-index: 1;
+  cursor: pointer;
+}
+
+input[type="checkbox"] {
+  position: absolute;
+  top: -100px;
+}
+ +

最初の規則は <label> をスタイルします。 ここでは、次のことをしています。

+ + + +

2番目の規則は、実際のチェックボックスの <input> 要素に {{cssxref("position")}}: absolute を設定し、それを画面上部の範囲外に離すことで隠します。 実際の UI でこれを見たくありません。

+ +

パネルのスタイリング

+ +

今度は実際のスライド式パネル自体をスタイルする時が来ました。 CSS の最後に次の規則を追加してください。

+ +
aside {
+  background-color: #a60000;
+  color: white;
+
+  width: 340px;
+  height: 100%;
+  padding: 0 20px;
+
+  position: fixed;
+  top: 0;
+  right: -370px;
+
+  transition: 0.6s all;
+}
+ +

ここではたくさんのことが起こっています — 少しずつ説明しましょう。

+ + + +

チェック状態を設定する

+ +

追加する CSS の最後の部分がもう1つあります。 CSS の下部に次のコードを追加してください。

+ +
input[type=checkbox]:checked + aside {
+  right: 0px;
+}
+ +

セレクタはここではかなり複雑です — 私たちは <input> 要素に隣接する <aside> 要素を選択していますが、それがチェックされているときだけです(これを達成するための {{cssxref(":checked")}} 擬似クラスの使用に注意してください)。 この場合、<aside> の {{cssxref("right")}} プロパティを 0px に設定しています。 これにより、パネルが再び画面に表示されるようになります(遷移により滑らかに)。 ラベルをもう一度クリックすると、チェックボックスがオフになり、パネルを再び隠します。

+ +

切り替えボタン効果を作成するためのかなり賢い JavaScript フリーの方法は、これで終りです。 これは、IE9 以降で機能します(滑らかな遷移は、IE10 以降で機能します)。 この効果には、いくつかの懸念があります — フォーム要素はこの目的のために意図されていないので、少し乱用です。 さらに、その効果はアクセシビリティの観点からはあまり良くありません。 ラベルはデフォルトではフォーカスできず、フォーム要素を意味論的でない方法で使用するとスクリーンリーダーに問題が生じる可能性があります。 JavaScript とリンクまたはボタンのほうが適切かもしれませんが、それを試してみるのも楽しいでしょう。

+ +

まとめ

+ +

それでは、位置指定の見方を締めくくります — これまでのところ、基本的な仕組みがどのように機能するのか、またこれらを適用して興味深い UI 機能を構築する方法を理解しているはずです。 これをすぐに理解できなくても心配しないでください — 位置指定はかなり高度なトピックであり、理解を助けるために記事をいつでも再び参照することができます。 次の話題はフレックスボックスです。

+ + + +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/responsive_design/index.html b/files/ja/learn/css/css_layout/responsive_design/index.html new file mode 100644 index 0000000000..0629613548 --- /dev/null +++ b/files/ja/learn/css/css_layout/responsive_design/index.html @@ -0,0 +1,334 @@ +--- +title: レスポンシブデザイン +slug: Learn/CSS/CSS_layout/Responsive_Design +tags: + - Images + - Media Queries + - RWD + - Responsive web design + - flexbox + - fluid grids + - grid + - multicol + - typography +translation_of: Learn/CSS/CSS_layout/Responsive_Design +--- +
{{learnsidebar}}{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}
+ +

Web デザインの初期には、特定の画面サイズを対象とするページが作成されていました。 ユーザーの画面がデザイナーの予想よりも大きかったり小さかったりした場合、結果は望ましくないスクロールバーから、過度に長い行長、そして中途半端なスペースにまで及びました。 より多様な画面サイズが利用可能になると、レスポンシブ Web デザイン(responsive web design、RWD)の概念が登場しました。 これは、さまざまな画面幅、解像度などに合わせて Web ページがレイアウトと外観を変更できるようにする一連の実践です。 これは、マルチデバイス Web のデザイン方法を変えたアイデアであり、この記事は、それをマスターするために知っておくべき主なテクニックを理解するのに役立ちます。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS の第一歩CSS の構成要素を学ぶ)
学習目標:レスポンシブデザインの基本概念と歴史を理解する。
+ +

歴史的な Web サイトのレイアウト

+ +

歴史のある時点で、Web サイトを設計するときに次の2つの選択肢がありました。

+ + + +

これらの2つのアプローチは、サイトを設計する人の画面上では最も見栄えの良い Web サイトをもたらす傾向がありました! リキッドのサイトは、小さな画面では押しつぶされたデザインになり(下図参照)、大きな画面では読みにくいほど長い行長になります。

+ +
モバイルサイズのビューポートに押しつぶされた2列のレイアウト。 +
+
+ +
+

: このシンプルなリキッドレイアウトを見てください: ソースコード。 例を表示しているときに、ブラウザーのウィンドウを内側または外側にドラッグして、さまざまなサイズでどのように見えるかを確認します。

+
+ +

固定幅のサイトでは、画面の幅がサイトの幅よりも小さいと水平スクロールバーが発生するリスクがあり(下図参照)、大きな画面ではデザインの端に多くの空白ができます。

+ +
モバイルのビューポートに水平スクロールバーを備えたレイアウト。 +
+
+ +
+

: この単純な固定幅レイアウトを見てください: ソースコード。 繰り返しますが、ブラウザーのウィンドウのサイズを変更したときの結果を確認してください。

+
+ +
+

: 上記のスクリーンショットは、Firefox 開発ツールのレスポンシブデザインモードを使用して撮影したものです。

+
+ +

モバイル Web が最初の多機能携帯電話で現実のものになり始めたため、モバイルを採用したい企業は通常、異なる URL(多くの場合 m.example.comexample.mobi など)を使用して、サイトの特別なモバイルバージョンを作成しました。 これは、サイトの2つの異なるバージョンを開発し、最新の状態に保つ必要があることを意味しました。

+ +

さらに、これらのモバイルサイトは、しばしば非常に切り詰められたエクスペリエンスを提供しました。 モバイルデバイスがより強力になり、完全な Web サイトを表示できるようになったため、サイトのモバイルバージョンに閉じ込められ、フル機能のデスクトップバージョンのサイトにあることがわかっている情報にアクセスできないモバイルユーザーにとって、これはいらだたしいことでした。

+ +

レスポンシブデザインより前のフレキシブルレイアウト

+ +

Web サイトを構築する際のリキッドまたは固定幅の方法の欠点を解決するために、多くのアプローチが開発されました。 2004年に Cameron Adams は、解像度依存レイアウト(英語)という題名の投稿を書き、さまざまな画面解像度に適応できるデザインを作成する方法を説明しました。 このアプローチでは、画面解像度を検出して正しい CSS をロードするために JavaScript が必要でした。

+ +

Zoe Mickley Gillenwater は、フレキシブル(柔軟な)サイトを作成するさまざまな方法の説明と形式化をし、画面を埋めるか、サイズを完全に固定するかの間で妥協点を見つけるために尽力しました

+ +

レスポンシブデザイン

+ +

レスポンシブデザインという用語は、2010年に Ethan Marcotte によって初めて作られ、3つのテクニックを組み合わせて使用​​することを説明しています。

+ +
    +
  1. 1つ目は、Gillenwater が既に検討したフルード(流動的な)グリッドのアイデアであり、Marcotte の記事 Fluid Grids(2009年に A List Apart で公開)で読むことができます。
  2. +
  3. 2番目のテクニックは、フルード画像のアイデアです。 max-width プロパティを 100% に設定する非常に簡単なテクニックを使用すると、画像が含まれる列が画像の本来のサイズより狭くなった場合、画像は小さく縮小されますが、大きくなることはありません。 これにより、画像はオーバーフローするのではなく、柔軟なサイズの列に収まるように縮小できますが、列が画像よりも広くなった場合には大きくならず、ピクセル化もされません。
  4. +
  5. 3番目の重要なコンポーネントはメディアクエリーです。 メディアクエリーにより、CSS のみを使用して、Cameron Adams が JavaScript を使用して以前に検討したタイプのレイアウトの切り替えができるようになります。 すべての画面サイズに対して1つのレイアウトを使用するのではなく、レイアウトを変更できます。 サイドバーは小さな画面に合わせて位置を変更したり、別のナビゲーションを表示したりできます。
  6. +
+ +

レスポンシブ Web デザインは独立した技術ではないことを理解することが重要です。 レスポンシブ Web デザインは、コンテンツの表示に使用されているデバイスに対応できるレイアウトを作成するために使用される、Web デザインへのアプローチまたはベストプラクティスのセットを説明する用語です。 Marcotte の最初の検討では、これは柔軟なグリッド(フロートを使用)とメディアクエリーを意味していましたが、その記事が書かれてからほぼ10年で、レスポンシブに動作することがデフォルトになりました。 最新の CSS レイアウトの方法は本質的にレスポンシブであり、レスポンシブサイトの設計を容易にするために Web プラットフォームに新しいものが組み込まれています。

+ +

この記事の残りの部分では、レスポンシブサイトを作成するときに使用できるさまざまな Web プラットフォーム機能について説明します。

+ +

メディアクエリー

+ +

レスポンシブデザインは、メディアクエリー(media query)によってのみ出現できました。 Media Queries Level 3 仕様は2009年に勧告候補になりました。 つまり、ブラウザーでの実装の準備が整ったとみなされました。 メディアクエリーを使用すると、一連のテスト(例えば、ユーザーの画面が特定の幅または特定の解像度より大きいかどうか)を実行し、CSS を選択的に適用して、ユーザーのニーズに合わせて適切にページをスタイルできます。

+ +

例えば、次のメディアクエリーは、現在の Web ページが画面メディア(したがって印刷ドキュメントではない)として表示され、ビューポートの幅が少なくとも 800 ピクセルであるかどうかをテストします。 .container セレクターの CSS は、これら2つのことが当てはまる場合にのみ適用されます。

+ +
@media screen and (min-width: 800px) {
+  .container {
+    margin: 1em 2em;
+  }
+} 
+
+ +

スタイルシート内に複数のメディアクエリーを追加して、レイアウト全体またはその一部をさまざまな画面サイズに最適に調整できます。 メディアクエリーが導入され、レイアウトが変更されるポイントは、ブレークポイント(breakpoints)と呼ばれます。

+ +

メディアクエリーを使用する場合の一般的なアプローチは、狭い画面のデバイス(携帯電話など)用に単純な単一列レイアウトを作成し、次に、より大きな画面かチェックして複数列レイアウトを処理するのに十分な画面幅があることがわかったら、複数列レイアウトを実装することです。 これは多くの場合、モバイルファーストデザインと呼ばれます。

+ +

詳細については、メディアクエリーの MDN ドキュメントをご覧ください。

+ +

柔軟なグリッド

+ +

レスポンシブサイトは、ブレークポイント間でレイアウトを変更するだけでなく、柔軟なグリッド上に構築されます。 柔軟なグリッドは、存在する可能性のあるすべてのデバイスサイズを対象にする必要がなく、ピクセルパーフェクトレイアウトを構築する必要がないことを意味します。 膨大な数の異なるサイズのデバイスが存在し、少なくともデスクトップでは常にブラウザーのウィンドウが最大化されているわけではないという事実を考えると、ピクセルパーフェクトレイアウトのアプローチは不可能です。

+ +

柔軟なグリッドを使用することで、ブレークポイントを追加し、コンテンツの見た目が悪くなり始めた時点でデザインを変更するだけで済みます。 例えば、画面サイズが大きくなると行長が読みにくい長さになり、ボックスが狭くなるにつれて各行に2つの単語が押しつぶされるようになります。

+ +

レスポンシブデザインの初期には、レイアウトを実行するための唯一の選択肢はフロートを使用することでした。 柔軟なフロートレイアウトは、各要素に幅をパーセントで指定し、レイアウト全体で合計が 100% を超えないようにすることで実現します。 フルードグリッドに関する元の作品で、Marcotte はピクセルを使用して設計されたレイアウトを取得し、それをパーセントに変換するための公式を詳しく説明しました。

+ +
対象 / コンテキスト = 結果
+
+ +

例えば、対象の列のサイズが 60 ピクセルで、コンテキスト(またはコンテナ)が 960 ピクセルの場合、60 を 960 で割って、小数点を右に2桁移動した後、CSS で使用できる値を得られます。

+ +
.col {
+  width: 6.25%; /* 60 / 960 = 0.0625 */
+} 
+
+ +

このアプローチは、今日の Web の多くの場所で見られます。 これについては、過去のレイアウト方法の記事のレイアウトセクションで説明しています。 仕事でこのアプローチを使用している Web サイトに出くわす可能性が高いため、フロートベースの柔軟なグリッドを使用して最新のサイトを構築しなくても、理解する価値があります。

+ +

次の例は、メディアクエリーと柔軟なグリッドを使用した簡単なレスポンシブデザインを示しています。 狭い画面では、レイアウトは次のように上下に積み重ねられたボックスを表示します。

+ +
ボックスが上下に積み上げられたレイアウトのモバイルビュー。 +
+
+ +

より広い画面では、次のように2つの列に移動します。

+ +
2列のレイアウトのデスクトップビュー。 +
+
+ +
+

: この例のライブ例ソースコードは GitHub にあります。

+
+ +

最新のレイアウト技術

+ +

段組みレイアウトフレックスボックスグリッドなどの最新のレイアウト方法は、デフォルトでレスポンシブです。 それらはすべて、あなたが柔軟なグリッドを作成しようとしていると仮定し、それを行う簡単な方法を提供します。

+ +

段組み

+ +

これらのレイアウトメソッドの中で最も古いものは段組み(multicol)です。 column-count の指定で、コンテンツを分割する列の数を指定します。 ブラウザーはこれらのサイズを計算し、サイズは画面サイズに応じて変化します。

+ +
.container {
+  column-count: 3;
+} 
+
+ +

代わりに column-width の指定で、最小幅を指定します。 ブラウザーは、その幅の列をコンテナに収まるだけ作成し、すべての列の間で残りのスペースを分配します。 したがって、列の数は、どのくらいのスペースがあるかに応じて変化します。

+ +
.container {
+  column-width: 10em;
+} 
+
+ +

フレックスボックス

+ +

フレックスボックス(Flexbox)では、フレックス項目は初期の振る舞いとして、コンテナ内のスペースに従って、項目間のスペースを縮小および分散します。 flex-growflex-shrink の値を変更することにより、項目の周囲に多少のスペースがあった場合の振る舞いを指定できます。

+ +

次の例では、CSS レイアウトのフレックスボックスのトピックのフレックス項目の柔軟なサイズ変更で説明されているように、flex: 1 の一括指定を使用して、それぞれのフレックス項目はフレックスコンテナ内に同じ量のスペースを取ります。

+ +
.container {
+  display: flex;
+}
+
+.item {
+  flex: 1;
+} 
+
+ +
+

: 例として、今度はフレックスボックスを使用して、上記のシンプルなレスポンシブレイアウトを再構築しました。 列のサイズを計算するために奇妙なパーセント値を使用する必要がなくなったことがわかります: ソースコード

+
+ +

CSS グリッド

+ +

CSS グリッドレイアウトでは、fr 単位を使用して、グリッドトラック全体に利用可能なスペースを分散できます。 次の例では、サイズが 1fr の3つのトラックを持つグリッドコンテナを作成します。 これにより、3つの列トラックが作成され、それぞれがコンテナ内の使用可能なスペースの一部を取得します。 グリッドを作成するこのアプローチの詳細については、CSS レイアウトのグリッドのトピックの fr 単位での柔軟なグリッドを参照してください。

+ +
.container {
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr;
+} 
+
+ +
+

: .wrapper に列を定義できるため、グリッドレイアウトのバージョンはさらに単純です: ソースコード

+
+ +

レスポンシブ画像

+ +

レスポンシブ画像に対する最も簡単なアプローチは、レスポンシブデザインに関する Marcotte の初期の記事で説明されているとおりです。 基本的に、必要な最大サイズの画像を取得し、縮小します。 これは現在でも使用されているアプローチであり、ほとんどのスタイルシートでは次の CSS がどこかにあります。

+ +
img {
+  max-width: 100%;
+} 
+
+ +

このアプローチには明らかな欠点があります。 画像は本来のサイズよりもはるかに小さく表示される可能性があり、これは帯域幅の浪費です — モバイルユーザーは、ブラウザーのウィンドウに実際に表示されるサイズの数倍の画像をダウンロードすることになる場合があります。 さらに、モバイルとデスクトップで同じ画像アスペクト比を使用したくない場合があります。 例えば、モバイル用に正方形の画像を用意して、デスクトップのランドスケープ画像と同じシーンを表示するとよいかもしれません。 または、モバイルでの画像のサイズが小さいことを認めながら、小さな画面サイズでもより簡単に理解できるまったく別の画像を表示したい場合があります。 これらのことは、単に画像を縮小するだけでは達成できません。

+ +

{{htmlelement("picture")}} 要素と {{htmlelement("img")}} の srcset 属性と size 属性を使用したレスポンシブ画像は、これらの両方の問題を解決します。 「ヒント」(画像に最適な画面サイズと解像度を記述するメタデータ)とともに複数のサイズを提供でき、ブラウザーは各デバイスに最適な画像を選択し、ユーザーが使用しているデバイスに適した画像サイズをダウンロードできるようにします。

+ +

さまざまなサイズで使用されるアートディレクション画像は、さまざまな画面サイズに対して、さまざまな切り抜きまたはまったく異なる画像を提供します。

+ +

MDN の HTML の学習セクションで、レスポンシブ画像の詳細なガイドを見つけることができます。

+ +

レスポンシブタイポグラフィ

+ +

以前の研究ではカバーされていなかったレスポンシブデザインの要素は、レスポンシブタイポグラフィ(responsive typography)のアイデアでした。 基本的に、これは、メディアクエリー内のフォントサイズを変更して、画面を占める量を増減させることを表します。

+ +

この例では、レベル1の見出しを 4rem に設定します。 つまり、基本フォントサイズの4倍になります。 それは本当に大きな見出しです! このジャンボ見出しは大きな画面サイズでのみ必要です。 したがって、まず小さな見出しを作成し、ユーザーが少なくとも 1200px の画面サイズを持っていることがわかった場合は、メディアクエリーを使用して大きな見出しで上書きします。

+ +
html {
+  font-size: 1em;
+}
+
+h1 {
+  font-size: 2rem;
+}
+
+@media (min-width: 1200px) {
+  h1 {
+    font-size: 4rem;
+  }
+} 
+
+ +

上記のレスポンシブグリッドの例を編集して、説明した方法を使用してレスポンシブタイポグラフィも含めました。 レイアウトが2列バージョンになると、見出しのサイズがどのように切り替わるかを確認できます。

+ +

モバイルでは、次のように見出しが小さくなります。

+ +
見出しサイズが小さいスタックレイアウト。 +
+
+ +

ただし、デスクトップでは、次のようにより大きな見出しサイズで表示されます。

+ +
見出しが大きい2列レイアウト。 +
+
+ +
+

: この例を実際に見てください: ソースコード

+
+ +

このタイポグラフィへのアプローチが示すように、メディアクエリーをページのレイアウトの変更のみに制限する必要はありません。 これらを使用して任意の要素を微調整し、代わりとなる画面サイズでより使いやすく魅力的にすることができます。

+ +

レスポンシブタイポグラフィにビューポート単位を使用

+ +

興味深いアプローチは、ビューポート単位 vw を使用してレスポンシブタイポグラフィを有効にすることです。 1vw はビューポートの幅の 1% に等しいため、vw を使用してフォントサイズを設定すると、常にビューポートのサイズに関連付けられます。

+ +
h1 {
+  font-size: 6vw;
+}
+ +

上記の問題は、vw 単位を使用するとユーザーがテキストをズームする機能を失うことです。 そのテキストは常にビューポートのサイズに関連しているためです。 したがって、ビューポート単位を単独で使用してテキストを設定しないでください

+ +

解決策があり、calc() を使用する必要があります。 emrem などの固定サイズを使用した値に vw 単位を足しても、テキストはズーム可能です。 次のように基本的に、vw 単位はズームした値に足します。

+ +
h1 {
+  font-size: calc(1.5rem + 3vw);
+}
+ +

これは、見出しのフォントサイズを指定する必要があるのは一度だけで、モバイル用にメディアクエリーで再定義せずともよいことを意味します。ビューポートのサイズを大きくするにつれて、フォントは徐々に大きくなります。

+ +
+

実際のこの例を見てください: ソースコード

+
+ +

ビューポートメタタグ

+ +

レスポンシブなページの HTML ソースを見ると、通常、ドキュメントの <head> に次の {{htmlelement("meta")}} タグがあります。

+ +
<meta name="viewport" content="width=device-width,initial-scale=1">
+
+ +

このメタタグは、モバイルブラウザーに、ビューポートの幅をデバイスの幅に設定し、ドキュメントを意図したサイズの 100% にスケーリングするよう指示します。 これにより、ドキュメントはモバイル向けに最適化されたサイズで表示されます。

+ +

なぜこれが必要でしょうか? モバイルブラウザーは、ビューポートの幅について嘘をつく傾向があるためです。

+ +

このメタタグが存在するのは、最初の iPhone が出て、人々が小さな電話画面で Web サイトを表示し始めたとき、ほとんどのサイトがモバイル向けに最適化されていなかったためです。 したがって、モバイルブラウザーはビューポートの幅を 960 ピクセルに設定し、その幅でページをレンダリングし、デスクトップレイアウトの縮小版として結果を表示します。 他のモバイルブラウザー(Google Android など)も同じことを行いました。 ユーザーは Web サイトをズームインして画面内を移動し、興味のある部分を見ることができましたが、見た目は悪かったです。 レスポンシブデザインのないサイトに出くわす不幸がある場合、今日でもこれを見ることができます。

+ +

問題は、モバイルブラウザーでは、ブレークポイントとメディアクエリーを使用したレスポンシブデザインが意図したとおりに機能しないことです。 ビューポートの幅が 480px 以下で作動する狭い画面レイアウトがあり、ビューポートが 960px に設定されている場合、モバイルで狭い画面のレイアウトが表示されることはありません。 width=device-width を設定すると、Apple のデフォルトの width=960px がデバイスの実際の幅で上書きされるため、メディアクエリーは意図したとおりに機能します。

+ +

したがって、ドキュメントの先頭に上記の HTML 行を常に含める必要があります

+ +

ビューポートメタタグで使用できる設定は次のように他にもありますが、一般的には上記の行を使用します。

+ + + +

minimum-scalemaximum-scale、特に user-scalableno に設定することは避けてください。 ユーザーには必要なだけズームを許可する必要があります。 これを禁止すると、アクセシビリティの問題が発生します。

+ +
+

: @viewport というビューポートメタタグを置き換えるように設計された CSS の @ 規則がありますが、ブラウザーのサポートが不十分です。 両方が使用されたときは、メタタグが @viewport を上書きします。

+
+ +

まとめ

+ +

レスポンシブデザインとは、表示される環境に対応するサイトまたはアプリのデザインを指します。 これには多くの CSS および HTML の機能とテクニックが含まれており、現在では基本的に Web サイトをデフォルトで構築する方法になっています。 サイトを携帯電話でアクセスするところを考えてください — デスクトップバージョンを縮小したサイトや、物事を見つけるために横にスクロールする必要があるサイトに出くわすことは、おそらくかなり珍しいことです。 これは、Web がレスポンシブデザインのこのアプローチに移行したためです。

+ +

また、これらのレッスンで学んだレイアウト方法の助けを借りて、レスポンシブデザインを実現することがはるかに容易になりました。 今日の Web 開発が初めてでも、レスポンシブデザインの初期よりも多くのツールを意のままに使用できます。 したがって、参照している資料の年齢を確認する価値があります。 歴史的な記事はまだ有用ですが、CSS と HTML の現代的な用法により、訪問者がどのデバイスを使用してサイトを表示しても、エレガントで便利なデザインをはるかに簡単に作成できます。

+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/css_layout/supporting_older_browsers/index.html b/files/ja/learn/css/css_layout/supporting_older_browsers/index.html new file mode 100644 index 0000000000..93feda2cf0 --- /dev/null +++ b/files/ja/learn/css/css_layout/supporting_older_browsers/index.html @@ -0,0 +1,248 @@ +--- +title: 古いブラウザーのサポート +slug: Learn/CSS/CSS_layout/Supporting_Older_Browsers +tags: + - Beginner + - CSS + - Guide + - Layout + - Learn + - feature queries + - flexbox + - float + - grid + - legacy +translation_of: Learn/CSS/CSS_layout/Supporting_Older_Browsers +--- +
{{LearnSidebar}}
+ +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Legacy_Layout_methods", "Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension", "Learn/CSS/CSS_layout")}}

+ +

このモジュールでは、フレックスボックスとグリッドをデザインの主なレイアウト方法として使用することをお勧めしています。 しかしながら、サイトへの訪問者には、古いブラウザーや、使用している方法をサポートしていないブラウザーを使用している人がいます。 これはウェブ上で常に当てはまります — 新しい機能が開発されると、ブラウザーによって異なるものが優先されます。 この記事では、古い技術のユーザーを締め出すことなく最新のウェブテクニックを使用する方法について説明します。

+ + + + + + + + + + + + +
前提知識:HTML の基本(HTML 入門を学ぶ)、および CSS の機能の考え方(CSS 入門ボックスの装飾を学ぶ)。
学習目標:使用したい機能をサポートしていない可能性がある、古いブラウザーでレイアウトのサポートを提供する方法を理解すること。
+ +

あなたのサイトのブラウザー利用状況はどうですか?

+ +

すべてのウェブサイトは、対象視聴者という点で異なります。 取るべきアプローチを決める前に、古いブラウザーでサイトにやってくる訪問者の数を調べてください。 あなたが追加したり置き換えたりしている既存のウェブサイトを持っているなら、人々が使用している技術を伝えることができる分析機能(analytics)を利用できるので、これは簡単です。 分析機能を持っていないか、真新しいサイトであるならば、場所によってフィルターをかけた統計(statistics)を提供することができる Statcounter のようなサイトがあります。

+ +

また、デバイスの種類やサイトの利用方法についても検討する必要があります。 例えば、モバイルデバイスの平均数よりも多いと予想される場合があります。 アクセシビリティと支援技術を使用している人々は常に考慮されるべきですが、いくつかのサイトではさらに重要になるかもしれません。 私の経験では、開発者は多くの場合、古いバージョンの Internet Explorer でのユーザーの 1% の体験を非常に心配していますが、はるかに多い数のアクセシビリティが必要な人々は考慮していません。

+ +

使用したい機能に対するサポートはどうですか?

+ +

サイトにやってくるブラウザーを知ったら、それがどのような技術をサポートしているかや、その技術を利用できない訪問者にどれだけ簡単に代替手段を提供できるかについて、使用したい技術を評価できます。 MDN では、CSS プロパティを詳述した各ページにブラウザーの互換性情報を提供することで、これを簡単にできるようにしています。 例えば、{{cssxref("grid-template-columns")}} のページを見てください。 このページの下部には、主要なブラウザーと、このプロパティのサポートを開始したバージョンの一覧をまとめた表があります。

+ +

+ +

機能がどの程度サポートされているかを調べるもう1つの一般的な方法は、Can I Use ウェブサイトです。 このサイトには、ウェブプラットフォームの機能の大部分と、それらのブラウザーのサポート状況に関する情報が記載されています。 あなたは場所によって使用統計を見ることができます — あなたが主に世界の特定の地域のためにユーザーを持っているサイトで働いているなら有用です。 Google Analytics アカウントをリンクして、あなたのユーザーデータに基づいて分析することもできます。

+ +

ユーザーが持っている技術、そしてあなたが使いたいと思うかもしれないことへのサポートを理解することは、すべての決断を下し、すべてのユーザーをサポートするための最善の方法を知るための良い場所にあなたを置きます。

+ +

サポートは「同じに見える」という意味ではありません

+ +

一部のユーザーはサイトを携帯電話で見たり、他のユーザーは大きなデスクトップ画面を見たりするため、ウェブサイトはすべてのブラウザーで同じように見えるとは限りません。 同様に、一部のユーザは古いブラウザーのバージョンを持ち、他のユーザは最新のブラウザーを持ちます。 一部のユーザーは、コンテンツがスクリーンリーダーによって読み上げられているのを聞いているかもしれないし、それを読むことができるようにページにズームインしているかもしれません。 全員をサポートするということは、防御的に設計されたバージョンのコンテンツを提供することを意味します。 その結果、最新のブラウザーでは見栄えがよくなりますが、それでも古いブラウザーのユーザにとっては基本レベルで使用できます。

+ +

基本レベルのサポートは、ページの通常フローが意味をなすように、コンテンツを適切に構成することによります。 非常に限られた機能の携帯電話を持っているユーザーは CSS の多くを得ないかもしれません、しかし内容は読みやすくする方法で流れます。 したがって、よく構造化された HTML 文書を常に出発点にする必要があります。 スタイルシートを削除した場合、コンテンツは意味をなしますか?

+ +

1つの選択肢は、非常に古いブラウザーや限られたブラウザーを使用している人々のための代替手段として、サイトのこのプレーンなビューを残すことです。 これらのブラウザーでこのサイトにアクセスしている人の数が非常に少ない場合は、最新のブラウザーと同様の経験をそれらの人に与えようとして時間を注いでも意味がありません。 サイトをよりアクセスしやすくするために時間をかけて、はるかに多くのユーザーにサービスを提供することをお勧めします。 プレーンな HTML ページと何から何までいろいろなものとの間には妥協点があり、CSS は実際にこれらの代替手段の作成をかなり簡単にしました。

+ +

CSS で代替手段を作成する

+ +

CSS の仕様には、2つのレイアウト方法が同じ項目に適用されたときにブラウザーが何をするのかを説明する情報が含まれています。 これは、例えばフロート項目が CSS グリッドレイアウトを使用しているグリッド項目でもある場合に何が起こるかの定義があることを意味します。 ブラウザーが理解できない CSS を無視するという知識とこの情報を組み合わせると、すでに説明した過去のテクニックを使用して単純なレイアウトを作成し、それをグリッドレイアウトを理解している最新のブラウザーではグリッドレイアウトで上書きする方法があります。

+ +

以下の例では、3つの <div> をフロートさせて、それらが一行に表示されるようにしました。 CSS グリッドレイアウトをサポートしていないブラウザーでは、ボックスの行はフロートレイアウトとして表示されます。 グリッド項目になったフロート項目はフロートのふるまいを失います。 つまり、wrapper をグリッドコンテナに変えることによって、フロート項目はグリッド項目になります。 ブラウザーがグリッドレイアウトをサポートしていればグリッドビューを表示し、そうでなければ display: grid と関連のプロパティを無視してフロートレイアウトが使用されます。

+ +
+
* {box-sizing: border-box;}
+
+.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  max-width: 400px;
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr;
+}
+
+.item {
+  float: left;
+  border-radius: 5px;
+  background-color: rgb(207,232,220);
+  padding: 1em;
+}
+
+ +
<div class="wrapper">
+  <div class="item">Item One</div>
+  <div class="item">Item Two</div>
+  <div class="item">Item Three</div>
+</div>
+
+ +

{{ EmbedLiveSample('Example1', '100%', '200') }}

+
+ +
+

: クリアされた項目がグリッド項目になると、{{cssxref("clear")}} プロパティも無効になります。 そのため、フッターがクリアされたレイアウトを作成し、それをグリッドレイアウトにすることができます。

+
+ +

代替手段の方法

+ +

このフロートの例と同様の方法で使用できるレイアウト方法はいくつかあります。 作成するレイアウトパターンに最も適したものを選択できます。

+ +
+
フロートとクリア
+
上記のように、フロート項目またはクリアされた項目がフレックス項目またはグリッド項目になると、float プロパティや clear プロパティはレイアウトに影響しなくなります。
+
display: inline-block
+
この方法を使用して列レイアウトを作成できます。 項目に display: inline-block が設定されていて、それからフレックス項目またはグリッド項目になる場合、inline-block のふるまいは無視されます。
+
display: table
+
CSS レイアウト入門で説明した CSS 表の作成方法は、代替手段として使用できます。 CSS 表レイアウトが設定されている項目は、それらがフレックス項目またはグリッド項目になると、このふるまいを失います。 重要なことに、表構造を修正するために作成された匿名ボックスは作成されません。
+
段組みレイアウト
+
特定のレイアウトでは、代替手段として段組みレイアウトを使用できます。 コンテナに定義された column-* プロパティのいずれかがあり、その後グリッドコンテナになると、段組みレイアウトのふるまいは起こりません。
+
グリッドの代替手段としてのフレックスボックス
+
フレックスボックスは、IE10 と IE11 でサポートされているため、グリッドよりもブラウザーのサポートが優れています。 ただし、このレッスンの後半で、古いブラウザーでのフレックスボックスのかなり曖昧でわかりにくいサポートについて説明します。 フレックスコンテナをグリッドコンテナにした場合、子に適用されている flex プロパティはすべて無視されます。
+
+ +

古いブラウザーでの多くのレイアウトの調整では、このように CSS を使用することでまともな体験を与えることができるかもしれません。 古くてよくサポートされているテクニックに基づいた、より単純なレイアウトを追加してから、新しい CSS を使用して、視聴者の 90% 以上が見るレイアウトを作成します。 ただし、代替手段のコードに新しいブラウザーでも解釈されるものを含める必要がある場合があります。 この良い例は、列をグリッド表示に近づけるためにフロート項目にパーセント幅を追加し、コンテナを埋めるように伸縮する場合です。

+ +

フロートレイアウトでは、パーセントはコンテナから計算されます — 33.333% はコンテナ幅の3分の1です。 ただしグリッドでは、 33.333% は項目が配置されているグリッド領域から計算されるため、グリッドレイアウトが導入されると、実際に必要なサイズのさらに3分の1になってしまいます。

+ +
+
* {box-sizing: border-box;}
+
+.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  max-width: 400px;
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr;
+}
+
+.item {
+  float: left;
+  border-radius: 5px;
+  background-color: rgb(207,232,220);
+  padding: 1em;
+  width: 33.333%;
+}
+
+ +
<div class="wrapper">
+  <div class="item">Item One</div>
+  <div class="item">Item Two</div>
+  <div class="item">Item Three</div>
+</div>
+
+ +

{{ EmbedLiveSample('Example2', '100%', '200') }}

+
+ +

この問題に対処するには、グリッドがサポートされているかどうか、したがってグリッドが幅を上書きするかどうかを検出する方法が必要です。 CSS は下記の解決策を持っています。

+ +

機能クエリ

+ +

機能クエリを使用すると、ブラウザーが特定の CSS 機能をサポートしているかどうかをテストできます。 つまり、特定の機能をサポートしていないブラウザー用の CSS を作成してから、そのブラウザーがサポートしているかどうかを確認し、サポートしている場合は素敵なレイアウトを追加することができます。

+ +

上記の例に機能クエリを追加すると、グリッドをサポートしている場合、項目の幅を auto に戻すことができます。

+ +
+
* {box-sizing: border-box;}
+
+.wrapper {
+  background-color: rgb(79,185,227);
+  padding: 10px;
+  max-width: 400px;
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr;
+}
+
+.item {
+  float: left;
+  border-radius: 5px;
+  background-color: rgb(207,232,220);
+  padding: 1em;
+  width: 33.333%;
+}
+
+@supports (display: grid) {
+  .item {
+      width: auto;
+  }
+}
+
+ +
<div class="wrapper">
+  <div class="item">Item One</div>
+  <div class="item">Item Two</div>
+  <div class="item">Item Three</div>
+</div>
+
+ +

{{ EmbedLiveSample('Example3', '100%', '200') }}

+
+ +

機能クエリのサポートは最近のブラウザーでは非常に優れていますが、CSS グリッドをサポートしていないブラウザーでも機能クエリをサポートしていないことに注意してください。 これは、上で詳述されたアプローチがそれらのブラウザーで働くということを意味します。 していることは、すべての機能クエリの外側で、古い CSS を最初に書くことです。 グリッドをサポートせず、機能クエリもサポートしないブラウザーは、理解できるレイアウト情報を使用し、それ以外はすべて無視します。 機能クエリをサポートするブラウザーは CSS グリッドもサポートするため、グリッドのコードと機能クエリ内のコードを実行します。

+ +

機能クエリの仕様には、ブラウザーが機能をサポートしていないことをテストする機能も含まれています — これは、ブラウザーが機能クエリをサポートしている場合にのみ役立ちます。 将来的には、機能クエリをサポートしていないブラウザーはなくなるため、サポートの欠如を確認するアプローチが有効になります。 ただし現時点では、最善のサポートのために古い CSS を使用してから上書きするというアプローチを使用してください。

+ +

古いバージョンのフレックスボックス

+ +

古いバージョンのブラウザーでは、以前のフレックスボックス仕様の繰り返しを見つけることができます。 これを書いている時点で、これはほとんどフレックスボックスのために -ms- 接頭辞を使う Internet Explorer 10 の問題です。 これはまた、いくつかの古い記事やチュートリアルが存在することを意味します。 この便利なガイド(英語)は何を見ているのかを確認するのに役立ちますし、非常に古いブラウザーでフレックスのサポートが必要な場合にも役立ちます。

+ +

IE10 と IE11 の接頭辞版のグリッド

+ +

CSS グリッド仕様は、当初 Internet Explorer 10 で試作されました。 つまり、IE10 と IE11 は最新のグリッドをサポートしていませんが、このサイトに記載されている最新の仕様とは異なり、非常に使いやすいバージョンのグリッドレイアウトを使用しています。 IE10 および IE11 の実装は、前に -ms- が付いています。 つまり、これらのブラウザーに使用でき、マイクロソフト以外のブラウザーでは無視されます。 Edge はまだ古い構文を理解しているので、最新のグリッド CSS ではすべてが安全に上書きされるように注意してください。

+ +

グリッドレイアウトのプログレッシブエンハンスメントのガイドはグリッドの IE バージョンを理解するのを助けることができ、このレッスンの最後にいくつかの追加の役に立つリンクを含めました。 ただし、以前のバージョンの IE に非常に多くの訪問者がいない限り、サポートされていないすべてのブラウザーで機能する代替手段の作成に集中することをお勧めします。

+ +

古いブラウザーをテストする

+ +

フレックスボックスとグリッドをサポートしているブラウザーの大多数では、古いブラウザーをテストするのはかなり難しいかもしれません。 1つの方法は、クロスブラウザーテストのモジュールに詳述されているように、Sauce Labs のようなオンラインテストツールを使うことです。

+ +

また、仮想マシンをダウンロードしてインストールし、自分のコンピュータ上の封じ込められた環境で古いバージョンのブラウザーを実行することもできます。 古いバージョンの Internet Explorer にアクセスできることは特に便利で、そのために、マイクロソフトはさまざまな仮想マシンを無料でダウンロード(英語)できるようにしました。 これらは、Mac、Windows、Linux の各オペレーティングシステムで利用可能で、Windows コンピュータを使用していなくても、古い Windows ブラウザーや最新の Windows ブラウザーでテストするのに最適な方法です。

+ +

まとめ

+ +

今やあなたは自信を持ってグリッドやフレックスボックスのようなテクニックを使い、古いブラウザーのための代替手段を作り、そして将来現れるであろう新しいテクニックを利用する知識を持っています。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/CSS/CSS_layout/Legacy_Layout_methods", "Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension", "Learn/CSS/CSS_layout")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/first_steps/getting_started/index.html b/files/ja/learn/css/first_steps/getting_started/index.html new file mode 100644 index 0000000000..e11d48443c --- /dev/null +++ b/files/ja/learn/css/first_steps/getting_started/index.html @@ -0,0 +1,263 @@ +--- +title: CSS 入門 +slug: Learn/CSS/First_steps/Getting_started +tags: + - Beginner + - CSS + - Classes + - Elements + - Learn + - Selectors + - Syntax + - state +translation_of: Learn/CSS/First_steps/Getting_started +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}
+ +

この記事では、かんたんな HTML コードに CSS を適用させ、その過程でこの言語についての実用的なことを学びます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、ソフトウェアのインストールファイルの働き方についての基本的な知識、HTML の基本 (HTML序論を学んでいること。)
目的:CSS 文書と HTML ファイルのリンクのさせかたを理解し、簡単なテキストをスタイリングできるようになる。
+ +

HTML からはじめよう

+ +

HTML 文書から始めましょう。あなたのコンピューターのフォルダーに index.html として以下のコードを保存してください。

+ +
<!doctype html>
+<html lang="ja">
+<head>
+    <meta charset="utf-8">
+    <title>CSS 入門</title>
+</head>
+
+<body>
+
+    <h1>見出し1です</h1>
+
+    <p>これは第一段落の文です。この文には <span>span 要素</span>
+と<a href="http://example.com">リンク</a>が含まれます。</p>
+
+    <p>これは第二段落の文です。この文には <em>em 要素</em>が含まれます。</p>
+
+    <ul>
+        <li>一つ目の項目</li>
+        <li>二つ目の項目</li>
+        <li><em>三つ目</em>の項目</li>
+    </ul>
+
+</body>
+
+</html>
+
+ +
+

: もし簡単にファイルの作れないデバイスや環境でこの記事を読んでいても心配しないでください。このページにあるコードを書くためにライブコードエディターが用意されています。

+
+ +

CSS を加える

+ +

まず必要なのは、使いたい CSS ルールを HTML 文書に適用させることです。これには一般的に3つの方法がありますが、いまは最も一般的で便利な方法— CSS を {{htmlelement("head")}} 要素の中にリンクする方法を見てみましょう。

+ +

HTML ドキュメントとおなじフォルダーにファイルをつくり、styles.css として保存してください。拡張子 .css となっているのが CSS ファイルです。

+ +

styles.cssindex.html にリンクさせるには、HTML 文書にある {{htmlelement("head")}} 要素の中につぎのコードを追記してください:

+ +
<link rel="stylesheet" href="styles.css">
+ +

{{htmlelement("link")}} 要素はブラウザーに、スタイルシートがあること、rel 属性を使うこと、href 属性の値でスタイルシートのある場所を伝えます。styles.css に以下のルールを記述すれば、CSS が働くかテストできます。使っているコードエディターでつぎのコードを CSS ファイルに追記してください:

+ +
h1 {
+  color: red;
+}
+ +

HTML ファイルと CSS ファイルを保存し、ブラウザーでこのページを再読み込みしてみましょう。文書の先頭にある見出し 1 が赤くなるはずです。もしそうなったら、おめでとうございます。CSS の HTML への適用に成功しました! もしそうならなかったら、すべてを正しく入力しているか慎重に確認してください。

+ +

あなたのコンピューターに保存した styles.css を使い続けても良いですし、このチュートリアルの下の方にあるインタラクティブエディターを使い続けることもできます。もし最初のパネルにある CSS が 上にある HTML 文書とリンクされているなら、インタラクティブエディターは動作します。

+ +

HTML 要素をスタイリングする

+ +

見出しを赤くすることで、HTML 要素に焦点をあてたスタイリングを試しました。要素セレクタHTML の要素名を直接あてはめるセレクタ)に焦点をあてたのです。文書内のすべての段落に焦点をあてるなら、セレクタとして p を使うことができます。すべての段落を緑色にするために次を使います:

+ +
p {
+  color: green;
+}
+ +

セレクタをカンマで区切ることによって、同時に複数のセレクタへ焦点をあてることができます。もしすべての段落とリストすべてを緑にしたければ、CSS のルールセットは次のようになります:

+ +
p, li {
+    color: green;
+}
+ +

下にあるインタラクティブエディターのコードボックスを編集するか、コンピューターに保存された CSS ファイルを編集してこのルールセットを試してみてください。

+ +

{{EmbedGHLiveSample("css-examples/learn/getting-started/started1.html", '100%', 900)}} 

+ +

要素の基本的なふるまいを変える

+ +

よくマークアップされた HTML 文書をみると、かんたんな例でさえ、基本的なスタイリングを加えることでブラウザーが HTML を読みやすくしているかがわかります。見出しは大きく太線になっているし、リストは箇条書きになっています。これはブラウザーがすべてのページにデフォルトで適用されるスタイルシートを含んでいるために起きます。それらがなければ、すべてのテキストがまとまって一緒に実行され、すべてを一からスタイリングしなければなりません。最新のブラウザーはすべて、ほぼ同じ方法をもちいて、デフォルトで HTML コンテンツを表示します。

+ +

ブラウザーが選んだのとは別のスタイリングにしたい事もあるでしょう。これには単純に変更したい HTML 要素をえらび、CSS ルールを変更したい外観に変えるだけで可能です。よい例が <ul> 要素、つまり順番なしリストです。箇条書きの点がついていますが、もしこれが要らないと思ったら次のようにして削除することができます:

+ +
li {
+  list-style-type: none;
+}
+ +

これをあなたの CSS に加えて試してみてください。

+ +

list-style-type プロパティはどんな値がサポートされているか MDN上で調べるのに適したプロパティです。list-style-type のページをみるとページの上部に違うプロパティ値を試せる対話型の例があります。そしてページの下部には使えるプロパティ値が詳細に説明されています。

+ +

このページをみると、どのようなものに変えられるか見つけられます。プロパティ値 square  に変えてみてください。

+ +

クラスを加える

+ +

これまで、HTML 要素名をもとにしたスタイリングをしてきました。これは、文書内にあるその要素すべてをおなじ見ばえにしたいときには有効です。しかしそんな場合はほとんどないので、ほかを変えずに一部の要素だけを選ぶ方法を知っておく必要があります。もっとも一般的なのが、HTML 要素にクラスを追加し、それに焦点をあてる方法です。

+ +

HTML 文書の 2番目のリストアイテムへ、こんな風に class 属性を加えてください:

+ +
<ul>
+  <li>Item one</li>
+  <li class="special">二つ目の項目</li>
+  <li><em>三つ目</em>の項目</li>
+</ul>
+ +

ピリオドから始まるセレクタを作ることで、special クラス に焦点を当てることができます。以下を CSS に加えてください:

+ +
.special {
+  color: orange;
+  font-weight: bold;
+}
+ +

保存してからブラウザーを更新し結果を見てみましょう。

+ +

ページ上でおなじ見た目にしたいリストアイテムに対して special クラスを適用できます。たとえば、段落内にある<span> 要素にも同じく、オレンジの太字にしたいかもしれません。これにも class 属性の値として special を加えてみてください。上書き保存後にページを再読み込みして結果を確認してみましょう。

+ +

HTML 要素セレクタに続けてクラスセレクタが記述されているのを時々見るかもしれません:

+ +
li.special {
+  color: orange;
+  font-weight: bold;
+}
+ +

この構文は、「special クラスをもっている li 要素へ焦点をあてろ」という意味です。もしそうなっていたらもう、<span> 要素やほかに special クラスにした要素には適用できません。セレクタのリストに次を付け加える必要があります:

+ +
li.special,
+span.special {
+  color: orange;
+  font-weight: bold;
+}
+ +

いくつかのクラスがたくさんの要素に適用され、スタイリングが必要になる度に CSS を編集し続けることを望まないかもしれません。したがって、ある要素だけに特別なルールを作成し、他の要素に適用されないようにする場合を除き、要素をバイパスしてクラスを参照することが最善の場合があります。

+ +

文書内の場所に基づいてスタイリングする

+ +

文書のどこにあるかで見栄えを変えたい時があります。それを助けるセレクタはいくつかありますが、いまは 2種類だけ見てみましょう。HTML 文書には 2 つの <em> 要素があります — ひとつは段落の中に、もうひとつはリストアイテムの中に、です。<li> 要素の中にある <em> だけを選びたいとき、ディセンダント・コンビネーター と呼ばれるセレクタを使うことができます。これは2つの異なるセレクタのあいだにスペースを設けることで設置できます。

+ +

CSS につぎのルールセットを追加してください。

+ +
li em {
+  color: rebeccapurple;
+}
+ +

このセレクタは <li> 要素の中にある <em> 要素を選択します。よって HTML 文書の中で、3番目のリストアイテム内にある <em> 要素はパープルに変わっていますが、段落内にある <em> 要素は変更されていません。

+ +

HTML ドキュメント内で、見出しの直後に来る段落を見出しとおなじ階層レベルにしたいと思うことがあるかもしれません。このときはセレクタ同士の間に +  を入れます(adjacent sibling combinator:アジェイセント・シブリング・コンビネーター)。

+ +

いま扱っている CSS につぎのルールセットを追加してみてください:

+ +
h1 + p {
+  font-size: 200%;
+}
+ +

下のライブ例では、上に挙げた2つのルールセットが含まれています。ここに、段落内にある span 要素を赤くするルールセットを追加してください。正しくできれば第一段落の span 要素は赤くなり、最初のリストアイテムは色が変わらないはずです。

+ +

{{EmbedGHLiveSample("css-examples/learn/getting-started/started2.html", '100%', 1100)}}

+ +
+

: ごらんの通り、CSS には要素に焦点をあてるための方法がいくつかあります。ここに挙げたのと、もっとたくさんのセレクタをこのコースの後にあるセレクタの記事で見ていきます。

+
+ +

状態に基づいてスタイリングする

+ +

最後にこのチュートリアルで取り上げるのは、状態に基づいてスタイルを設定する方法です。かんたんな例はリンクのスタイリングです。リンクをスタイリングするとき、<a> (anchor) 要素に焦点をあてる必要があります。リンクされたページを開いていなかったり、開いた後だったり、マウスの矢印を置いたり(ホバー)、キーボードで選択したり、クリックしたりといったように状態が変わります。こうしたさまざまな状態を CSS で選ぶことができます。— 以下だと、リンクされたページを開く前はピンクに、開いた後は緑になります。

+ +
a:link {
+  color: pink;
+}
+
+a:visited {
+  color: green;
+}
+ +

ユーザーがリンクの上にマウスの矢印を持っていく(ホバー)とリンクの見た目を変えるようにできます。たとえばつぎのルールセットだと、リンクの下線が消えます:

+ +
a:hover {
+  text-decoration: none;
+}
+ +

下のライブ例では、プロパティ値をいろいろ変えることでさまざまなリンクの状態を試せます。すでに加えられているルールセットをみると、ピンクがとても明るくて読みづらいことがわかります。もっといい色に変えてみましょう。太字に変えられますか?

+ +

{{EmbedGHLiveSample("css-examples/learn/getting-started/started3.html", '100%', 900)}} 

+ +

リンクをホバーすると下線が消えるようにしていますが、どんな状態でも下線が消えているようにできます。ただし実際のサイトでは、ページを見ている人に、リンクはリンクであることを知らせるのを忘れないようにしてください。下線を残すのは、ユーザーが慣れているように、テキスト内にリンクがあることを伝える重要な手掛かりになります。CSS にふくまれるあらゆるものには、変更によって文章を使いづらくするおそれがあることを強調しておきます。

+ +
+

: MDN の記事で、アクセシビリティ についての注意をたびたび目にするでしょう。これについて語る時は、ウェブページがどんな人にも理解でき、使えるものである必要性に言及しています。

+ +

訪問者はマウス付きコンピューター やタッチスクリーン付き電話で見ているかもしれません。あるいはスクリーンリーダーで文章を読んでいることや、大きな文字をつかう必要があることや、キーボードだけを使っていることもあるでしょう。

+ +

プレーンな HTML ドキュメントは一般的にあらゆる人に対してアクセシブルですので、スタイリングするときはアクセシビリティを下げないようにするのが大切です。

+
+ +

セレクタとコンビネーターを組み合わせる

+ +

複数のセレクタとコンビネーターを組み合わせることができます:

+ +
/* <article> 要素の内側にある <p> 要素の <span> 要素に焦点を当てるとき  */
+article p span { ... }
+
+/* <h1> 要素の直後に来る <ul> 要素の、そのまた直後に来る <p> 要素に焦点を当てるとき */
+h1 + ul + p { ... }
+ +

複数の形のセレクタも組み合わせられます。以下のコードを CSS に追加してみてください:

+ +
body h1 + p .special {
+  color: yellow;
+  background-color: black;
+  padding: 5px;
+}
+ +

これは <body> 要素の中にある <h1> 要素の直後に来た <p> 要素の中にある special クラスの要素をスタイリングします。

+ +

HTML のうち、スタイルが適用されるのは <span class="special"> のみです。

+ +

現時点では複雑に思えても心配しなくて大丈夫です。CSS を書いていくうちにすぐに理解できるようになります。

+ +

まとめ

+ +

このチュートリアルでは、CSS によるドキュメントのスタイル設定の仕方をいくつか見てきました。残りのレッスンでさらに深堀りしていきます。あたなはもうすでに、テキストのスタイリングや要素のさまざまな指定の仕方、さらには MDN ドキュメント内でのプロパティと値の調べ方といったことも理解したはずです。

+ +

次のレッスンでは、CSS の構造を見ていきます。

+ +

{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}

+ +

このモジュールの記事

+ +
    +
  1. CSS とは何か?
  2. +
  3. CSS 入門
  4. +
  5. CSS の全体像
  6. +
  7. CSS はどう働くか?
  8. +
  9. 新しい知識を使う
  10. +
diff --git a/files/ja/learn/css/first_steps/how_css_is_structured/index.html b/files/ja/learn/css/first_steps/how_css_is_structured/index.html new file mode 100644 index 0000000000..a9e2ae7130 --- /dev/null +++ b/files/ja/learn/css/first_steps/how_css_is_structured/index.html @@ -0,0 +1,530 @@ +--- +title: CSS の全体像 +slug: Learn/CSS/First_steps/How_CSS_is_structured +tags: + - Beginner + - CSS + - HTML + - Learn + - Selectors + - Structure + - comments + - properties + - shorthand + - values + - whitespace +translation_of: Learn/CSS/First_steps/How_CSS_is_structured +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}
+ +

CSS の概要と基本的な使い方について理解できたので、今度は CSS の構造をもう少し詳しく見てみましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータリテラシー、 基本的なソフトウェアのインストール、 基本的な ファイル操作、 HTML の基本 (HTML 入門で学習)、基本的な CSS の動作
目的:CSS の基本的な構文の構造を詳細に学ぶ。
+ +

CSS を HTML に適用する

+ +

まず、文書に CSS を適用する方法として、外部スタイルシートを使う方法、内部スタイルシートを使う方法、インラインスタイルを使う方法の3つの方法を見てみましょう。

+ +

外部スタイルシート

+ +

外部スタイルシートには .css という拡張子を持つ別のファイルに CSS が含まれています。これは、文書に CSS を持ち込む最も一般的で便利な方法です。1つの CSS ファイルを複数のウェブページにリンクして、すべてのウェブページを同じ CSS スタイルシートでスタイル付けすることができます。 CSS 入門では、外部のスタイルシートをウェブページにリンクしました。

+ +

HTML の <link> 要素から外部 CSS スタイルシートを参照しています。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My CSS experiment</title>
+    <link rel="stylesheet" href="styles.css">
+  </head>
+  <body>
+    <h1>Hello World!</h1>
+    <p>This is my first CSS example</p>
+  </body>
+</html>
+ +

CSS ファイルはこのようになります。

+ +
h1 {
+  color: blue;
+  background-color: yellow;
+  border: 1px solid black;
+}
+
+p {
+  color: red;
+}
+ +

{{htmlelement("link")}} 要素の href 属性は、ファイルシステム上のファイルを参照する必要があります。上の例では、 CSS ファイルは HTML 文書と同じフォルダーにありますが、どこか別の場所に配置してパスを調整することもできます。以下に 3 つの例を示します。

+ +
<!-- 現在のディレクトリの中の styles というサブディレクトリの中 -->
+<link rel="stylesheet" href="styles/style.css">
+
+<!-- カレントディレクトリの中にある styles というサブディレクトリの中にある、 general というサブディレクトリの中 -->
+<link rel="stylesheet" href="styles/general/style.css">
+
+<!-- ひとつ上のレベルのディレクトリに行き、その下にある styles というサブディレクトリの中 -->
+<link rel="stylesheet" href="../styles/style.css">
+ +

内部スタイルシート

+ +

内部スタイルシートは、 HTML 文書の中に配置します。内部スタイルシートを作成するには、 CSS を HTML 文書の {{htmlelement("head")}} の中にある {{htmlelement("style")}} 要素の中に入れてください。

+ +

例えば、 HTML はこのようになります。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My CSS experiment</title>
+    <style>
+      h1 {
+        color: blue;
+        background-color: yellow;
+        border: 1px solid black;
+      }
+
+      p {
+        color: red;
+      }
+    </style>
+  </head>
+  <body>
+    <h1>Hello World!</h1>
+    <p>This is my first CSS example</p>
+  </body>
+</html>
+ +

状況によっては、内部スタイルシートが便利な場合もあります。たとえば、コンテンツ管理システムを使用している場合、外部の CSS ファイルを変更することがブロックされているかもしれません。

+ +

しかし、複数のページを持つサイトでは、内部スタイルシートは効率の悪い作業方法になります。内部スタイルシートを使用して、複数のページに統一された CSS スタイルを適用するには、そのスタイルを使用するすべてのウェブページに内部スタイルシートをコピーしなければなりません。効率性の低下はサイトの保守にも影響します。内部スタイルシートの CSS では、1 つの簡単なスタイル変更でも、複数のウェブページの編集が必要になるリスクがあります。

+ +

インラインスタイル

+ +

インラインスタイルは、単一の HTML 要素のみに影響を与える CSS 宣言で、 style 属性の中に記述します。 HTML 文書におけるインラインスタイルの実装は次のようになります。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My CSS experiment</title>
+  </head>
+  <body>
+    <h1 style="color: blue;background-color: yellow;border: 1px solid black;">Hello World!</h1>
+    <p style="color:red;">This is my first CSS example</p>
+  </body>
+</html>
+ +

この方法での CSS の使用は、可能な限り避けてください。まず、 CSS の実装の中では最も保守の効率が悪いものです。一つのスタイルを変更するために、一つのウェブページ内で複数の編集が必要になるかもしれません。第二に、インライン CSS はプレゼンテーション用のコードを HTML やコンテンツに混ぜてしまうため、すべてが読んだり理解したりしにくいものになってしまいます。コードとコンテンツを分離すれば、ウェブサイトで働くすべての人にとって保守が容易になります。

+ +

インラインスタイルが一般的な状況はいくつかあります。作業環境が非常に制限されている場合は、インラインスタイルの使用に頼らざるを得ないかもしれません。例えば、 CMS では HTML の本文しか編集できない場合があります。また、できるだけ多くのメールクライアントとの互換性を実現するために、 HTML メールでインラインスタイルが多用されているのを見ることもあるでしょう。

+ +

CSS を試してみる

+ +

次の演習では、コンピューターにフォルダーを作成してください。フォルダーには好きな名前をつけてください。以下のテキストをコピーして、フォルダーの中に 2 つのファイルを作成してください。

+ +

index.html:

+ +
<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>My CSS experiments</title>
+    <link rel="stylesheet" href="styles.css">
+  </head>
+  <body>
+
+    <p>Create your test HTML here</p>
+
+  </body>
+</html>
+ +

styles.css:

+ +
/* Create your test CSS here */
+
+p {
+  color: red;
+}
+ +

試してみたい CSS を見つけたら、 HTML の <body> の内容をスタイル付けする HTML に置き換え、テスト用の CSS コードを CSS ファイルに追加してください。

+ +

別の方法として、以下のインタラクティブなエディターを使用することもできます。

+ +

{{EmbedGHLiveSample("css-examples/learn/getting-started/experiment-sandbox.html", '100%', 800)}}

+ +

楽しみながら、先に進んでいきましょう。

+ +

セレクター

+ +

セレクターは CSS に欠かせない構成要素です。CSS 入門のチュートリアルでは、すでにさまざまな種類のセレクターを見てきました。セレクターは、 HTML 文書のなかでスタイルを適用する対象を指定するものです。もし CSS が期待通りにコンテンツに適用されなかったら、セレクターが一致すると思っていた方法で一致していないのかもしれません。

+ +

それぞれの CSS 規則の先頭には、セレクターまたはセレクターのリストを書きます。これによって、ブラウザにどの要素にCSS規則を適用するかを指示します。次のコード例は、いずれも有効なセレクター、またはセレクターのリストです。

+ +
h1
+a:link
+.manythings
+#onething
+*
+.box p
+.box p:first-child
+h1, h2, .intro
+ +

上記のセレクターを使った CSS 規則を作ってみてください。セレクターによってスタイル付けされる HTML を追加します。上記の構文に馴染みのないものがあれば、 MDN を検索してみてください。

+ +
+

: 次のモジュールの記事 CSS セレクター で、セレクターについてより詳しく学ぶことができます。

+
+ +

詳細度

+ +

2 つのセレクターが同じ HTML 要素を選択するシナリオに遭遇するかもしれません。以下のスタイルシートを考えてみましょう。 p セレクターで段落のテキストを青に設定します。しかし、選択された要素のテキストを赤に設定するクラスもあります。

+ +
.special {
+  color: red;
+}
+
+p {
+  color: blue;
+}
+ +

HTML 文書の中に special のクラスを持つ段落があるとします。両方の規則が適用されます。どちらのセレクターが優先されるでしょうか?段落のテキストが青と赤のどちらになると思いますか?

+ +
<p class="special">What color am I?</p>
+ +

CSS 言語には、競合が発生した場合にどちらのセレクターが強いかを制御するための規則があります。これらの規則はカスケード (cascade) 詳細度 (specificity) と呼ばれています。以下のコードブロックでは、 p セレクターに対して2つの規則が定義されていますが、段落テキストは青くなります。これは、段落テキストを青に設定する宣言がスタイルシートの後に現れているからです。後のスタイルは、それより前のスタイルシートに現れた競合するスタイルを置き換えます。これがカスケード規則です。

+ +
p {
+  color: red;
+}
+
+p {
+  color: blue;
+}
+ +

しかし、クラスセレクターと要素セレクターの間に競合がある前の例では、クラスが優先され、赤い段落テキストがレンダリングされます。スタイルシートの後方に競合するスタイルが表示されているにもかかわらず、どうしてこのようなことが起こるのでしょうか?クラスは、要素セレクターよりも詳細度が高いことになっており、より具体的であると評価されるので、他の競合するスタイル宣言をキャンセルしたのです。

+ +

この実験を自分でやってみましょう。 HTML を追加して、2つの p { ... } 規則をスタイルシートに追加します。次に、最初の p セレクターを .special に変更して、それがスタイルをどのように変えるかを見てみましょう。

+ +

詳細度とカスケードの規則は、最初は複雑に見えるかもしれません。これらの規則は、 CSS に慣れてくると理解しやすくなります。次のモジュールの カスケードと継承 の章では、詳細度の計算方法を含めて詳しく説明しています。

+ +

今のところ、詳細度が存在することを覚えておいてください。スタイルシートの他の何かがより高い詳細度を持っているために、 CSS が期待通りに適用されないことがあります。 1 つの要素に複数の規則が適用される可能性があることを認識することは、この種の問題を解決するための最初のステップです。

+ +

プロパティと値

+ +

もっとも基本的なレベルでは、 CSS は2つの部品でできています。

+ + + +

次の例では、一組のプロパティと値を強調表示しています。プロパティ名は color で、値は blue です。

+ +

A declaration highlighted in the CSS

+ +

プロパティが値と組み合わせられているとき、この組み合わせを CSS 宣言 (CSS declaration) と呼びます。 CSS 宣言は CSS 宣言ブロック (CSS Declaration Blocks) の中に入っています。次のコード例では CSS の宣言ブロックを強調しています。

+ +

A highlighted declaration block

+ +

そして、 CSS 宣言ブロックはセレクターと組になって CSS 規則セット (または CSS 規則) になります。1つは h1 セレクター用、もう1つは p セレクター用です。色付きのハイライトは h1 規則を識別します。

+ +

The rule for h1 highlighted

+ +

CSS プロパティを特定の値に設定することが、文書のレイアウトとスタイルを定義する主な方法です。 CSS エンジンは、どの宣言がページの各要素に適用されるかを計算します。

+ +
+

重要: CSS のプロパティと値は大文字と小文字を区別します。それぞれのプロパティと値の組はコロン (:) で区切られます。

+
+ +

以下に挙げたプロパティの様々な値を調べてみてください。それぞれの HTML 要素にスタイルを適用する CSS 規則を書いてみてください。

+ + + + + +
+

重要: プロパティが不明だった場合、または指定されたプロパティの値が妥当ではなかった場合は、宣言が無効なものとして扱われます。ブラウザーの CSS エンジンはこれを完全に無視します。

+
+ +
+

重要: CSS (および他のウェブ標準) では、言語ごとに綴りに揺れがあったり確実でない場合には、アメリカ綴りを標準とすることが合意されています。例えば、 colorcolor と綴るべきであり、 colour では動作しません。

+
+ +

関数

+ +

ほとんどの値は比較的単純なキーワードや数値ですが、関数の形をとる値もあります。例として、calc() 関数があります。これは CSS 内で簡単な数式を行うことができます。

+ +
+
<div class="outer"><div class="box">The inner box is 90% - 30px.</div></div>
+ +
.outer {
+  border: 5px solid black;
+}
+
+.box {
+  padding: 10px;
+  width: calc(90% - 30px);
+  background-color: rebeccapurple;
+  color: white;
+}
+
+ +

これは次のように表示されます。

+ +

{{EmbedLiveSample('calc_example', '100%', 200)}}

+ +

関数は、関数名と、関数に渡す値を囲む括弧で構成されています。上記の calc() の例では、値は、このボックスの幅を含むブロックの幅の 90% から 30 ピクセルを引いた値と定義しています。計算の結果は、事前に計算して静的な値として入力できるものではありません。

+ +

他の例としては、 {{cssxref("transform")}} のさまざまな値、たとえば rotate() などがあります。

+ +
+
<div class="box"></div>
+ +
.box {
+  margin: 30px;
+  width: 100px;
+  height: 100px;
+  background-color: rebeccapurple;
+  transform: rotate(0.8turn);
+}
+
+ +

上記のコードの出力は次のようになります。

+ +

{{EmbedLiveSample('transform_example', '100%', 200)}}

+ +

以下に挙げたプロパティのそれぞれの値を調べてみましょう。ぞれぞれの HTML 要素にスタイルを適用する CSS 規則を記述してみましょう。

+ + + +

アット規則

+ +

CSS のアット規則 は、 CSS が実行すること、またはそれがどのように動作するべきかの指示を提供します。いくつかのアット規則は、キーワードと値だけのシンプルなものです。例えば、 @import はスタイルシートを別の CSS スタイルシートにインポートします。

+ +
@import 'styles2.css';
+ +

よく目にするであろうアット規則が @media があり、メディアクエリを作成するために使用されます。メディアクエリは CSS スタイルを提供する条件を使用します。

+ +

以下の例では、スタイルシートは <body> 要素に既定でピンクの背景を定義しています。しかし、ブラウザーのビューポートが 30em よりも広い場合は、青い背景を定義するメディアクエリが続いています。

+ +
body {
+  background-color: pink;
+}
+
+@media (min-width: 30em) {
+  body {
+    background-color: blue;
+  }
+}
+ +

これ以外のアット規則にも、これからのチュートリアルで遭遇するでしょう。

+ +

ビューポートの幅に基づいてスタイルを変更するメディアクエリを追加できるかどうかを確認してください。ブラウザーウィンドウの幅を変更して結果を確認してみてください。

+ +

一括指定

+ +

{{cssxref("font")}}, {{cssxref("background")}}, {{cssxref("padding")}}, {{cssxref("border")}}, {{cssxref("margin")}} のようなプロパティは一括指定プロパティ (shorthand properties) と呼ばれています。これは一括指定プロパティが複数の値を1行で設定するからです。

+ +

例えば、コードのこの 1 行を見てください。

+ +
/* 4 つの値による一括定義、例えば padding や margin
+   では、値が適用される順序は top, right, bottom, left の順 (top から時計回り) です。
+   他の種類の一括指定もあり、例えば 2 つの値による一括指定を padding/margin に設定すると、
+   top/bottom と left/right になります。*/
+padding: 10px 15px 15px 5px;
+ +

これは以下の 4 行のコードと同等です。

+ +
padding-top: 10px;
+padding-right: 15px;
+padding-bottom: 15px;
+padding-left: 5px;
+ +

次の 1 行を見てください。

+ +
background: red url(bg-graphic.png) 10px 10px repeat-x fixed;
+ +

以下の 5 行と同等です。

+ +
background-color: red;
+background-image: url(bg-graphic.png);
+background-position: 10px 10px;
+background-repeat: repeat-x;
+background-attachment: fixed;
+ +

コースの後半では、他にも多くの一括指定プロパティの例に遭遇します。 MDN の CSS リファレンスは、あらゆる一括指定プロパティについてのより詳しい情報を得るための良いリソースです。

+ +

自分の CSS の練習でこれらの前述) 使用してみて、それがどのように動作するかをよりよく理解するようにしてください。また、様々な値を使って実験してみてください。

+ +
+

警告: CSS の一括指定を使用する際に、省略した値がどのようにリセットされるかはあまり目立たない側面です。 CSS 一括指定で指定されていない値は初期値に戻ります。これは、 CSS 一括指定で省略された値は、以前に設定された値を上書きしてしまう可能性があることを意味します。

+
+ +

コメント

+ +

どんなコーディング作業でもそうですが、 CSS と一緒にコメントを書くのがベストプラクティスです。これは、後で修正や強化のために戻ってきたときに、コードがどのように動作するかを思い出すのに役立ちます。また、他の人がコードを理解するのにも役立ちます。

+ +

CSS のコメントは /* で始まり */ で終わります。以下の例では、コメントはコードのそれぞれの区間のの先頭をマークしています。これは、コードベースが大きくなるにつれて、コードベースを移動するのに役立ちます。このようなコメントの付け方をすると、コードエディターでコメントを検索することで、コードの区間を効率的に見つけることができます。

+ +
/* 基本的な要素のスタイル付けを扱う */
+/* -------------------------------------------------------------------------------------------- */
+body {
+  font: 1em/150% Helvetica, Arial, sans-serif;
+  padding: 1em;
+  margin: 0 auto;
+  max-width: 33em;
+}
+
+@media (min-width: 70em) {
+  /* 大きな画面やウィンドウで読みやすいように、グローバルフォントの大きさを
+     大きくします。 */
+  body {
+    font-size: 130%;
+  }
+}
+
+h1 {font-size: 1.5em;}
+
+/* DOM で入れ子になっている特定の要素を処理します。 */
+/* -------------------------------------------------------------------------------------------- */
+div p, #id:first-line {
+  background-color: red;
+  border-radius: 3px;
+}
+
+div p {
+  margin: 0;
+  padding: 1em;
+}
+
+div p + p {
+  padding-top: 0;
+}
+ +

コードを「コメントアウト」すると、試験的にコードの区間を一時的に無効にするのにも便利です。以下の例では、 .special の規則はコードを「コメントアウト」することで無効化されています。

+ +
/*.special {
+  color: red;
+}*/
+
+p {
+  color: blue;
+}
+ +

CSS にコメントを追加してみましょう。

+ +

ホワイトスペース

+ +

ホワイトスペースとは、半角スペース、タブ、改行を意味します。ブラウザーが HTML のホワイトスペースを無視するように、ブラウザーは CSS の中のホワイトスペースを無視します。ホワイトスペースの価値は、読みやすさを向上させるためにあります。

+ +

下の例では、それぞれの宣言 (と規則の先頭/末尾) が個別の行で行われています。これは間違いなく、CSS を書くのに良い方法です。これにより、CSS の保守や理解が容易になります。

+ +
body {
+  font: 1em/150% Helvetica, Arial, sans-serif;
+  padding: 1em;
+  margin: 0 auto;
+  max-width: 33em;
+}
+
+@media (min-width: 70em) {
+  body {
+    font-size: 130%;
+  }
+}
+
+h1 {
+  font-size: 1.5em;
+}
+
+div p,
+#id:first-line {
+  background-color: red;
+  border-radius: 3px;
+}
+
+div p {
+  margin: 0;
+  padding: 1em;
+}
+
+div p + p {
+  padding-top: 0;
+}
+
+ +

次の例は、同等の CSS をより圧縮したものです。2つの例は同じように動作しますが、下の例の方が読みにくいでしょう。

+ +
body {font: 1em/150% Helvetica, Arial, sans-serif; padding: 1em; margin: 0 auto; max-width: 33em;}
+@media (min-width: 70em) { body {font-size: 130%;} }
+
+h1 {font-size: 1.5em;}
+
+div p, #id:first-line {background-color: red; border-radius: 3px;}
+div p {margin: 0; padding: 1em;}
+div p + p {padding-top: 0;}
+
+ +

自分のプロジェクトでは、個人的な好みに応じてコードを書式化します。チームプロジェクトでは、チームやプロジェクトに独自のスタイルガイドがあるかもしれません。

+ +
。 +

重要: CSS 宣言ではホワイトスペースが値を区切っていますが、プロパティ名にホワイトスペースが含まれることはありません。

+
+ +

例えば、以下の宣言は正しい CSS です。

+ + + +
margin: 0 auto;
+padding-left: 10px;
+ +

次の例は誤ったCSSです:

+ +
margin: 0auto;
+padding- left: 10px;
+ +

0auto という書き方をブラウザは正しい値と解釈してくれません。なぜなら、margin プロパティの値 0、および auto はふたつの別々の値だからです。padding-もまた、ブラウザが認識できる正しいプロパティ名ではありません。

+ +

CSSのプロパティに対する複数の値どうしを区別するためには、最低でも1個以上の空白をあいだにおく必要があります。また、プロパティの名称や値のひとつひとつは、その一部分だけを切り離したりせず続けて書かなければなりません。

+ +

自分のCSSのなかで空白をさまざまに入れてみて、どうすればCSSが正しく機能して、どうすれば機能しなくなるかたしかめてみましょう。

+ +

次のステップ

+ +

ブラウザがHTMLやCSSを解釈してウェブページに作り替えていくながれを多少なりとも知っておくことは開発の役にたちます。そこで、次の記事 「CSS はどう働くか?」  では、ブラウザがWebページを生成する過程についてみていきましょう。

+ +

{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}

+ +

このモジュール内

+ +
    +
  1. CSS とは何か?
  2. +
  3. CSS 入門
  4. +
  5. CSS の全体像
  6. +
  7. CSS はどう働くか?
  8. +
  9. 新しい知識を使う
  10. +
diff --git a/files/ja/learn/css/first_steps/how_css_works/index.html b/files/ja/learn/css/first_steps/how_css_works/index.html new file mode 100644 index 0000000000..6044a3c29a --- /dev/null +++ b/files/ja/learn/css/first_steps/how_css_works/index.html @@ -0,0 +1,164 @@ +--- +title: CSS はどう働くか? +slug: Learn/CSS/First_steps/How_CSS_works +tags: + - Beginner + - CSS + - DOM + - Learn +translation_of: Learn/CSS/First_steps/How_CSS_works +--- +

{{LearnSidebar}}
+ {{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}

+ +

CSS の基本と目的、簡単なスタイルシートの書き方を学んできました。このレッスンでは、ブラウザーが CSS と HTML を実際にウェブページとして表示していくさまを見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、 基本的なソフトウェアがインストールされていることファイルの操作方法についての基本的な知識、HTML の基本 (HTML 概論を学習のこと)。
目的: +

ブラウザーが CSS と HTML を解析する方法、およびブラウザーが解釈できない CSS に遭遇したときに何が起こるかを理解する。

+
+ +

CSS は実際にはどう機能するのか?

+ +

ブラウザーがドキュメントを表示するとき、ブラウザーはそのコンテンツをスタイル情報と結合する必要があります。以下にリストしたいくつかの段階でドキュメントが処理されます。これはブラウザーがウェブページを読み込むときに起こることを単純化したものであり、各ブラウザーで処理は異なるものの、おおよそ何が起こるかを示しています。

+ +
    +
  1. ブラウザーが HTML をロードします(ネットワークから受信するなど)。
  2. +
  3. {{Glossary("HTML")}} が {{Glossary("DOM")}} (Document Object Model) に変換されます。DOM はコンピューターのメモリー内のドキュメントです。次のセクションで詳述します。
  4. +
  5. その後ブラウザーは埋め込まれた画像やビデオなどの HTML ドキュメントにリンクされているリソースと CSS を取得します。JavaScript はもう少し後に処理されるため、ここでは簡略化のため説明しません。
  6. +
  7. ブラウザーは取得した CSS を解析し、要素、クラス、ID などセレクタの種類ごとに分類します。見つけたセレクターに基づいて、DOM のどのノードにどのルールを適用するかを決定し、スタイルを適用します(この中間ステップはレンダーツリーと呼ばれます)。
  8. +
  9. レンダーツリーは、ルール適用後の構造にレイアウトされます。
  10. +
  11. ページが画面に表示されます(この段階はペイントと呼ばれます)。
  12. +
+ +

簡単に図に表すと次のとおりです。

+ +

+ +

DOM について

+ +

DOM にはツリーのような構造があります。マークアップの各要素、属性、およびテキストは、ツリー構造の {{Glossary("Node/DOM","DOM ノード")}} になります。ノードは他の DOM ノードとの関係によって定義されます。要素は子ノードの親であり、子ノードには兄弟があります。

+ +

DOM は CSS とドキュメントのコンテンツが出会う場所であるため、DOM を理解すると CSS の設計、デバッグ、および保守に役立ちます。ブラウザーの開発者ツールによって、どのルールが適用されるかを確認するために、アイテムを選択することで DOM にナビゲートされます。

+ +

DOM の実際

+ +

長く退屈な説明ではなく、例を用いて実際の HTML が DOM に変換される様子を見てみましょう。

+ +

以下のような HTML があります。

+ +
<p>
+  Let's use:
+  <span>Cascading</span>
+  <span>Style</span>
+  <span>Sheets</span>
+</p>
+
+ +

この場合 DOM では <p> 要素が親ノードです。子には、テキストノードと 3 つの <span> 要素をノードとして持ちます。一方で SPAN ノードは親でもあり、テキストノードを子に持ちます。

+ +
P
+├─ "Let's use:"
+├─ SPAN
+|  └─ "Cascading"
+├─ SPAN
+|  └─ "Style"
+└─ SPAN
+   └─ "Sheets"
+
+ +

ブラウザーは上述の HTML をこのように解釈し、DOM ツリーを以下のようにレンダリングし出力します。

+ +

{{EmbedLiveSample('A_real_DOM_representation', '100%', 55)}}

+ + + +

DOM への CSS 適用

+ +

ドキュメントに CSS を追加して、スタイルを設定したとします。先ほどと同じ以下の HTML を使います。

+ +
<p>
+  Let's use:
+  <span>Cascading</span>
+  <span>Style</span>
+  <span>Sheets</span>
+</p>
+ +

CSS は以下のものを適用します。

+ +
span {
+  border: 1px solid black;
+  background-color: lime;
+}
+ +

ブラウザーは HTML 解析によって DOM を作成したのちに、CSS を解析します。CSS には唯一 span セレクターしかないため、ブラウザーは CSS を非常に迅速にソートできます。
+ 3 つ の 
<span> にそのルールを適用し、最終的な視覚的表現を画面にペイントします。

+ +

結果、次のとおり出力されます。

+ +

{{EmbedLiveSample('Applying_CSS_to_the_DOM', '100%', 55)}}

+ +

次のモジュールの CSS のデバッグ ではブラウザーの開発者ツールを使用した CSS のデバッグと、ブラウザーが CSS を解釈する方法について詳しく学習します。

+ +

ブラウザーが解釈できない CSS に遭遇したらどうなるのか?

+ +

以前のレッスンでは、ブラウザーがすべての新しい CSS を実装するわけではないことを述べました。また多くの人が最新バージョンのブラウザーを使用しているわけでもありません。CSS は常に開発されており、ブラウザーがまだ認識できないような CSS セレクターや宣言に遭遇するとどうなるか疑問に思われるかもしれません。
+
+ その答えは何もせず、CSS の次の部分に移動するということです。

+ +

ブラウザーがルールを解析しているときに、理解できないプロパティまたは値に遭遇した場合、ブラウザーはそれを無視して次の宣言に進みます。こういうことは、プロパティまたは値のスペルが間違っている場合や、プロパティまたは値が新しすぎてブラウザーがまだサポートしていない場合に起こりえます。

+ +

同様に、ブラウザーが理解できないセレクターを検出した場合もそのルール全体を無視し、次のルールに進みます。

+ +

次の例では、色にイギリス英語のスペルを使用しているため、プロパティが正しくありません(訳注: color を誤って colour としてしまっている)。よって段落は青くなっていません。ただし、他の CSS はすべて適用されています。無効な行のみが無視されます。

+ +
+
<p> I want this text to be large, bold and blue.</p>
+ +
p {
+  font-weight: bold;
+  colour: blue; /* colorプロパティのスペルが正しくありません */
+  font-size: 200%;
+}
+
+ +

{{EmbedLiveSample('Skipping_example', '100%', 200)}}

+ +

この動作は非常に有用です。ブラウザが新しい CSS を理解しないとしてもエラーは発生しないということを理解した上で、新しい CSS を拡張機能として使用できるということを意味します。ブラウザーは新しい機能を取得するかしないかのどちらかになります。カスケードが機能する方法と、同じ特定性を持つ2つのルールがある場合、ブラウザはスタイルシートの中で出会った最後の CSS を使うという事実と相まって、新しい CSS をサポートしていないブラウザにも代替案を提供することができます。

+ +

とりわけ新しいゆえに必ずしもサポートされているというわけではない、という値を使用する場合に有用です。例えば、一部の古いブラウザーは calc() をサポートしていません。ボックスに対して予防的にピクセル単位の幅を指定しておき、その後 calc() で 100% - 50px の幅を指定した場合、古いブラウザーは前者(ピクセル指定)を使用し、理解できない calc() を無視します。かたや新しいブラウザーはピクセル指定を理解はできるものの、あとに記述された calc() の方を採用します

+ +
.box {
+  width: 500px;
+  width: calc(100% - 50px);
+}
+ +

以降のレッスンで、さまざまなブラウザーをサポートするための多くの方法を検討していきます。

+ +

最後に

+ +

このモジュールはほぼ完了です。ただしもうひとつだけやっておいてほしいことがあります。次の記事の新しい知識を使うにて実際のスタイリングをとおして CSS の腕試しをおこないます。

+ +

{{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}

+ +

このモジュール内

+ +
    +
  1. CSS とは何か?
  2. +
  3. CSS 入門
  4. +
  5. CSS の構造化
  6. +
  7. CSS はどう働くか?
  8. +
  9. 新しい知識を使う
  10. +
diff --git a/files/ja/learn/css/first_steps/index.html b/files/ja/learn/css/first_steps/index.html new file mode 100644 index 0000000000..3a7a08cb48 --- /dev/null +++ b/files/ja/learn/css/first_steps/index.html @@ -0,0 +1,53 @@ +--- +title: CSS の第一歩 +slug: Learn/CSS/First_steps +tags: + - Beginner + - CSS + - Landing + - Learn + - Module + - first steps +translation_of: Learn/CSS/First_steps +--- +
{{LearnSidebar}}
+ +

CSS (Cascading Style Sheets) はウェブページをスタイリングしたりレイアウトしたりするのに使われます — 例えば、文字、色、大きさを変えたり、コンテンツに余白を設けたり、複数列に分けたり、あるいはアニメーションを加えたりなど様々な装飾機能があります。このモジュールでは CSS を習得するために、どう働くかの基本とともに、構文のありかたと HTML にスタイリングを加えることを簡単な始め方を提供します。

+ +

前提条件

+ +

このモジュールを始める前に、次の状態になっておくべきです。

+ +
    +
  1. コンピューターの使い方と (ウェブを見たりコンテンツを消費したりといった)ウェブの受動的な使い方に関する基本的な知識に慣れ親しんでいること。
  2. +
  3. 基本的なソフトウェアのインストールで説明されている基本的な作業環境と、ファイルの扱い方で説明されているファイルの作り方や管理の仕方について理解していること。
  4. +
  5. HTML 入門で説明されている HTML についての基礎知識に慣れ親しんでいること。
  6. +
+ +
+

: 自分自身でファイルを作れない環境 (タブレットやその他の端末) で作業する場合、(ほとんどの) コードサンプルは JSBinGlitch といったオンラインコーディングプログラムで試すことが可能です。

+
+ +

ガイド

+ +

このモジュールには、CSS についてすべての基本的なことがらと、いくつかのスキルをテストできる次の記事が含まれています。

+ +
+
CSS とは何か?
+
{{Glossary("CSS")}} (Cascading Style Sheets; カスケーティングスタイルシート) は見栄えのよいウェブページを作ることができますが、背後ではどのように動いているのでしょうか?この記事では CSS について、簡単なコードの例とこの言語の主要な項目を説明します。
+
CSS 入門
+
この記事では、簡単な HTML コードに CSS を適用させ、その過程でこの言語についての実用的なことを学びます。
+
CSS の全体像
+
CSS の概要と使用方法の基本について理解できたので、今度は言語自体の構造をもう少し詳しく見てみましょう。ここで説明した概念の多くはすでに目にしています。あとに出てくる概念がわかりにくい場合は、ここに戻って見直してしてください。
+
CSS はどう働くか?
+
CSS の基本とその目的、そして簡単なスタイルシートの書き方を学びました。このレッスンでは CSS と HTML がブラウザーにどう働いてウェブページにするかを見ていきます。
+
新しい知識を使う
+
過去数回のレッスンで学んだことから、CSS で単純なテキスト文書をフォーマットし、独自のスタイルを追加できることがわかります。この記事ではそれを行う機会を提供します。
+
+ +

関連情報

+ +
+
Intermediate Web Literacy 1: Intro to CSS
+
本記事で説明した CSS 入門 スキルを確認およびテストするのにちょうどいい Mozilla 基礎コース。セレクター、属性、値などを使った HTML 要素のスタイリングを学べます。
+
diff --git a/files/ja/learn/css/first_steps/using_your_new_knowledge/index.html b/files/ja/learn/css/first_steps/using_your_new_knowledge/index.html new file mode 100644 index 0000000000..d404a70bbf --- /dev/null +++ b/files/ja/learn/css/first_steps/using_your_new_knowledge/index.html @@ -0,0 +1,100 @@ +--- +title: 新しい知識を使う +slug: Learn/CSS/First_steps/Using_your_new_knowledge +tags: + - Beginner + - CSS + - Learn + - Playground +translation_of: Learn/CSS/First_steps/Using_your_new_knowledge +--- +

{{LearnSidebar}}{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}

+ +

先のいくつかのレッスンで、あなたは CSS を使ってシンプルなテキストドキュメントにスタイルを追加してフォーマットする方法を学びました。ここでは、それを実際に行ってみましょう。

+ + + + + + + + + + + + +
前提条件:基礎コンピューターリテラシー、基本的なソフトウェアのインストールファイル操作の基礎知識 HTML の基礎 (HTML の入門で学ぶ)、CSS の基礎(このモジュールの残り)
目的:いくつかの CSS を試し、知識レベルを確認します
+ +

さあ始めよう

+ +

下の Live エディタで試すこともできますし、我々の Github リポジトリからサンプルファイルをダウンロードして試してみることもできます。ここで使うサンプルはシンプルな一ページの HTML で、頭にはとりあえずシンプルな CSS が埋め込まれています。もしローカルで動かすとき HTML と CSS が一緒になっているのが嫌だったら別々のファイルに分割しても構いません。あるいは、CodePenjsFiddleGlitch といったオンラインエディタを使うこともできます。

+ +
+

注記: もし途中で詰まったら、私達に気兼ねなく相談してください!詳しくはこの記事の一番下にある「アセスメントとさらなるヘルプ」の部分を見てください。

+
+ +

CSS を少し試してみよう

+ +

下のサンプルは、CSS でスタイルされたプロフィールページの例です。ここで使われているプロパティは次の通りです。これらについてはそれぞれリンクから MDN の記事に飛べますので、プロパティの詳細な説明についてはそちらをご参照ください。

+ + + +

下のプロフィールページでは、いろんなセレクタを使ったり、h1要素や h2要素などの装飾要素を使ったりしただけでなく、職業を表す部分ではクラスを定義してデザインを設定しました。

+ +

プロパティの値をいろいろに変えて見た目がどう変わるか試してみましょう。

+ +
    +
  1. 見出し 1 の文字色をピンクに変えてみましょう。色の指定には hotpink を使うとよいでしょう。
  2. +
  3. 見出し 1 の下に太さ 10px の点線をつけてみましょう。そしてその色を purple にしてみましょう。
  4. +
  5. 見出し 2 の書体をイタリックに変えてみましょう。
  6. +
  7. 連絡先情報の部分で使われている ul 要素の {{cssxref("background-color")}} を #eeeeee にして、{{cssxref("border")}} を太さ 5px の紫の線に変えてみましょう。また、{{cssxref("padding")}} を指定してコンテンツと連絡先情報の部分にスペースが空くように設定しましょう。
  8. +
  9. リンクの部分にマウスが乗ったとき、リンクが green に変わるように設定しましょう。
  10. +
+ +

完成したら次の画像のようになるはずです。

+ +

+ +

それから、このページに書かれていない属性をみてみましょう。MDN の CSS リファレンス には冒険が待っています!

+ +

ここには間違った回答はないことを覚えていてください — ここではいろいろ試して楽しみながら学びましょう。

+ +

{{EmbedGHLiveSample("css-examples/learn/getting-started/biog.html", '100%', 1600)}} 

+ +

アセスメントとさらなるヘルプ

+ +

作ったものを見てほしいときや、作業に詰まってしまって質問をしたいとき:

+ +
    +
  1. あなたが作ったものを CodePenjsFiddleGlitch などのコード共有サービスに公開してください。
  2. +
  3. 添削の依頼あるいは訊きたいことを MDN Discourse forum Learning category に投稿してください。ここに投稿するときには次のことを忘れないようにしてください。 +
      +
    • タイトルは何についての質問か分かるように、「Assessment wanted for CSS First Steps」のようにしてください。
    • +
    • 添削や質問を依頼したいコードへのリンクを貼ってください。ソースコードを示してもらわないとこちらもどうサポートしたらよいかがわからないからです。
    • +
    • どの課題に取り組んでいるのか分かるように課題へのリンクを貼ってください。そうしていただけるとあなたがどこで躓いているのか知ることができます。
    • +
    +
  4. +
+ +

次のステップ

+ +

最初のモジュールを修了しました。おめでとうございます。あなたはもう CSS の基本的な部分は理解できたはずです。そして、スタイルシートの挙動が分かるようになったはずです。次のモジュール、CSS ブロック構築ではいくつかの重要な部分を深く見ていきましょう。

+ +

{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}

+ +

このモジュール内

+ +
    +
  1. What is CSS?
  2. +
  3. Getting started with CSS
  4. +
  5. How CSS is structured
  6. +
  7. How CSS works
  8. +
  9. Using your new knowledge
  10. +
diff --git a/files/ja/learn/css/first_steps/what_is_css/index.html b/files/ja/learn/css/first_steps/what_is_css/index.html new file mode 100644 index 0000000000..0d7d6f3cd3 --- /dev/null +++ b/files/ja/learn/css/first_steps/what_is_css/index.html @@ -0,0 +1,129 @@ +--- +title: CSSとは何か? +slug: Learn/CSS/First_steps/What_is_CSS +tags: + - Beginner + - CSS + - Introduction to CSS + - Learn + - Modules + - Specifications + - Syntax +translation_of: Learn/CSS/First_steps/What_is_CSS +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}
+ +

{{Glossary("CSS")}} (Cascading Style Sheets;カスケーティングスタイルシート) は見栄えのよいページを作ることができますが、内部ではどう働くのでしょうか?この記事では簡単な構文の例とともに CSS とは何かについて説明し、この言語の重要な用語についても触れます。

+ + + + + + + + + + + + +
前提条件: +

基本的なコンピューターリテラシー、 基本的なソフトウェアがインストールされていることファイルの操作方法についての基本的な知識、HTML の基本 (HTML概論を学習のこと)。

+
目的:CSS とは何かを学ぶ。
+ +

HTML 概論 では HTML について触れ、文書をどのようにマークアップするかを学びました。この文書はウェブブラウザーで読むことができます。見出しは普通のテキストより大きく見え、段落はあたらしい行に分けられ、それらの間には空白が入ります。リンクはほかのテキストと区別するために色付きで下線が引かれています。これらはブラウザーによるデフォルトのスタイリングです。ページの作者がスタイリングしていなくても読みやすくなるようにブラウザーが HTML に適用するとても基本的なスタイルです。

+ +

The default styles used by a browser

+ +

しかし、ウェブサイトみんながこのような見た目では退屈でしょう。CSS をつかうとブラウザー内で HTML 要素をどう見せるかはっきりと制御できるようになり、マークアップを好きなように表現できます。

+ +

CSS の目的

+ +

前述のように、CSS は文書を(スタイルやレイアウトを)どのように表現するか指定する言語です。

+ +

文書 は普通、マークアップ言語をつかって構造化されたテキストファイルです。{{Glossary("HTML")}} がもっとも一般的な マークアップ言語ですが、{{Glossary("SVG")}} や {{Glossary("XML")}}も出会うことがあります。

+ +

文書を 表現する とは、それを使いやすいフォームに変換することを意味します。{{Glossary("Mozilla Firefox","Firefox")}}, {{Glossary("Google Chrome","Chrome")}}, あるいは {{Glossary("Microsoft Edge","Edge")}} といった{{Glossary("ブラウザー","ブラウザー")}} はコンピューター画面やプロジェクター、あるいはプリンタで印刷される文書が視覚的に表現されるよう設計されています。

+ +
+

: ブラウザーは時に{{Glossary("User agent","user agent ユーザーエージェント")}} と呼ばれますが、基本的に人に似せたコンピュータープログラムを意味します。CSS について語る時、ブラウザーは代表的なユーザーエージェントですが、それだけではありません。HTML と CSS 文書を印刷できる PDF に変換するようなユーザーエージェントもあります。

+
+ +

CSS は、例えば見出しやリンクの フォントサイズの変更といったごく基本的なテキストのスタイリングでもつかえます。例えば、一列のテキストをレイアウトしてメインコンテンツ領域と関連情報のためのサイドバーに分けるといった、レイアウト作成に使うこともできます。アニメーションのような効果も使えます。それぞれの例はこの段落のリンクをご覧ください。

+ +

CSS の構文

+ +

CSS はルールベースの言語です。ウェブページ上の特定の要素かグループに適用するスタイリングのルールを定義します。例えば、「ページ上の <h1> 要素の文字を大きく、赤くしたい」といったようにです。

+ +

これを実現するコードはとても簡単な CSS ルールです:

+ +
h1 {
+    color: red;
+    font-size: 5em;
+}
+ +

ルールは {{Glossary("CSS Selector", "セレクタ")}} から始まります。ここにはこれからスタイリングしようとする HTML 要素を選びます。この例では {{htmlelement("h1")}} を選んでいます。

+ +

つぎに波カッコ { } を書き、この中にプロパティプロパティ値 のペアで作られた 宣言 を 1 つ以上置きます。それぞれのペアは選んだ要素のプロパティとそれに与えたいプロパティ値を特定します。

+ +

コロン : の前にプロパティを書き、コロンの後にプロパティ値を書きます。CSS {{Glossary("property/CSS","プロパティ")}} は特定されたプロパティによって異なる許容値を持ちます。例えば、color プロパティは様々な color 値を持っています。font-size プロパティもあります。このプロパティは値として様々な size 単位 を持っています。

+ +

CSS スタイルシートはたくさんのルールを含みます。

+ +
h1 {
+    color: red;
+    font-size: 5em;
+}
+
+p {
+    color: black;
+}
+ +

ほかにどんな値があるか調べる必要があることに気づくでしょう。 MDN のプロパティのページをつかえば、忘れた時やほかにどんな値が使えるか知りたいときにすばやく調べられます。

+ +
+

: CSS リファレンスにすべての CSS プロパティのリストがあります。CSS の機能についてもっとたくさんの情報を見つける必要があるときには、検索エンジンで "mdn css-feature-name" と調べることに慣れても良いでしょう。 例えば、"mdn color" や "mdn font-size" を試してみてください!

+
+ +

CSS モジュール

+ +

CSSを使ってスタイリングできることがたくさんあるので、CSS は モジュール にまとめられています。 MDN を探せばこれらモジュールのリファレンスが見つかるでしょうし、多くのページは特定のモジュールで編集されていることがわかります。例えば、その目的やプロパティと機能の違いを見つけるために背景と境界 モジュールを見ることができます。(後述で) CSS 技術を定義する仕様へのリンクもあります。

+ +

CSS がどのように作られているか、ここではあまり心配する必要はありませんが、もし例えば、特定のプロパティが似たものの中で見つかる可能性があることを知っていれば、情報は見つけやすくなります。

+ +

たとえば、背景と境界モジュールに戻ってみましょう。background-color と border-color プロパティがこのモジュール内で定義されているのは理にかなっていると思うかもしれませんし、実際そうなっています。

+ +

CSS の仕様

+ +

(HTML, CSS, JavaScript といった) ウェブの標準技術はすべて、仕様 (または単に 「スペック」)とよばれる文書で定義されており、({{glossary("W3C")}}, {{glossary("WHATWG")}}, {{glossary("ECMA")}}, or {{glossary("Khronos")}} といった) 標準化組織によって発行され、技術がどう働くか定義しています。

+ +

CSS は W3C 内の CSS Working Group と呼ばれるグループにより開発されました。このグループは、CSS に関心のあるブラウザーベンダーやその他の企業の代表者で構成されています。またメンバー組織とつながらず、独立した声として行動する invited experts もいます。 

+ +

新しい CSS の機能は、CSS ワーキンググループにより開発され、仕様化されています。 特定のブラウザーが実験的に機能を実装させることもありますし、ウェブデザイナーやデベロッパーが要望することもありますし、ワーキンググループ自体が要件を固めることもあります。CSS は絶えず開発されており、新しい機能が利用可能になります。しかし重要なのは、古いウェブサイトが決して壊れてしまわないように、全員が努力していることです。2000年に作られたウェブサイトは限られた CSS 機能しか使えませんが、最新のブラウザーでも見えるようになっているべきなのです。

+ +

CSS の初心者としては、CSS仕様が圧倒的であることに気付くでしょう。これらは、ウェブ開発者が CSS を理解するために読むのではなく、エンジニアがユーザーエージェント機能のサポートを実装するために使用するのを想定しています。経験豊富な開発者の多くは、MDN ドキュメントや他のチュートリアルを参照します。ただし、それらが存在することを知り、使っている CSS やブラウザーによるサポート(以下を参照)、および仕様間の関係を理解することは価値があります。

+ +

ブラウザーサポート

+ +

一度CSS が指定されると、1 つ以上のブラウザーが CSS を実装している場合にのみウェブページの開発に役立ちます。これはコードが CSS ファイルの命令を画面に表示できるように記述されることを意味します。これは CSS がどう働くかのレッスンで見ることになるでしょう。すべてのブラウザーで同時にある機能が実装されることは通常はありませんし、それゆえ通常、一部のブラウザーでは CSS の一部を使用でき、他のブラウザーでは使用できないというギャップがあります。こういったわけで、どういった機能が実装されているか確認できることは有益です。MDN のそれぞれのページでは、関心のあるプロパティの状態が確認できるので、ウェブサイト上でそれが使えるか見極めることができます。

+ +

以下は CSS の font-family プロパティについての互換データです。

+ +

{{Compat("css.properties.font-family")}}

+ +

次のステップ

+ +

CSS とは何かについていくらか理解したと思いますので、CSS 入門 に進みましょう。ここでは自分で CSS を書き始められます。

+ +

{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}

+ +

このモジュール内

+ +
    +
  1. What is CSS?
  2. +
  3. Getting started with CSS
  4. +
  5. How CSS is structured
  6. +
  7. How CSS works
  8. +
  9. Using your new knowledge
  10. +
diff --git a/files/ja/learn/css/howto/create_fancy_boxes/index.html b/files/ja/learn/css/howto/create_fancy_boxes/index.html new file mode 100644 index 0000000000..74d0b3b379 --- /dev/null +++ b/files/ja/learn/css/howto/create_fancy_boxes/index.html @@ -0,0 +1,305 @@ +--- +title: 装飾的なボックスの作成 +slug: Learn/CSS/Howto/create_fancy_boxes +tags: + - Beginner + - CSS + - CodingScripting + - Learn +translation_of: Learn/CSS/Howto/create_fancy_boxes +--- +

CSS ボックスは、CSS で装飾されたウェブページの構成要素です。 見栄えを良くすることは、楽しさとやりがいの両方です。 デザインのアイデアを実用的なコードに変えることがすべてだからです。 面倒な制約と CSS の使用における狂気の自由のために、それは挑戦的です。 いくつかの装飾的なボックスをやりましょう。

+ +

実用的な側面に取り掛かる前に、CSS ボックスモデルに慣れていることを確認してください。 いくつかの CSS レイアウトの基本を熟知していることも賢明ですが、前提条件ではありません。

+ +

技術面では、装飾的なボックスの作成は、CSS の境界線と背景のプロパティの習得と、それらを特定のボックスに適用する方法についてのものです。 しかし、テクニックを超えてそれはまたあなたの創造性を解き放つことに関するすべてです。 それは1日で終わらないでしょうし、何人かのウェブ開発者はそれを楽しんで一生を過ごします。

+ +

私たちは多くの例を見ようとしていますが、可能な限り最も単純な HTML の部分、次の単純な要素に取り組むつもりです。

+ +
<div class="fancy">Hi! I want to be fancy.</div>
+ +

はい、それは HTML のごく一部ですが、その要素について何を調整できるのでしょうか? 次のすべてです。

+ + + +

とても広い遊び場があります。 楽しく始めましょう。

+ +

ボックスモデルの調整

+ +

ボックスモデルだけで、単純な境界線の追加、四角形の作成など、基本的なことを行うことができます。 負の padding や負の margin、あるいはその両方を使用して、border-radius をボックスの実際のサイズよりも大きくすることによって、プロパティを限界にプッシュすると、面白くなり始めます。

+ +

円を作る

+ + + +

これはとてもシンプルでとても楽しいものです。 {{cssxref("border-radius")}} プロパティは、ボックスに適用される丸い角を作成するように作られていますが、半径のサイズがボックスの実際の幅と等しいかそれより大きい場合はどうなるでしょうか?

+ +
.fancy {
+  /* 円の中では、中央揃えのテキストは見栄えがよくなります。 */
+  text-align : center;
+
+  /* テキストが境界線に触れないようにしましょう。
+     テキストはまだ四角形の中を流れているので、
+     そのようにするときれいに見えて、
+     それが「本当の」円であるという感覚を与えます。 */
+  padding : 2em;
+
+  /* 境界線は円に見えるようになります。
+     背景は境界線の半径で切り取られるので、
+     背景を使用することもできます。 */
+  border : 0.5em solid black;
+
+  /* 正方形であることを確認しましょう。
+     正方形でない場合は、円ではなく楕円です。 ;) */
+  width  : 5em;
+  height : 5em;
+
+  /* そして正方形を円に変えましょう。 */
+  border-radius: 100%;
+}
+ +

はい、円ができます。

+ +

{{ EmbedLiveSample('Making_circles', '100%', '170') }}

+ +

Backgrounds

+ +

装飾的なボックスについて話すとき、それを扱うためのコアとなるプロパティは background-* プロパティです。 背景をいじり始めると、CSS ボックスはあなたが満たすための空白のキャンバスになります。

+ +

いくつかの実用的な例に進む前に、背景について知っておくべきことが2つあるので、少し後退しましょう。

+ + + + + +

さて、背景を楽しんでみましょう。

+ +
.fancy {
+  padding : 1em;
+  width: 100%;
+  height: 200px;
+  box-sizing: border-box;
+
+  /* 背景の積み重ねの一番下を、
+     霧のかかった灰色の単色にしましょう。 */
+  background-color: #E4E4D9;
+
+  /* カラーストリップエフェクトを作成するために、
+     線形グラデーションを重ね合わせます。
+     お気づきのとおり、
+     色のグラデーションは画像と見なされ、
+     そのように操作することができます。 */
+  background-image: linear-gradient(175deg, rgba(0,0,0,0) 95%, #8da389 95%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 95%, #8da389 95%),
+                    linear-gradient(175deg, rgba(0,0,0,0) 90%, #b4b07f 90%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 92%, #b4b07f 92%),
+                    linear-gradient(175deg, rgba(0,0,0,0) 85%, #c5a68e 85%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 89%, #c5a68e 89%),
+                    linear-gradient(175deg, rgba(0,0,0,0) 80%, #ba9499 80%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 86%, #ba9499 86%),
+                    linear-gradient(175deg, rgba(0,0,0,0) 75%, #9f8fa4 75%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 83%, #9f8fa4 83%),
+                    linear-gradient(175deg, rgba(0,0,0,0) 70%, #74a6ae 70%),
+                    linear-gradient( 85deg, rgba(0,0,0,0) 80%, #74a6ae 80%);
+}
+ +

{{ EmbedLiveSample('Backgrounds', '100%', '200') }}

+ +
+

グラデーションは、非常に独創的な方法で使用できます。 あなたがクレイジーな例を見たいのなら、Lea Verou の CSS パターン(英語)を見てください。 こういったグラデーションの使用はかなり高くつきますが、パフォーマンス的に優れていることを忘れないでください。 グラデーションについてもっと知りたい場合は、気軽に専用記事にアクセスしてください。

+
+ +

疑似要素

+ +

1つのボックスを装飾するときに、自分自身が制限されていることに気付き、さらに素晴らしい装飾を作成するためにもっとボックスを追加したいと思うかもしれません。 ほとんどの場合、これは独自の装飾の目的で HTML 要素を追加することによって DOM を汚染することにつながります。 たとえそれが必要であっても、それはやや悪い習慣と考えられています。 そのような落とし穴を回避するための1つの解決策は、CSS 疑似要素を使用することです。

+ +

+ + + +

ボックスを雲に変える例を見てみましょう。

+ +
.fancy {
+  text-align: center;
+
+  /* 以前に円を作るために使用したのと同じトリックです。 */
+  box-sizing: border-box;
+  width     : 150px;
+  height    : 150px;
+  padding   : 80px 1em 0 1em;
+
+  /* 雲の「耳」のための場所を空けます。 */
+  margin    : 0 100px;
+
+  position: relative;
+
+  background-color: #A4C9CF;
+
+  /* それで、私たちは雲の底を平らにしたいので、
+     実際に一周していません。
+     この例を気軽に微調整して、
+     底が平らでない雲にしてください。 ;) */
+  border-radius: 100% 100% 0 0;
+}
+
+/* これらは、::before 疑似要素と ::after 疑似要素
+   の両方に適用される共通のスタイルです。 */
+.fancy::before,
+.fancy::after {
+  /* これは、たとえ値が空の文字列であっても、
+     疑似要素の表示を許可するために必要です。 */
+  content: '';
+
+  /* 擬似要素をボックスの左右に配置しますが、
+     常に一番下に配置します。 */
+  position: absolute;
+  bottom  : 0;
+
+  /* これにより、疑似要素は、何が起こっても
+     ボックスのコンテンツの下になります。 */
+  z-index : -1;
+
+  background-color: #A4C9CF;
+  border-radius: 100%;
+}
+
+.fancy::before {
+  /* これは雲の左耳の大きさです。 */
+  width  : 125px;
+  height : 125px;
+
+  /* 少し左に動かします。 */
+  left    : -80px;
+
+  /* 雲の底が平らに保たれるようにするには、
+     左耳の正方形の右下角を作る必要があります。 */
+  border-bottom-right-radius: 0;
+}
+
+.fancy::after {
+  /* これは右耳の雲の大きさです。 */
+  width  : 100px;
+  height : 100px;
+
+  /* 少し右に動かします。 */
+  right   : -60px;
+
+  /* 雲の底が平らに保たれるようにするには、
+     右耳の正方形の左下角を作る必要があります。 */
+  border-bottom-left-radius: 0;
+}
+ +

{{ EmbedLiveSample('A_cloud', '100%', '160') }}

+ +

ブロッククォート

+ +

擬似要素を使用するより実用的な例は、HTML の {{HTMLElement('blockquote')}} 要素のための素晴らしいフォーマットを構築することです。 それでは、少し異なる HTML スニペットを使った例を見てみましょう(デザインのローカライゼーションもどのように処理するかを見る機会を提供してくれます)。

+ +
<blockquote>People who think they know everything are a great annoyance to those of us who do. <i>Isaac Asimov</i></blockquote>
+<blockquote lang="fr">L'intelligence, c'est comme les parachutes, quand on n'en a pas, on s'écrase. <i>Pierre Desproges</i></blockquote>
+ +

それで、これが装飾です。

+ +
blockquote {
+  min-height: 5em;
+  padding   : 1em 4em;
+  font      : 1em/150% sans-serif;
+  position  : relative;
+  background-color: lightgoldenrodyellow;
+}
+
+blockquote::before,
+blockquote::after {
+  position: absolute;
+  height  : 3rem;
+  font    : 6rem/100% Georgia, "Times New Roman", Times, serif;
+}
+
+blockquote::before {
+  content: '“';
+  top    : 0.3rem;
+  left   : 0.9rem;
+}
+
+blockquote::after {
+  content: '”';
+  bottom : 0.3rem;
+  right  : 0.8rem;
+}
+
+blockquote:lang(fr)::before {
+  content: '«';
+  top    : -1.5rem;
+  left   : 0.5rem;
+}
+
+blockquote:lang(fr)::after {
+  content: '»';
+  bottom : 2.6rem;
+  right  : 0.5rem
+}
+
+blockquote i {
+  display   : block;
+  font-size : 0.8em;
+  margin-top: 1rem;
+  text-style: italic;
+  text-align: right;
+}
+ +

{{ EmbedLiveSample('Blockquote', '100%', '300') }}

+ +

すべて一緒に、他

+ +

ですから、これらすべてを混ぜ合わせると素晴らしいエフェクトを生み出すことができます。 ある時点で、そのようなボックス装飾を達成することは、CSS プロパティの設計と技術的使用の両方において、創造性の問題です。 このようにすることで、この例のようにボックスを生き生きとさせることができる錯視を作成することが可能です。

+ + + +

部分的なドロップシャドウ・エフェクトを作りましょう。 {{cssxref("box-shadow")}} プロパティを使用すると、内部光と平らなドロップシャドウ・エフェクトを作成できますが、ちょっとした追加作業で、擬似要素と {{cssxref("transform")}} プロパティを使用してより自然なジオメトリを作成することが可能になります。

+ +
.fancy {
+  position: relative;
+  background-color: #FFC;
+  padding: 2rem;
+  text-align: center;
+  max-width: 200px;
+}
+
+.fancy::before {
+  content: "";
+
+  position : absolute;
+  z-index  : -1;
+  bottom   : 15px;
+  right    : 5px;
+  width    : 50%;
+  top      : 80%;
+  max-width: 200px;
+
+  box-shadow: 0px 13px 10px black;
+  transform: rotate(4deg);
+}
+ +

{{ EmbedLiveSample('All_together_and_more', '100%', '100') }}

+ +

次は何ですか?

+ +

多くの点で、装飾的なボックスを作ることは主に背景の中に色と画像を追加することなので、色と画像の管理を掘り下げる価値があるかもしれません。 また、装飾的なボックス自体がより大きなレイアウトの一部でなければ、それ自体はまったく役に立ちません。 まだチェックしていないのであれば、レイアウトの基本を見てください。

+ +
 
diff --git a/files/ja/learn/css/howto/generated_content/index.html b/files/ja/learn/css/howto/generated_content/index.html new file mode 100644 index 0000000000..add931f8d9 --- /dev/null +++ b/files/ja/learn/css/howto/generated_content/index.html @@ -0,0 +1,88 @@ +--- +title: Content +slug: Learn/CSS/Howto/Generated_content +tags: + - CSS + - 'CSS:Getting_Started' + - Getting_Started +translation_of: Learn/CSS/Howto/Generated_content +--- +
{{CSSTutorialTOC}}
+ +
{{previousPage("/ja/docs/CSS/Getting_Started/Color", "Color")}} これは CSS Getting Startedチュートリアルの第9章です; 文書が表示されたとき CSS を使ってコンテンツを追加するいくつかの方法について述べます。スタイルシートを編集して、テキストや画像を追加できます。
+ +

コンテンツについて

+ +

CSS の重要な利点のひとつが、文書の体裁(style)と内容(コンテンツ)を切り離しやすくすることです。それでも、あるコンテンツを文書ではなく、スタイルシートに含めたほうがわかりやすいことがあります。

+ +

スタイルシートではテキストや画像から成るコンテンツを記述できます。コンテンツと文書の構造に強い関連があるとき、コンテンツをスタイルシート内に記述します。

+ +
+
さらに詳しく
+ +

スタイルシートでコンテンツを記述すると、面倒な話が生まれる可能性があります。例えば、文書の複数の言語版をスタイルシートを共有して作ることがあるかもしれません。これは、スタイルシートの部分的に訳すときには、その一部を別々のファイルにわけるとともに、適切な言語版の文書とリンクされるよう編集しなければならない、ということです。

+ +

この混乱は、コンテンツがすべての言語や文化で利用できる記号や画像で記述されていれば発生しません。

+ +

スタイルシート内に記述されたコンテンツは、DOMの一部にはなりません。

+
+ +

テキストコンテンツ

+ +

CSS で要素の前または後ろにテキストコンテンツを挿入できます。このためには、ルールを作って {{cssxref(":before")}} または {{cssxref(":after")}} をそのセレクタに追加します。宣言部分には、specify the {{cssxref("content")}} プロパティと、その値としてテキストコンテンツを記述します。

+ +
+
例 +

HTML

+ +
A text where I need to <span class="ref">something</span>
+ +

CSS

+ +
.ref::before {
+  font-weight: bold;
+  color: navy;
+  content: "Reference ";
+}
+ +

結果

+ +

{{ EmbedLiveSample('Text_content', 600, 30) }}h3

+
+
+ +
+
さらに詳しく
+ +

スタイルシートの文字セットのデフォルトは UTF-8 ですが、リンク、スタイルシート自身の内部、もしくはその他の方法で指定できます。CSS Specification の 4.4 CSS style sheet representation をご覧ください。

+ +

文字を、バックスペースによるエスケープ機構を使って記述することもできます。例えば、\265B はチェスの黒クイーンの記号 ♛ です。詳しくは、Referring to characters not represented in a character encoding と CSS Specification の Characters and case をご覧ください。

+
+ +

画像コンテンツ

+ +

要素の前や後ろに画像を追加するには、{{cssxref("content")}} プロパティの値として画像ファイルの URL を記述します。

+ +
+
+ +

このルールは glossary を持つすべてのリンクの後ろに、空白文字とアイコンを追加します:

+ +

HTML

+ +
<a href="developer.mozilla.org" class="glossary">developer.mozilla.org</a>
+ +

CSS

+ +
a.glossary::after {
+   content: " " url("https://mdn.mozillademos.org/files/16322/glossary-icon.gif");
+}
+ +

結果

+ +

{{ EmbedLiveSample('Image_content', 600, 40) }}

+
+ +

次は何?

+ +
{{nextPage("/ja/docs/CSS/Getting_Started/Lists", "Lists")}} スタイルシートでコンテンツを追加し、リストの項目に印をつけることがよくあります。次の章では リスト要素のスタイル記述 について述べます。
diff --git a/files/ja/learn/css/howto/index.html b/files/ja/learn/css/howto/index.html new file mode 100644 index 0000000000..2ecbac3e25 --- /dev/null +++ b/files/ja/learn/css/howto/index.html @@ -0,0 +1,90 @@ +--- +title: CSS を使ってよくある問題を解決する +slug: Learn/CSS/Howto +tags: + - Beginner + - CSS + - Learn +translation_of: Learn/CSS/Howto +--- +
{{LearnSidebar}}
+ +

以下のリンクは CSS で解決できるよくある問題の解決法です。

+ +

よくある使用例

+ +
+ + + +
+ +

まれで高度なテクニック

+ +

CSS ではとても高度なデザインテクニックも利用できます。これらの記事は、複雑な使用例を解き明かします。

+ +

一般的

+ + + +

高度なエフェクト

+ + + +

レイアウト

+ + + +

関連情報

+ +

CSS FAQ — さまざまなトピック: デバッグからセレクタの使い方まで。

diff --git a/files/ja/learn/css/index.html b/files/ja/learn/css/index.html new file mode 100644 index 0000000000..58897d3289 --- /dev/null +++ b/files/ja/learn/css/index.html @@ -0,0 +1,68 @@ +--- +title: CSS +slug: Learn/CSS +tags: + - Beginner + - CSS + - CodingScripting + - Debugging + - Landing + - NeedsContent + - Topic + - length + - specificity +translation_of: Learn/CSS +--- +
{{LearnSidebar}}
+ +

Cascading Style Sheets — {{glossary("CSS")}} — は{{glossary("HTML")}} を学んだら、まず次に勉強すべき技術です。 HTML はコンテンツの構造と{{glossary("Semantics","意味論")}}を定義するのに使用されるのに対し、CSS はそのコンテンツにスタイルを与えたりレイアウトを決めるために使われます。 例えばフォント、色、サイズ、余白を変更したり、コンテンツを複数の列に分割して段組を作成したり、アニメーションやその他の装飾機能を追加するのに CSS は利用できます。

+ +

学習の道のり

+ +

CSS に挑戦する前に HTML の基礎を学習しておくべきです。 まず、HTML 入門 に取り組むことを推奨します — その後に、以下のことについて学んでください:

+ + + +

HTML の基本のキが理解できたら、HTML と CSS の 2 つのトピックスを行き来しながらふたつを同時に学習することを推奨します。 なぜなら、CSS を理解すると HTMLを勉強するのが更に興味深くまたもっと楽しくなり、またHTML を知ることなくして CSS を学習することはできないからです。

+ +

またこのトピックを開始する前に、コンピューターの基本的な使い方と、ウェブを受動的に使用すること (つまり、ウェブコンテンツを消費すること) に慣れている必要があります。 基本的なソフトウェアをインストールする に詳しく書かれているような基本的な環境を持っており、 ファイルの扱い に詳しく書かれているようなファイルの作成・管理方法を理解している必要があります — なおこれらについては初心者向けの記事集であるウェブ入門のなかに入っています。

+ +

このトピックに取り組む前に ウェブ入門 を読むと良いでしょう。 ただ、このウェブ入門のなかのCSS basicsの記事で紹介されていることの多くは、CSS 入門 でもカバーされているのでこれは必須ではありません。

+ +

モジュール

+ +

このトピックは、以下のモジュールで構成されており、取り組むべき順に記載していますので、上から始めていくとよいでしょう。

+ +
+
+
CSS の第一歩
+
CSS (Cascading Style Sheets) はウェブページをスタイリングしたりレイアウトしたりするのに使われます — 例えば、文字、色、大きさを変えたり、コンテンツに余白を設けたり、複数列に分けたり、 あるいはアニメーションを加えたりなど様々な装飾機能があります。このモジュールでは、CSSのはたらきからCSSの構文、そしてそれを使ってHTMLをどうデザインしていくのかといったCSSをマスターするための入門編を丁寧に解説します。
+
+
CSS の構成要素
+
+

このモジュールは CSS の第一歩から派生しています。CSSにちょっと慣れて簡単な経験も積んだところで、それをもう少し掘り下げてみましょう。カスケードと継承・セレクター・単位・サイズ設定・背景と枠線についてやデバックの方法などを見ていきます。

+ +

ここでの目的は、テキストの装飾や CSS レイアウトなどのより具体的な分野に進む前に、適切な CSS を書くための手法を知り、すべての重要な理論を理解できるようになることです。

+
+
テキストの装飾
+
CSS 言語の基本を習得したら、次に取り組むべき CSS のトピックはテキストの装飾です — これは、CSS で最もよく使うことの一つです。 ここでは、フォント、太字、イタリック、ラインと文字の間隔、ドロップシャドウやその他のテキスト機能の設定を含む、テキストの装飾の基本を見ていきます。あなたのページにカスタムフォントを適用し、リストとリンクを装飾するところを見ることによって、このモジュールを締めくくります。
+
CSS レイアウト
+
ここまでで既に CSS の基本、テキストの装飾方法、コンテンツを格納するボックスの装飾方法と操作方法を見てきました。 今度は、ビューポートを基準にしてボックスを適切な場所に配置する方法、および互いの配置方法を検討します。 必要な前提知識はカバーされているので、奥深いCSSレイアウトの世界に飛び込むことができます。さまざまな display の設定、flexboxのようなモダンなやり方から、CSS grid、positioning、そしてまだまだ知っておきたいと思うかもしれないレガシーなテクニックまでを概観していきます。
+
+ +

CSS でよくある問題を解決するには

+ +

CSS を使ってよくある問題を解決する には、ウェブページを作成する際よく発生する問題を CSS を使って解決する方法へのリンクがまとめられています。

+ +

最初から、HTML 要素とその背景に色を付けたり、要素の大きさや形や位置を変えたり、要素のボーダー(境界線)を定義することがもっとも多かったでしょう。 しかし CSS の基本をしっかり理解していれば、できないことはそれほど多くありません。 CSS学習のなかで最も嬉しいことの1つは、一度基礎を理解してしまうと、やり方が実はまだよくわかっていなくても、できることとできないことに対して大抵はかなり良い感触が得られることです!

+ +

関連情報

+ +
+
MDN での CSS
+
MDN での CSS ドキュメントの主な出発点です。 CSS 言語のすべての機能を詳しく説明したリファレンスドキュメントがあります。 プロパティがとりうるすべての値を知りたいですか? ここは良い場所です。
+
diff --git a/files/ja/learn/css/introduction_to_css/fundamental_css_comprehension/index.html b/files/ja/learn/css/introduction_to_css/fundamental_css_comprehension/index.html new file mode 100644 index 0000000000..c8012c9a8a --- /dev/null +++ b/files/ja/learn/css/introduction_to_css/fundamental_css_comprehension/index.html @@ -0,0 +1,133 @@ +--- +title: 基本的な CSS の理解 +slug: Learn/CSS/Introduction_to_CSS/Fundamental_CSS_comprehension +tags: + - Assessment + - Beginner + - CSS + - CodingScripting + - Syntax + - コメント + - スタイル + - セレクタ + - ボックスモデル + - ルール +translation_of: Learn/CSS/Building_blocks/Fundamental_CSS_comprehension +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/CSS/Introduction_to_CSS/Debugging_CSS", "Learn/CSS/Introduction_to_CSS")}}
+ +

このモジュールで多くをカバーしてきました、最後まで来て気分が良いでしょう! 次に進む前の最後のステップは、モジュールの評価を試みることです。これには、最終的なデザイン (名刺/ゲーマーカード/ソーシャルメディアプロファイル) を作成するために完了しなければならないいくつかの関連演習が含まれます。

+ + + + + + + + + + + + +
前提条件:この評価を実施する前に、すでにこのモジュールのすべての記事を通して作業しているはずです。
目的:基本的な CSS 理論、構文、およびメカニズムの理解をテストする。
+ +

出発点

+ +

この評価を開始するには、次のことが必要です。

+ + + +
+

メモ: 代わりとして、JSBinThimble のようなサイトを使って評価することもできます。HTML を貼り付けて CSS をこれらのオンラインエディタのいずれかに入力し、この URL を使用して <img> 要素を画像ファイルに向けることができます。使用しているオンラインエディタに別の CSS パネルがない場合は、それをドキュメントの先頭の <style> 要素に自由に配置してください。

+
+ +

プロジェクト概要

+ +

生の HTML と画像が提供されているので、これにスタイルを設定するのに必要な CSS を気の利いた小さなオンライン名刺に書く必要があります。これは、おそらくゲーマーカードやソーシャルメディアのプロファイルを兼ねるでしょう。次のセクションではする必要があることについて説明します。

+ +

基本設定:

+ + + +

CSS リソースファイルで提供されているセレクタとルールセットに注意してください。

+ + + +

書く必要がある新しいルールセット:

+ + + +
+

メモ: 2番目のルールセットは <html> 要素に font-size: 10px; を設定することに注意してください。これは <html> のすべての子孫について、em はデフォルトの16 px ではなく10 px になることを意味します (これはもちろん、階層内で問題の子孫と <html> の間に別の font-size が設定されている先祖がいない場合に限ります。これは必要な値に影響を与える可能性がありますが、この単純な例では問題にはなりません)。

+
+ +

その他の考慮事項

+ + + +

ヒントとコツ

+ + + +

+ +

次のスクリーンショットは、完成したデザインの外観の例を示しています。

+ +

A view of the finished business card, show a reader header and footer, and a darker center panel containing the main details and image.

+ +

評価

+ +

組織的な研修の一部としてこの評価に従っているなら、あなたは採点のためにあなたの教師/メンターに作業結果を提出できるはずです。もし自己学習しているのであれば、この練習問題についてのディスカッションスレッド、または Mozilla IRC#mdn IRC チャンネルで尋ねることで、非常に簡単に採点ガイドを入手できます。最初にエクササイズをしてみてください — 不正をすることによって得られるものは何もありません!

+ +

{{PreviousMenu("Learn/CSS/Introduction_to_CSS/Debugging_CSS", "Learn/CSS/Introduction_to_CSS")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/css/styling_boxes/a_cool_looking_box/index.html b/files/ja/learn/css/styling_boxes/a_cool_looking_box/index.html new file mode 100644 index 0000000000..32aa19ca2e --- /dev/null +++ b/files/ja/learn/css/styling_boxes/a_cool_looking_box/index.html @@ -0,0 +1,100 @@ +--- +title: かっこいいボックス +slug: Learn/CSS/Styling_boxes/A_cool_looking_box +tags: + - Assessment + - Beginner + - CSS + - Learn + - backgrounds + - borders + - box + - box model + - effects +translation_of: Learn/CSS/Building_blocks/A_cool_looking_box +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper", "Learn/CSS/Styling_boxes")}}
+ +

この評価では、人目を引くボックスを作成しようとすることで、かっこいいボックスを作成する方法をさらに習得できます。

+ + + + + + + + + + + + +
前提知識:この評価を試みる前に、このモジュールのすべての記事を読んでおくべきです。
学習目標:CSS ボックスモデルと、境界線や背景などの他のボックス関連機能の理解をテストすること。
+ +

出発点

+ +

この評価を開始するには、次のことが必要です。

+ + + +
+

: あるいは、JSBinThimble などのサイトを使って評価することもできます。 HTML を貼り付けて CSS をこれらのオンラインエディタのいずれかに入力できます。 使用しているオンラインエディタに別の CSS パネルがない場合は、それをドキュメントの先頭の <style>  要素に自由に配置してください。

+
+ +

プロジェクトの概要

+ +

あなたの仕事は、かっこよくて装飾的な箱を作り、私たちが CSS で持つことができる楽しみを探ることです。

+ +

一般的なタスク

+ + + +

ボックスの装飾

+ +

提供された {{htmlelement("p")}} に次のように装飾を設定してください。

+ + + +

+ +

次のスクリーンショットは、完成したデザインがどのように見えるかの例を示しています。

+ +

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合は、採点のために作品を教師や指導者に渡すことができるはずです。 自己学習をしている場合は、この演習についてのディスカッションスレッドMozilla IRC#mdn IRC チャンネルで尋ねることで、かなり簡単に採点の手引きを得ることができます。 まず演習を試してみてください — 不正行為によって得られるものは何もありません!

+ +

{{PreviousMenu("Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper", "Learn/CSS/Styling_boxes")}}

+ +

 

+ +

このモジュール内の文書

+ + + +

 

diff --git a/files/ja/learn/css/styling_boxes/creating_fancy_letterheaded_paper/index.html b/files/ja/learn/css/styling_boxes/creating_fancy_letterheaded_paper/index.html new file mode 100644 index 0000000000..6d793d69ff --- /dev/null +++ b/files/ja/learn/css/styling_boxes/creating_fancy_letterheaded_paper/index.html @@ -0,0 +1,108 @@ +--- +title: 装飾的なレターヘッド付きの便箋の作成 +slug: Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper +tags: + - Assessment + - Background + - Beginner + - Boxes + - CSS + - CodingScripting + - border + - box + - letter + - letterhead + - letterheaded + - paper +translation_of: Learn/CSS/Building_blocks/Creating_fancy_letterheaded_paper +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/Styling_boxes/Advanced_box_effects", "Learn/CSS/Styling_boxes/A_cool_looking_box", "Learn/CSS/Styling_boxes")}}
+ +

好印象を与えたいのなら、素敵なレターヘッドの便箋に手紙を書くのはとても良い考えです。この評価では、そのような見た目のオンラインテンプレートの作成に挑戦します。

+ + + + + + + + + + + + +
前提知識:この評価を試みる前に、このモジュールのすべての記事を読んでおくべきです。
学習目標:CSS ボックスモデルの理解と、背景の実装などの他のボックス関連機能をテストします。
+ +

出発点

+ +

この評価を開始するには、次のことが必要です。

+ + + +
+

: あるいは、JSBinThimble などのサイトを使って評価することもできます。 HTML を貼り付けて CSS をこれらのオンラインエディタのいずれかに入力できます。 使用しているオンラインエディタに別の CSS パネルがない場合は、それをドキュメントの先頭の <style>  要素に自由に配置してください。

+
+ +

プロジェクトの概要

+ +

レターヘッド付きの便箋のテンプレートを作成するのに必要なファイルを与えられました。 ファイルをまとめるだけでいいのです。 目的を達するには、次のことが必要です。

+ +

メインの手紙

+ + + + + + + +

ヒントとコツ

+ + + +

+ +

次のスクリーンショットは、完成したデザインがどのように見えるかの例を示しています。

+ +

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合は、採点のために作品を教師や指導者に渡すことができるはずです。 自己学習をしている場合は、この演習についてのディスカッションスレッドMozilla IRC#mdn IRC チャンネルで尋ねることで、かなり簡単に採点の手引きを得ることができます。 まず演習を試してみてください — 不正行為によって得られるものは何もありません!

+ +

{{PreviousMenuNext("Learn/CSS/Styling_boxes/Advanced_box_effects", "Learn/CSS/Styling_boxes/A_cool_looking_box", "Learn/CSS/Styling_boxes")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/styling_text/fundamentals/index.html b/files/ja/learn/css/styling_text/fundamentals/index.html new file mode 100644 index 0000000000..163dd945ee --- /dev/null +++ b/files/ja/learn/css/styling_text/fundamentals/index.html @@ -0,0 +1,748 @@ +--- +title: 基本的なテキストとフォントの装飾 +slug: Learn/CSS/Styling_text/Fundamentals +tags: + - Article + - Beginner + - CSS + - Guide + - Style + - Text + - alignment + - family + - font + - shorthand + - spacing + - weight +translation_of: Learn/CSS/Styling_text/Fundamentals +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text")}}
+ +

この記事では、{{glossary("CSS")}} によるテキストの装飾の習得に向けて旅を始めましょう。 ここでは、フォントの太さ、ファミリーそしてスタイルの設定、フォントの一括指定、テキストの配置とその他のエフェクト、ラインと文字の間隔などを含んだ、テキストやフォントの装飾の基本について詳しく説明します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー、HTML の基本(HTML 入門を学ぶ)、CSS の基本(CSS 入門を学ぶ)。
学習目標:ウェブページのテキストを装飾するために必要な基本的なプロパティとテクニックを学ぶこと。
+ +

CSS においてテキストの装飾には何が関係していますか?

+ +

HTML と CSS を使った作業ですでに経験したように、要素内のテキストは要素のコンテンツボックス内にレイアウトされます。 コンテンツ領域の左上(RTL 言語のコンテンツの場合は右上)から始まり、ラインの終りに向かって流れます。 終りに達すると、次のラインに進み、続けてすべてのコンテンツがボックスに配置されるまで次のラインに進みます。 テキストコンテンツは事実上一連のインライン要素のようにふるまい、互いに隣接するラインに配置され、ラインの終りに達するまで、または、{{htmlelement("br")}} 要素を使用して手動で改行を強制しない限り改行を作成しません。

+ +
+

: 上の段落で混乱していると感じても問題ありません — 先に進む前に、ボックスモデル理論を磨くために、ボックスモデルの記事に戻って見直してください。

+
+ +

テキストを装飾するために使用される CSS プロパティは、一般的に次の2つのカテゴリに分類されます。 この記事では、これらのプロパティを個別に説明します。

+ + + +
+

: 要素内のテキストはすべて単一の実体として影響を受けることに注意してください。 テキストの一部分を({{htmlelement("span")}} や {{htmlelement("strong")}} など)適切な要素でラップしたり、{{cssxref("::first-letter")}}(要素のテキストの最初の文字を選択)、{{cssxref("::first-line")}}(要素のテキストの最初の行を選択)、{{cssxref("::selection")}}(現在カーソルで強調表示されているテキストを選択)のようなテキスト固有の疑似要素を使用しない限り、テキストの一部分を選択して装飾することはできません。

+
+ +

フォント

+ +

フォントを装飾するためのプロパティを見るためにまっすぐに進みましょう。 この例では、次のような同じ HTML サンプルにいくつかの異なる CSS プロパティを適用します。

+ +
<h1>Tommy the cat</h1>
+
+<p>I remember as if it were a meal ago...</p>
+
+<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter
+ may have nestled its way into his mighty throat. Many a fat alley rat
+had met its demise while staring point blank down the cavernous barrel of
+ this awesome prowling machine. Truly a wonder of nature this urban
+predator — Tommy the cat had many a story to tell. But it was a rare
+occasion such as this that he did.</p>
+ +

完成した例は Github にあります(ソースコードも参照してください)。

+ +

+ +

{{cssxref("color")}} プロパティは、選択された要素の前景のコンテンツの色を設定します(通常はテキストですが、{{cssxref("text-decoration")}} プロパティを使用してテキストに下線や上線を配置するなど、他のいくつかの要素を含めることもできます)。

+ +

color は次のように任意の CSS カラー単位を受け入れることができます。

+ +
p {
+  color: red;
+}
+ +

これにより、次のように段落は標準のブラウザーのデフォルトの黒ではなく赤になります。

+ + + +

{{ EmbedLiveSample('Color', '100%', 220) }}

+ +

フォントファミリー

+ +

テキストに別のフォントを設定するには、{{cssxref("font-family")}} プロパティを使用します — これにより、選択した要素に適用するブラウザーのフォント(またはフォントのリスト)を指定できます。 ウェブサイトにアクセスしているマシンで利用可能な場合にのみ、ブラウザーはフォントを適用します。 そうでない場合は、ブラウザーの{{anch("Default fonts", "デフォルトフォント")}}を使用するだけです。 簡単な例はこんな感じです。

+ +
p {
+  font-family: arial;
+}
+ +

これにより、ページ上のすべての段落に、どのコンピュータでも見られる arial フォントが採用されます。

+ +

ウェブセーフフォント

+ +

フォントの入手可能性と言えば、すべてのシステムで一般的に利用でき、したがってそれほど心配することなく使用できるフォントの数は限られています。これらはいわゆるウェブセーフフォント (web safe fonts) です。

+ +

ほとんどの場合、ウェブ開発者は、テキストコンテンツの表示に使用されるフォントをより具体的に制御したいと考えています。 問題は、ウェブページを見るために使用されているコンピュータでどのフォントが利用可能かを知る方法を見つけることです。 あらゆる場合にこれを知る方法はありませんが、ウェブセーフフォントは最も使用されているオペレーティングシステム(Windows、Mac、最も一般的な Linux ディストリビューション、Android、および iOS)のほぼすべての実例で使用可能です。

+ +

実際のウェブセーフフォントのリストは、オペレーティングシステムが進化するにつれて変わりますが、少なくとも現時点では次のフォントをウェブセーフと見なすことをお勧めします(それらの多くは90年代後半から2000年代初頭にかけての Microsoft の Core fonts for the Web の先鞭のおかげで普及しました)。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名前総称タイプ
Arialsans-serifArial に好ましい代替として Helvetica を追加するのがベストプラクティスと考えられることがよくあります。 それらのフォントフェースはほぼ同じですが、Arial の方が広く入手可能であっても Helvetica はより良い形状をしていると考えられます。
Courier Newmonospaceいくつかの OS は Courier と呼ばれる Courier New フォントの代替(おそらく古い)バージョンを持っています。 Courier New と一緒に両方を使用することを推奨します。
Georgiaserif
Times New Romanserifいくつかの OS は Times と呼ばれる Times New Roman フォントの代替(おそらく古い)バージョンを持っています。 Times New Roman と一緒に両方を使用することを推奨します。
Trebuchet MSsans-serifこのフォントの使用には注意が必要です — モバイル OS では広く使用されていません。
Verdanasans-serif
+ +
+

: さまざまなリソースの中で、cssfontstack.com ウェブサイトには、Windows および macOS オペレーティングシステムで利用可能なウェブセーフフォントのリストがあり、使用しても安全と見なせるものについて判断を下すことができます。

+
+ +
+

: ウェブページとともにカスタムフォントをダウンロードして、フォントの使用方法を自由にカスタマイズできる方法があります。 それは、ウェブフォント(web fonts)です。 これはもう少し複雑で、このモジュールの後の別の記事でこれを議論するでしょう。

+
+ +

デフォルトフォント

+ +

CSS はフォントの5つの総称名を定義しています: セリフ(serif)、サンセリフ(sans-serif)、等幅(monospace)、筆記体(cursive)、ファンタジー(fantasy)。 これらは非常に一般的なものであり、それらの総称名を使用するときに使用される正確なフォントは各ブラウザー次第であり、それらが実行されているオペレーティングシステムごとに異なります。 これは、ブラウザーが最低限適切なフォントを提供するように最善を尽くそうとする場合の最悪のシナリオを表します。 serifsans-serif、および monospace はかなり予測可能であり、妥当なものを提供するはずです。 その一方で、cursivefantasy はそれほど予測できないので、慎重に使用してテストすることをお勧めします。

+ +

5つの名前は次のように定義されています。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
用語定義
serifセリフ(いくつかの書体のストロークの終わりに見られる隆起やその他の細部)を持つフォントです。My big red elephant
sans-serifセリフがないフォントです。My big red elephant
monospaceすべての文字が同じ幅を持つフォントで、通常はコードリストで使用されます。My big red elephant
cursive流れるような連続したストロークで、手書き文字を模倣することを目的としたフォントです。My big red elephant
fantasy装飾的なフォントです。My big red elephant
+ +

フォントスタック

+ +

ウェブページで使用したいフォントの可用性を保証することはできないため(ウェブフォントでさえ何らかの理由で失敗する可能性もあります)、ブラウザーに複数のフォントから選択できるようにフォントスタック(font stack)を指定できます。 これは単に、次のようにカンマで区切られた複数のフォント名からなる font-family の値です。

+ +
p {
+  font-family: "Trebuchet MS", Verdana, sans-serif;
+}
+ +

そのような場合、ブラウザーはリストの先頭から始めて、そのフォントがマシンで利用可能かどうかを確認します。 そうであれば、そのフォントを選択した要素に適用します。 そうでない場合は、次のフォントに移動します。

+ +

リストされているフォントがどれも利用できない場合、ブラウザーが少なくともほぼ適切なものを提供できるように、スタックの最後に適切な総称フォント名を指定することをお勧めします。 この点を強調するために、他のオプションが利用できない場合、段落にはブラウザーのデフォルトの serif フォントを使用します — これは通常は Times New Roman です — これは sans-serif フォントには不適切です!

+ +
+

: Trebuchet MS のように、複数の単語を含むフォント名は "Trebuchet MS" のように引用符で囲む必要があります。

+
+ +

font-family の例

+ +

前の例に追加して、次のように段落に sans-serif フォントを付けます。

+ +
p {
+  color: red;
+  font-family: Helvetica, Arial, sans-serif;
+}
+ +

これにより、次のような結果が得られます。

+ + + +

{{ EmbedLiveSample('A_font-family_example', '100%', 220) }}

+ +

フォントサイズ

+ +

前のモジュールの CSS の値と単位の記事で、長さとサイズの単位を確認しました。 フォントサイズ({{cssxref("font-size")}} プロパティで設定)は、これらの単位のほとんど(およびパーセントなどの他の単位)で測定された値を取ることができますが、テキストのサイズを設定するために使用する最も一般的な単位は次のとおりです。

+ + + +

要素の font-size は、その要素の親要素から継承されます。 これはすべてドキュメント全体のルート要素 — {{htmlelement("html")}} — で始まり、font-size はブラウザー間で標準で 16px に設定されています。 ルート要素内の段落(またはブラウザーによって設定された異なるサイズを持たない他の要素)は、最終サイズが 16px になります。 他の要素はデフォルトサイズが異なる場合があります。 例えば、{{htmlelement("h1")}} 要素のサイズはデフォルトで 2em に設定されているため、最終的なサイズは 32px になります。

+ +

入れ子になった要素のフォントサイズを変更し始めると、物事はより複雑になります。 例えば、ページに {{htmlelement("article")}} 要素があり、その font-size1.5em(これは計算すると 24px の最終的なサイズになります)に設定し、次に <article> 要素内の段落に 20px で計算したフォントサイズを使用するようにしたい場合に、あなたは何 em の値を使用しますか?

+ +
<!-- ドキュメントのベースフォントサイズは 16px です -->
+<article> <!-- ここのフォントサイズが 1.5em の場合 -->
+  <p>My paragraph</p> <!-- 20px のフォントサイズにするにはどう計算しますか? -->
+</article>
+ +

その em 値を 20 / 24 、つまり 0.83333333em に設定する必要があります。 数学は複雑になる可能性があるため、装飾方法には注意が必要です。 可能な限り rem を使用して、物事を単純にし、可能な限りコンテナ要素のフォントサイズを設定しないようにするのが最善です。

+ +

簡単なサイズ設定の例

+ +

テキストのサイズを変更するときは、通常、ドキュメントのベース font-size10px に設定することをお勧めします。 そうすれば、数学の計算がはるかに簡単になります — その場合、必要な (r)em 値は、16 ではなく、10 で割ったピクセルフォントサイズです。 これで、ドキュメント内のさまざまな種類のテキストのサイズを簡単に変更できます。 スタイルシートの指定された領域にすべての font-size の規則セットをリストすることをお勧めします。 そうすれば、それらは簡単に見つけられます。

+ +

新しい結果はこんな感じです。

+ + + +
html {
+  font-size: 10px;
+}
+
+h1 {
+  font-size: 2.6rem;
+}
+
+p {
+  font-size: 1.4rem;
+  color: red;
+  font-family: Helvetica, Arial, sans-serif;
+}
+ +

{{ EmbedLiveSample('A_simple_sizing_example', '100%', 220) }}

+ +

フォントスタイル、フォントの太さ、テキスト変換、テキスト飾り

+ +

CSS は、テキストの視覚的な太さや強調を変更するために次の4つの共通のプロパティを提供します。

+ + + +

例にこれらのプロパティをいくつか追加してみましょう。

+ +

新しい結果はこんな感じです。

+ + + +
html {
+  font-size: 10px;
+}
+
+h1 {
+  font-size: 2.6rem;
+  text-transform: capitalize;
+}
+
+h1 + p {
+  font-weight: bold;
+}
+
+p {
+  font-size: 1.4rem;
+  color: red;
+  font-family: Helvetica, Arial, sans-serif;
+}
+ +

{{ EmbedLiveSample('Font_style_font_weight_text_transform_and_text_decoration', '100%', 220) }}

+ +

テキストのドロップシャドウ

+ +

{{cssxref("text-shadow")}} プロパティを使ってテキストにドロップシャドウを付けることができます。 次の例に示すように、これは最大4つの値を取ります。

+ +
text-shadow: 4px 4px 5px red;
+ +

4つのプロパティは次のとおりです。

+ +
    +
  1. 元のテキストからの影の水平方向のオフセット — これは、ほとんどの CSS の長さとサイズの単位を取ることができますが、最も一般的には px を使用します。 この値を含める必要があります。
  2. +
  3. 元のテキストからの影の垂直方向のオフセット — 基本的に水平方向のオフセットと同じようにふるまいますが、影を左右に移動するのではなく上下に移動する点が異なります。 この値を含める必要があります。
  4. +
  5. ぼかし半径 — 値が大きいほど、影はより広く分散されます。 この値が含まれていない場合、デフォルトは 0 になり、ぼかしは行われません。 これは、ほとんどの CSS の長さとサイズの単位を取ることができます。
  6. +
  7. 影のベースカラー — 任意の CSS カラー単位を取ります。 含まれていない場合、デフォルトは black です。
  8. +
+ +
+

注: 正のオフセット値は影を右下に移動させますが、-1px -1px のように負のオフセット値を使用して影を左上に移動させることもできます。

+
+ +

複数の影

+ +

複数の影の値をコンマで区切って含めることで、次のように同じテキストに複数の影を付けることができます。

+ +
text-shadow: -1px -1px 1px #aaa,
+             0px 4px 1px rgba(0,0,0,0.5),
+             4px 4px 5px rgba(0,0,0,0.7),
+             0px 0px 7px rgba(0,0,0,0.4);
+ +

これを Tommy the cat の例の {{htmlelement("h1")}} 要素に適用すると、結果は次のようになります。

+ + + +

{{ EmbedLiveSample('Multiple_shadows', '100%', 220) }}

+ +
+

:  Sitepoint の記事 Moonlighting with CSS text-shadow で、text-shadow の使い方のより興味深い例を見ることができます。

+
+ +

テキストのレイアウト

+ +

基本的なフォントのプロパティ以外の方法で、テキストのレイアウトに影響を与えるために使用できるプロパティを見てみましょう。

+ +

テキストの配置

+ +

{{cssxref("text-align")}} プロパティは、テキストを含むコンテンツボックス内でのテキストの配置方法を制御するために使用されます。 利用可能な値は次の通りで、通常のワードプロセッサアプリケーションとほとんど同じように機能します。

+ + + +

例の {{htmlelement("h1")}} に、text-align: center; を適用した場合、次のようになるでしょう。

+ + + +

{{ EmbedLiveSample('Text_alignment', '100%', 220) }}

+ +

ラインの高さ

+ +

{{cssxref("line-height")}} プロパティはテキストの各ラインの高さを設定します — これはほとんどの長さとサイズの単位をとることができますが、乗数として機能し、一般的に最良の選択肢と考えられる単位なしの値をとることもできます — line-height を得るために {{cssxref("font-size")}} が乗算されます。 本文はラインが離れていると、一般的に見栄えがよく、読みやすくなります。 推奨されるラインの高さは約 1.5 〜 2(ダブルスペース)です。 したがって、テキストのラインをフォントの高さの 1.5 倍に設定するには、次のようにします。

+ +
line-height: 1.5;
+ +

この例の {{htmlelement("p")}} 要素にこれを適用すると、次のようになります。

+ + + +

{{ EmbedLiveSample('Line_height', '100%', 250) }}

+ +

文字と単語の間隔設定

+ +

{{cssxref("letter-spacing")}} プロパティと {{cssxref("word-spacing")}} プロパティを使用すると、テキスト内の文字と単語の間隔を設定できます。 これらはあまり使用しませんが、ある外観を得るためや、特に濃いフォントの読みやすさを向上させるために使用することがあります。 それらはほとんどの長さとサイズの単位を取ることができます。

+ +

例として、この例の {{htmlelement("p")}} 要素の最初のラインに次を適用したとします。

+ +
p::first-line {
+  letter-spacing: 2px;
+  word-spacing: 4px;
+}
+ +

次のようになります。

+ + + +

{{ EmbedLiveSample('Letter_and_word_spacing', '100%', 250) }}

+ +

その他の検討に値するプロパティ

+ +

上記のプロパティは、ウェブページ上でテキストを装飾する方法のアイデアを与えますが、使うことができるもっと多くのプロパティがあります。 ここでは最も重要なものだけを取り上げたいと思います。 上記の使い方に慣れてきたら、次のことも調べてください。

+ +

フォントスタイル

+ + + +

テキストのレイアウトスタイル

+ + + +

フォントの一括指定

+ +

多くのフォントプロパティは、一括指定プロパティの {{cssxref("font")}} を介して設定することもできます。 これらは、{{cssxref("font-style")}}、{{cssxref("font-variant")}}、{{cssxref("font-weight")}}、{{cssxref("font-stretch")}}、{{cssxref("font-size")}}、{{cssxref("line-height")}}、{{cssxref("font-family")}} の順に書きます。

+ +

これらすべてのプロパティのうち、font 一括指定プロパティを使用する場合に必要なのは、font-sizefont-family のみです。

+ +

{{cssxref("font-size")}} プロパティと {{cssxref("line-height")}} プロパティの間にスラッシュを入れる必要があります。

+ +

完全な例は次のようになります。

+ +
font: italic normal bold normal 3em/1.5 Helvetica, Arial, sans-serif;
+ +

能動的学習: テキストの装飾で遊ぶ

+ +

この能動的学習セッションでは、具体的な演習はありません。 フォントやテキストのレイアウトのプロパティをいくつか試してみて、作成できるものを確認してください! オフラインの HTML / CSS ファイルを使用してこれを行うか、下記のライブ編集可能な例にコードを入力することができます。

+ +

間違えた場合は、Reset ボタンを使用していつでもリセットできます。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 800) }}

+ +

まとめ

+ +

この記事のテキストで遊んで楽しんでくださいね! 次の記事では、HTML リストの装飾について知っておくべきことをすべて説明します。

+ +

{{NextMenu("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/styling_text/index.html b/files/ja/learn/css/styling_text/index.html new file mode 100644 index 0000000000..6bcfb0a722 --- /dev/null +++ b/files/ja/learn/css/styling_text/index.html @@ -0,0 +1,55 @@ +--- +title: テキストの装飾 +slug: Learn/CSS/Styling_text +tags: + - Beginner + - CSS + - CodingScripting + - Fonts + - Landing + - Links + - Module + - Text + - font + - letter + - line + - lists + - shadow + - web fonts +translation_of: Learn/CSS/Styling_text +--- +
{{LearnSidebar}}
+ +

CSS 言語の基本を習得したら、次に取り組むべき CSS のトピックはテキストの装飾です — これは、CSS で行う最も一般的なことの一つです。 ここでは、フォント、太字、イタリック体、ラインと文字の間隔、ドロップシャドウやその他のテキスト機能の設定を含む、テキストの装飾の基本を見ていきます。あなたのページにカスタムフォントを適用し、リストとリンクを装飾するところを見ることによって、このモジュールを締めくくります。

+ +

前提知識

+ +

このモジュールを始める前に、HTML 入門のモジュールで説明したようにすでに HTML についての基本的な知識があり、CSS 入門で説明したように CSS の基本に慣れている必要があります。

+ +
+

メモ: 自分のファイルを作成できないコンピューター/タブレット/その他の端末で作業している場合、JSBinCodePenThimble のようなオンラインコーディングプログラムで (ほとんどの) サンプルコードを試せます。

+
+ +

ガイド

+ +

このモジュールには以下の記事が含まれていて、HTML のテキストコンテンツの装飾の背後にあるすべての重要事項を説明しています。

+ +
+
基本的なテキストとフォントの装飾
+
この記事では、フォントの太さ、ファミリーとスタイル、フォントの一括指定、テキストの配置とその他のエフェクト、ラインと文字の間隔の設定など、テキストとフォントの装飾のすべての基本について詳しく説明します。
+
リストの装飾
+
リストは他のテキストとほとんど同じようにふるまいますが、知っておくべきリスト固有の CSS プロパティと、考慮すべきベストプラクティスがいくつかあります。この記事はすべてを説明しています。
+
リンクの装飾
+
リンクを装飾するときは、擬似クラスを使用してリンク状態を効果的に装飾する方法と、ナビゲーションメニューやタブなどの一般的なさまざまなインターフェイス機能で使用するためのリンクの装飾方法を理解することが重要です。この記事では、これらすべてのトピックを見ていきます。
+
ウェブフォント
+
ここでは、ウェブフォントを詳しく探ります — これらを使用すると、ウェブページと一緒にカスタムフォントをダウンロードすることを可能にして、より多様でカスタムなテキストの装飾を可能にします。
+
+ +

評価

+ +

以下の評価では、上記のガイドで説明されているテキストの装飾のテクニックについての理解をテストします。

+ +
+
コミュニティスクールのホームページの組版
+
この評価では、コミュニティスクールのホームページのテキストを装飾してもらい、テキストの装飾についての理解をテストします。
+
diff --git a/files/ja/learn/css/styling_text/styling_links/index.html b/files/ja/learn/css/styling_text/styling_links/index.html new file mode 100644 index 0000000000..60588e794f --- /dev/null +++ b/files/ja/learn/css/styling_text/styling_links/index.html @@ -0,0 +1,453 @@ +--- +title: リンクの装飾 +slug: Learn/CSS/Styling_text/Styling_links +tags: + - Article + - Beginner + - CSS + - Focus + - Guide + - Learn + - Links + - Pseudo-class + - hover + - hyperlinks + - menus + - tabs +translation_of: Learn/CSS/Styling_text/Styling_links +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}
+ +

リンクを装飾するときは、擬似クラスを使用してリンク状態を効果的に装飾する方法と、ナビゲーションメニューやタブなどの一般的なさまざまなインターフェイス機能で使用するためのリンクの装飾方法を理解することが重要です。 この記事では、これらすべてのトピックを見ていきます。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー、HTML の基本(HTML 入門を学ぶ)、CSS の基本(CSS 入門を学ぶ)、CSS のテキストとフォントの基礎
学習目標:リンク状態を装飾する方法と、ナビゲーションメニューのような一般的な UI 機能でリンクを効果的に使用する方法を学ぶこと。
+ + + +

ハイパーリンクの作成のベストプラクティスに従って、HTML がリンクをどのように実装するかを調べました。 この記事では、この知識を基にして、リンクの装飾のためのベストプラクティスを示します。

+ + + +

最初に理解するべきことはリンク状態の概念です。リンクが存在できる様々な状態のことで、それらは異なる疑似クラスを使って装飾することができます。

+ + + +

デフォルトの装飾

+ +

次の例は、リンクがデフォルトでどのようにふるまうかを示しています(CSS は、テキストをより見やすくするために、単にテキストを拡大して中央に配置しています)。

+ +
<p><a href="#">A simple link</a></p>
+
+ +
p {
+  font-size: 2rem;
+  text-align: center;
+}
+ +

{{ EmbedLiveSample('Default_styles', '100%', 120) }}

+ +
+

: このページの例にあるリンクはすべて偽のリンクです — #(ハッシュまたはポンド記号)が実際の URL の代わりに配置されています。 これは、実際のリンクが含まれている場合、それらをクリックすると例が壊れる可能性があるためです(エラーが発生したり、ロードしたページから埋め込まれた例に戻ることができません)。 # は現在のページにリンクしているだけです。

+
+ +

デフォルトの装飾を調べていくうちに、次のようないくつかのことに気付くでしょう。

+ + + +

興味深いことに、これらのデフォルトの装飾は、1990年代半ばのブラウザーの初期の頃のものとほぼ同じです。 これは、ユーザーがこのふるまいを知っており、予期するようになったためです — リンクの装飾が異なると、多くの人が混乱してしまうでしょう。 これは、リンクの装飾を設定してはいけないという意味ではなく、予想されるふるまいから大きく外れてはいけないということです。 少なくとも次のことをするべきです。

+ + + +

デフォルトの装飾は、次の CSS プロパティを使用してオフにしたり変更したりできます。

+ + + +
+

: リンクの装飾は上記のプロパティに制限されているわけではありません — 好きなプロパティを自由に使用できます。 夢中になりすぎないようにしてください!

+
+ + + +

デフォルトの状態を少し詳しく見てきたので、典型的なリンクの装飾のセットを見てみましょう。

+ +

まず始めに、空の規則セットを書き出します。

+ +
a {
+
+}
+
+
+a:link {
+
+}
+
+a:visited {
+
+}
+
+a:focus {
+
+}
+
+a:hover {
+
+}
+
+a:active {
+
+}
+ +

リンクのスタイルは互いに重なっているため、この順序は重要です。 例えば、最初の規則の装飾は、それ以降のすべての規則に適用され、リンクがアクティブになっているときは、ホバーもしています。 これらを間違った順序で並べると、物事は適切に機能しません。 順番を覚えておくには、LoVe Fears HAte のようなニーモニックを使用してみてください。

+ +

それでは、これを適切に装飾するための情報を追加しましょう。

+ +
body {
+  width: 300px;
+  margin: 0 auto;
+  font-size: 1.2rem;
+  font-family: sans-serif;
+}
+
+p {
+  line-height: 1.4;
+}
+
+a {
+  outline: none;
+  text-decoration: none;
+  padding: 2px 1px 0;
+}
+
+a:link {
+  color: #265301;
+}
+
+a:visited {
+  color: #437A16;
+}
+
+a:focus {
+  border-bottom: 1px solid;
+  background: #BAE498;
+}
+
+a:hover {
+  border-bottom: 1px solid;
+  background: #CDFEAA;
+}
+
+a:active {
+  background: #265301;
+  color: #CDFEAA;
+}
+ +

CSS を適用するためのサンプル HTML も提供します。

+ +
<p>There are several browsers available, such as <a href="#">Mozilla
+Firefox</a>, <a href="#">Google Chrome</a>, and
+<a href="#">Microsoft Edge</a>.</p>
+ +

2つをまとめると、この結果が得られます。

+ +

{{ EmbedLiveSample('Styling_some_links', '100%', 150) }}

+ +

それでは、ここで何をしたでしょうか? これは確かにデフォルトの装飾とは異なるように見えますが、それでもユーザーに何が起こっているのかを知るための十分な身近な経験を提供します。

+ + + + + +

この能動的学習セッションでは、空の規則のセットにあなた自身の宣言を追加してリンクを本当にかっこよく見せてください。 想像力を駆使して、ワイルドに。 上記の例と同じように、よりかっこよく機能的なものを思いつくことができると確信しています。

+ +

間違えた場合は、Reset ボタンを使用していつでもリセットできます。 本当に立ち往生してしまったら、上に示した例を挿入するために Show solution ボタンを押してください。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 800) }}

+ + + +

一般的なやり方は、リンクがどの種類のコンテンツを指しているかに関するより多くの標識を提供するためにリンクにアイコンを含めることです。 外部リンク(他のサイトにつながるリンク)にアイコンを追加する、本当に簡単な例を見てみましょう。 このようなアイコンは、通常、ボックスから出る小さな矢印のように見えます — この例では、icons8.com からの素晴らしい例を使います。

+ +

欲しい効果が得られる HTML と CSS を見てみましょう。 まず、装飾する簡単な HTML です。

+ +
<p>For more information on the weather, visit our <a href="#">weather page</a>,
+look at <a href="http://#">weather on Wikipedia</a>, or check
+out <a href="http://#">weather on Extreme Science</a>.</p>
+ +

次に、CSS です。

+ +
body {
+  width: 300px;
+  margin: 0 auto;
+  font-family: sans-serif;
+}
+
+p {
+  line-height: 1.4;
+}
+
+a {
+  outline: none;
+  text-decoration: none;
+  padding: 2px 1px 0;
+}
+
+a:link {
+  color: blue;
+}
+
+a:visited {
+  color: purple;
+}
+
+a:focus, a:hover {
+  border-bottom: 1px solid;
+}
+
+a:active {
+  color: red;
+}
+
+a[href*="http"] {
+  background: url('https://mdn.mozillademos.org/files/12982/external-link-52.png') no-repeat 100% 0;
+  background-size: 16px 16px;
+  padding-right: 19px;
+}
+ +

{{ EmbedLiveSample('Including_icons_on_links', '100%', 150) }}

+ +

それでは、ここで何が起こっているのでしょうか? これまで見てきたのと同じ情報なので、CSS の大部分はスキップします。 しかし最後の規則は興味深いです — ここでは前回の記事のリストアイテムのカスタム行頭記号を処理したのと同じ方法で外部リンクにカスタム背景画像を挿入しています — 今回は個々のプロパティの代わりに {{cssxref("background")}} の一括指定を使用します。 挿入したい画像へのパスを設定し、no-repeat を指定してコピーを1つだけ挿入するようにしてから、テキストコンテンツの右側へ 100%、上から 0 ピクセルの位置を指定します。

+ +

また、{{cssxref("background-size")}} を使用して、背景画像を表示するサイズを指定します。 レスポンシブウェブデザインの目的に合わせて、アイコンを大きくしておいて、このようにサイズを変更すると便利です。 ただし、これは IE 9 以降でのみ機能するため、これらの古いブラウザーをサポートする必要がある場合は、画像のサイズを変更しておいて、それをそのまま挿入する必要があります。

+ +

最後に、背景画像を表示するスペースを確保するためにリンクに {{cssxref("padding-right")}} を設定しているので、テキストと重なっていません。

+ +

最後の一言 — どのように外部リンクだけを選択したのでしょうか? あなたがHTML リンクを適切に記述しているのなら、外部リンクには絶対 URL のみを使用しているはずです — 自分のサイトの他の部分にリンクするには(最初のリンクのように)相対リンクを使用するほうが効率的です。 したがって、テキスト  "http" は(2番目と3番目のリンクのように)外部リンクにのみ現れ、これを属性セレクタで選択できます。 a[href*="http"] は {{htmlelement("a")}} 要素を選択しますが、"http" を含む値を持つ {{htmlattrxref("href","a")}} 属性がある場合に限ります。

+ +

それでは、これで全部です — 上の能動的学習セクションを再検討して、この新しいテクニックを試してみてください!

+ +
+

: 背景レスポンシブウェブデザインにまだ慣れていなくても心配しないでください。 これらは他の場所で説明されています。

+
+ + + +

この記事でこれまでに説明したツールは、他の方法でも使用できます。 例えば、ホバーのような状態は、リンクだけでなく、さまざまな要素を装飾するために使用できます — 段落、リスト項目、またはその他のもののホバー状態を装飾することができます。

+ +

さらに、リンクは特定の状況下ではボタンのように見えて、そうふるまうように装飾されているのが普通です — ウェブサイトのナビゲーションメニューは通常リンクを含むリストとしてマークアップれており、ユーザーがサイトの他の部分にアクセスできるようにする一連のコントロールボタンやタブのように簡単にスタイル設定できます。 その方法を探りましょう。

+ +

まず、いくつかの HTML です。

+ +
<ul>
+  <li><a href="#">Home</a></li><li><a href="#">Pizza</a></li><li><a href="#">Music</a></li><li><a href="#">Wombats</a></li><li><a href="#">Finland</a></li>
+</ul>
+ +

そして CSS です。

+ +
body,html {
+  margin: 0;
+  font-family: sans-serif;
+}
+
+ul {
+  padding: 0;
+  width: 100%;
+}
+
+li {
+  display: inline;
+}
+
+a {
+  outline: none;
+  text-decoration: none;
+  display: inline-block;
+  width: 19.5%;
+  margin-right: 0.625%;
+  text-align: center;
+  line-height: 3;
+  color: black;
+}
+
+li:last-child a {
+  margin-right: 0;
+}
+
+a:link, a:visited, a:focus {
+  background: yellow;
+}
+
+a:hover {
+  background: orange;
+}
+
+a:active {
+  background: red;
+  color: white;
+}
+ +

これにより、次のような結果が得られます。

+ +

{{ EmbedLiveSample('Styling_links_as_buttons', '100%', 100) }}

+ +

最も興味深い部分に焦点を当てて、ここで何が起こっているのかを説明しましょう。

+ + + +
+

: HTML 内のリスト項目がすべて一行に記述されていることに気付いたかもしれません。インラインブロック要素間のスペースや改行は、単語間のスペースと同様にページにスペースを作成します。 そして、そのようなスペースは水平ナビゲーションメニューのレイアウトを壊すでしょう。だからスペースを取り除きました。この問題(と、その解決方法)についての詳細は、インラインブロック要素間のスペースの戦い(英語)で見つけることができます。

+
+ +

あなたのスキルをテストしてみてください!

+ +

あなたはこの記事の最後に到達し、すでに私たちのアクティブラーニングのセクションでいくつかのスキルテストを行いましたが、今後の最も重要な情報を覚えていますか?この情報を保持しているかどうかを確認するためのアセスメントがモジュールの最後にあります。コミュニティスクールのホームページの組版を参照してください。

+ +

この評価ではこのモジュールで説明されているすべての知識をテストしますので、次に進む前に次の記事を読んだほうがいいかもしれません。

+ +

まとめ

+ +

この記事が、リンクについて知っておく必要があるすべての情報を提供してくれることを願っています — 今のところは! テキストの装飾モジュールの最後の記事では、ウェブサイトでのカスタムフォントの使用方法や、ウェブフォントの使用方法について詳しく説明しています。

+ +

{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/styling_text/styling_lists/index.html b/files/ja/learn/css/styling_text/styling_lists/index.html new file mode 100644 index 0000000000..0690271d64 --- /dev/null +++ b/files/ja/learn/css/styling_text/styling_lists/index.html @@ -0,0 +1,398 @@ +--- +title: リストの装飾 +slug: Learn/CSS/Styling_text/Styling_lists +tags: + - Article + - Beginner + - CSS + - Guide + - Styling + - Text + - bullets + - lists +translation_of: Learn/CSS/Styling_text/Styling_lists +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/Styling_text/Fundamentals", "Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text")}}
+ +

リストは他のテキストとほとんど同じようにふるまいますが、知っておくべきリスト固有の CSS プロパティと、考慮すべきベストプラクティスがいくつかあります。 この記事はすべてを説明しています。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー、HTML の基本(HTML 入門を学ぶ)、CSS の基本(CSS 入門を学ぶ)、CSS のテキストとフォントの基礎
学習目標:リストの装飾に関連するベストプラクティスとプロパティに慣れること。
+ +

簡単なリストの例

+ +

はじめに、簡単なリストの例を見てみましょう。 この記事を通して、順序なしリスト、順序付きリスト、そして説明リストを見ていきます。これらはどれも似たような装飾機能持っていますが、リストの種類に特有のものもあります。 装飾していない例は Github にあります(ソースコードもチェックしてください)。

+ +

そのリストの例の HTML はこんな感じです。

+ +
<h2>Shopping (unordered) list</h2>
+
+<p>Paragraph for reference, paragraph for reference, paragraph for reference,
+paragraph for reference, paragraph for reference, paragraph for reference.</p>
+
+<ul>
+  <li>Hummus</li>
+  <li>Pita</li>
+  <li>Green salad</li>
+  <li>Halloumi</li>
+</ul>
+
+<h2>Recipe (ordered) list</h2>
+
+<p>Paragraph for reference, paragraph for reference, paragraph for reference,
+paragraph for reference, paragraph for reference, paragraph for reference.</p>
+
+<ol>
+  <li>Toast pita, leave to cool, then slice down the edge.</li>
+  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
+  <li>Wash and chop the salad.</li>
+  <li>Fill pita with salad, hummus, and fried halloumi.</li>
+</ol>
+
+<h2>Ingredient description list</h2>
+
+<p>Paragraph for reference, paragraph for reference, paragraph for reference,
+paragraph for reference, paragraph for reference, paragraph for reference.</p>
+
+<dl>
+  <dt>Hummus</dt>
+  <dd>A thick dip/sauce generally made from chick peas blended with tahini, lemon juice, salt, garlic, and other ingredients.</dd>
+  <dt>Pita</dt>
+  <dd>A soft, slightly leavened flatbread.</dd>
+  <dt>Halloumi</dt>
+  <dd>A semi-hard, unripened, brined cheese with a higher-than-usual melting point, usually made from goat/sheep milk.</dd>
+  <dt>Green salad</dt>
+  <dd>That green healthy stuff that many of us just use to garnish kebabs.</dd>
+</dl>
+ +

ここで実際の例に行き、ブラウザー開発者ツールを使用してリスト要素を調べると、次のようないくつかの装飾のデフォルト設定に気付くでしょう。

+ + + +

リストの間隔の取り扱い

+ +

リストを装飾するときは、(段落や画像などの)周囲の要素と同じ垂直方向の間隔(バーティカルリズム(vertical rhythm)とも呼ばれる)と、互いに同じ水平方向の間隔を維持するように装飾を調整する必要があります(Github で完成した装飾した例を見ることができ、ソースコードも見つけることができます)。

+ +

テキストの装飾と間隔調整に使用する CSS は次のとおりです。

+ +
/* General styles */
+
+html {
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 10px;
+}
+
+h2 {
+  font-size: 2rem;
+}
+
+ul,ol,dl,p {
+  font-size: 1.5rem;
+}
+
+li, p {
+  line-height: 1.5;
+}
+
+/* Description list styles */
+
+
+dd, dt {
+  line-height: 1.5;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: 1.5rem;
+}
+ + + +

リスト固有の装飾

+ +

リストの一般的な間隔調整テクニックを見てきました。 次に、リスト固有のプロパティを調べてみましょう。 最初に知っておくべき3つのプロパティがあり、それらは {{htmlelement("ul")}} や {{htmlelement("ol")}} 要素に設定できます。

+ + + +

行頭記号の装飾

+ +

前述のように、{{cssxref("list-style-type")}} プロパティを使用して、行頭記号(bullet point)に使用する行頭記号(bullet)の種類を設定できます。 この例では、順序付きリストで大文字のローマ数字を使用するように設定しています。

+ +
ol {
+  list-style-type: upper-roman;
+}
+ +

これにより、次のようになります。

+ +

行頭記号がリスト項目テキストの外側に表示されるように設定された順序付きリスト。

+ +

{{cssxref("list-style-type")}} のリファレンスページをチェックすることで、もっとたくさんのオプションを見つけることができます。

+ +

行頭記号の位置

+ +

{{cssxref("list-style-position")}} プロパティは、行頭記号をリスト項目の内側に表示するか、その外側の各項目の先頭より前に表示するかを設定します。 デフォルト値は outside です。 これは、上で見たように、行頭記号をリスト項目の外側に配置します。

+ +

値を inside に設定すると、行頭記号をラインの内側に配置します。

+ +
ol {
+  list-style-type: upper-roman;
+  list-style-position: inside;
+}
+ +

行頭記号がリスト項目のテキストの内側に表示されるように設定された順序付きリスト。

+ +

カスタム行頭記号画像の使用

+ +

{{cssxref("list-style-image")}} プロパティを使用すると、行頭記号にカスタム画像を使用できます。 構文は次のようにとても簡単です。

+ +
ul {
+  list-style-image: url(star.svg);
+}
+ +

ただし、このプロパティは、行頭記号の位置、サイズなどを制御するという点では少し制限があります。 {{cssxref("background")}} プロパティファミリーを使用するほうが得策です。 これについては、ボックスの装飾モジュールで詳しく説明します。 今のところ、これは味見です!

+ +

完成した例では、(既に上で見たものの上に)次のように順序なしリストを装飾しました。

+ +
ul {
+  padding-left: 2rem;
+  list-style-type: none;
+}
+
+ul li {
+  padding-left: 2rem;
+  background-image: url(star.svg);
+  background-position: 0 0;
+  background-size: 1.6rem 1.6rem;
+  background-repeat: no-repeat;
+}
+ +

ここでは次のことを行いました。

+ + + +

これにより、次のような結果が得られます。

+ +

行頭記号が小さな星の画像として設定された順序なしリスト

+ +

list-style 一括指定

+ +

上記の3つのプロパティはすべて、単一の一括指定プロパティ {{cssxref("list-style")}} を使用して設定できます。 例えば、次の CSS を、

+ +
ul {
+  list-style-type: square;
+  list-style-image: url(example.png);
+  list-style-position: inside;
+}
+ +

これに置き換えることができます。

+ +
ul {
+  list-style: square url(example.png) inside;
+}
+ +

値は任意の順序でリストすることができ、1つ、2つ、または3つすべてを使用できます(含まれていないプロパティーに使用されるデフォルト値は discnoneoutside です)。 typeimage の両方が指定されている場合、画像が何らかの理由でロードできない場合に、type を代替として使用します。

+ +

リストの数え方の制御

+ +

場合によっては、順序付きリストで異なる方法で数えたいことがあります — 例えば 1 以外の数から始めたり、逆方向に数えたり、1 以上のステップで数えたりです。 HTML と CSS には、ここで役立つツールがいくつかあります。

+ +

start

+ +

{{htmlattrxref("start","ol")}} 属性を使用すると、1 以外の数からリストを数え始めます。 次の例では、

+ +
<ol start="4">
+  <li>Toast pita, leave to cool, then slice down the edge.</li>
+  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
+  <li>Wash and chop the salad.</li>
+  <li>Fill pita with salad, hummus, and fried halloumi.</li>
+</ol>
+ +

この出力を与えます。

+ +

{{ EmbedLiveSample('start', '100%', 150) }}

+ +

reversed

+ +

{{htmlattrxref("reversed","ol")}} 属性はリストのカウントアップではなくカウントダウンを開始します。 次の例では、

+ +
<ol start="4" reversed>
+  <li>Toast pita, leave to cool, then slice down the edge.</li>
+  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
+  <li>Wash and chop the salad.</li>
+  <li>Fill pita with salad, hummus, and fried halloumi.</li>
+</ol>
+ +

この出力を与えます。

+ +

{{ EmbedLiveSample('reversed', '100%', 150) }}

+ +
+

: 逆方向のリストに start 属性の値より多くのリスト項目がある場合、カウントは引き続きゼロになり、その後負の値になります。

+
+ +

value

+ +

{{htmlattrxref("value","li")}} 属性を使用すると、リスト項目を特定の数値に設定できます。 次の例では、

+ +
<ol>
+  <li value="2">Toast pita, leave to cool, then slice down the edge.</li>
+  <li value="4">Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
+  <li value="6">Wash and chop the salad.</li>
+  <li value="8">Fill pita with salad, hummus, and fried halloumi.</li>
+</ol>
+ +

この出力を与えます。

+ +

{{ EmbedLiveSample('value', '100%', 150) }}

+ +
+

注: 非数値の {{cssxref("list-style-type")}} を使用している場合でも、value 属性に同等の数値を使用する必要があります。

+
+ +

能動的学習: ネストしたリストの装飾

+ +

この能動的学習セッションでは、上で学んだことを取り入れて、ネストしたリストを装飾してください。 HTML を提供してあるので、次のことを行います。

+ +
    +
  1. 順序なしリストに正方形の行頭記号を付けます。
  2. +
  3. 順序なしリスト項目と順序付きリスト項目のフォントサイズの 1.5 のラインの高さを指定します。
  4. +
  5. 順序付きリストに小文字のアルファベットの行頭記号を付けます。
  6. +
  7. 行頭記号の種類、間隔、その他見つけられるものは何でも試して、好きなだけリストの例を試してみてください。
  8. +
+ +

間違えた場合は、Reset ボタンを使用していつでもリセットできます。 本当に立ち往生したら、答えを見るために Show solution ボタンを押してください。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 800) }}

+ +

関連情報

+ +

CSS カウンターは、リストの数え方と装飾をカスタマイズするための高度なツールを提供しますが、非常に複雑です。 あなたが自身を伸ばしたいと思うならば、これらを調べることを勧めます。 次を見てください。

+ + + +

まとめ

+ +

関連するいくつかの基本的な原則と特定のプロパティを知っていれば、リストの装飾のこつは比較的簡単です。 次の記事では、リンクの装飾テクニックについて説明します。

+ +

{{PreviousMenuNext("Learn/CSS/Styling_text/Fundamentals", "Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text")}}

+ + + +

このモジュール内の文書

+ + diff --git a/files/ja/learn/css/styling_text/typesetting_a_homepage/index.html b/files/ja/learn/css/styling_text/typesetting_a_homepage/index.html new file mode 100644 index 0000000000..7fb8d97e42 --- /dev/null +++ b/files/ja/learn/css/styling_text/typesetting_a_homepage/index.html @@ -0,0 +1,126 @@ +--- +title: コミュニティスクールのホームページの組版 +slug: Learn/CSS/Styling_text/Typesetting_a_homepage +tags: + - Assessment + - Beginner + - CSS + - CodingScripting + - Link + - Styling text + - font + - list + - web font +translation_of: Learn/CSS/Styling_text/Typesetting_a_homepage +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}
+ +

この評価では、コミュニティスクールのホームページ用にテキストを装飾することで、このモジュール全体でカバーしてきたすべてのテキスト装飾テクニックについての理解をテストします。 途中で楽しい時間があるかもしれません。

+ + + + + + + + + + + + +
前提知識:この評価を試みる前に、このモジュールのすべての記事を読んでおくべきです。
学習目標:CSS テキスト装飾テクニックの理解をテストすること。
+ +

出発点

+ +

この評価を開始するには、次のことが必要です。

+ + + +
+

: あるいは、JSBinThimble などのサイトを使って評価することもできます。 HTML を貼り付けて CSS をこれらのオンラインエディタのいずれかに入力し、この URL を使用して背景画像を指定することができます。 使用しているオンラインエディタに別の CSS パネルがない場合は、それをドキュメントの先頭の <style> 要素に自由に配置してください。

+
+ +

プロジェクトの概要

+ +

架空のコミュニティカレッジのホームページ用の生の HTML と、ページを2列のレイアウトに装飾し、その他の基本的な装飾をする CSS が提供されています。 CSS ファイルの最後にあるコメントの下に CSS の追加部分を書いて、あなたが行った部分に簡単に印を付けることができるようにします。 一部のセレクタがくどくても心配しないで、この場合は見逃してください。

+ +

フォント

+ + + +

一般的なテキスト装飾

+ + + +

リンク

+ + + +

リスト

+ + + +

ナビゲーションメニュー

+ + + +

ヒントとコツ

+ + + +

+ +

次のスクリーンショットは、完成したデザインの外観の例です。

+ +

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合は、採点のために作品を教師や指導者に渡すことができるはずです。 自己学習をしている場合は、この演習についてのディスカッションスレッドMozilla IRC#mdn IRC チャンネルで尋ねることで、かなり簡単に採点の手引きを得ることができます。 まず演習を試してみてください — 不正行為によって得られるものは何もありません!

+ +

{{PreviousMenu("Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}

+ +

 

+ +

このモジュール内の文書

+ + + +

 

diff --git "a/files/ja/learn/css/styling_text/\343\202\246\343\202\247\343\203\226\343\203\225\343\202\251\343\203\263\343\203\210/index.html" "b/files/ja/learn/css/styling_text/\343\202\246\343\202\247\343\203\226\343\203\225\343\202\251\343\203\263\343\203\210/index.html" new file mode 100644 index 0000000000..d96b610029 --- /dev/null +++ "b/files/ja/learn/css/styling_text/\343\202\246\343\202\247\343\203\226\343\203\225\343\202\251\343\203\263\343\203\210/index.html" @@ -0,0 +1,219 @@ +--- +title: ウェブフォント +slug: Learn/CSS/Styling_text/ウェブフォント +tags: + - '@font-face' + - Article + - Beginner + - CSS + - CSS Fonts + - Fonts + - Guide + - Learn + - Web Development + - Web Fonts Article + - Web fonts documentation + - font-family + - web fonts +translation_of: Learn/CSS/Styling_text/Web_fonts +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text/Typesetting_a_homepage", "Learn/CSS/Styling_text")}}
+ +

このモジュールの最初の記事では、フォントとテキストの装飾に使用できる基本的な CSS 機能について調べました。 この記事では、ウェブフォントの詳細を調べながら、さらに進みます — これらを使用すると、ウェブページと一緒にカスタムフォントをダウンロードすることを可能にして、より多様なカスタムテキストの装飾を可能にします。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー、HTML の基本(HTML 入門を学ぶ)、CSS の基本(CSS 入門を学ぶ)、CSS のテキストとフォントの基礎
学習目標:サードパーティのサービスを使用するか、独自のコードを作成することによって、ウェブフォントをウェブページに適用する方法を習得する。
+ +

フォントファミリーの復習

+ +

基本的なテキストとフォントの装飾で見たように、HTML に適用されるフォントは {{cssxref("font-family")}} プロパティを使って制御できます。 これは1つ以上のフォントファミリー名を取り、ブラウザーはそれが実行されているシステムで利用可能なフォントを見つけるまでリストを順にたどります。

+ +
p {
+  font-family: Helvetica, "Trebuchet MS", Verdana, sans-serif;
+}
+ +

このシステムはうまく機能しますが、伝統的にウェブ開発者のフォント選択は限られていました。 一般的なすべてのシステムで利用できることを保証できるフォントは、ほんの一握りです — いわゆるウェブセーフフォントです。 フォントスタックを使用して希望するフォントを指定し、その後にウェブセーフの代替フォントを指定してからデフォルトのシステムフォントを指定することができますが、これはデザインが各フォントなどでうまく見えることを確認するためにテストの面でオーバーヘッドを追加します。(訳注:日本語フォントを英語フォントの後、デフォルトフォントの前に指定すれば、英語部分だけ英語フォントにすることができます。 つまり、英語フォントだけの指定であっても、日本語環境なら、日本語には日本語のデフォルトフォントが使われるということです。 中国語環境なら、中国語の漢字が使われることでしょう。)

+ +

ウェブフォント

+ +

しかし、IE バージョン 6 でも非常にうまく動作する代替手段があります。 ウェブフォントは、ウェブサイトにアクセスした時に一緒にダウンロードするフォントファイルを指定できる CSS の機能です。 つまり、ウェブフォントをサポートするブラウザーであれば、指定したフォントをそのまま使用できることを意味しています。 すばらしい! 必要な構文は次のようになります。

+ +

まず最初に、CSS の先頭に {{cssxref("@font-face")}} ブロックがあり、ダウンロードするフォントファイルを指定します。

+ +
@font-face {
+  font-family: "myFont";
+  src: url("myFont.woff");
+}
+ +

これより下では、@font-face の中で指定されているフォントファミリー名を使ってカスタムフォントを通常通り好きなものに適用できます。

+ +
html {
+  font-family: "myFont", "Bitstream Vera Serif", serif;
+}
+ +

構文はこれより少し複雑になります。 以下で詳しく説明します。

+ +

ウェブフォントに関して留意すべき重要な点が2つあります。

+ +
    +
  1. ブラウザーはさまざまなフォント形式をサポートしているため、適切なクロスブラウザーをサポートするには複数のフォント形式が必要になります。 例えば、最近のほとんどのブラウザーは最も効率的な形式である WOFF / WOFF2(Web Open Font Format バージョン 1 および 2)をサポートしていますが、古いバージョンの IE は EOT(Embedded Open Type)フォントしかサポートしていないし、古いバージョンの iPhone や Android のブラウザーをサポートするには、SVG 版のフォントを含める必要があるかもしれません。 必要なコードの生成方法を下の方で示します。
  2. +
  3. フォントは一般に自由に使用できません。 それらの代金を払わなければなりません、そして/またはコードの中で(またはサイトで)フォント作成者のクレジット表示のような他のライセンス条件に従わなければなりません。 フォントを盗み、適切なクレジットを与えずに使用するべきではありません。
  4. +
+ +
+

: テクノロジーとしてのウェブフォントは、バージョン 4 以降の Internet Explorer でサポートされています!

+
+ +

能動的学習: ウェブフォントの例

+ +

この点を考慮して、最初の原則から基本的なウェブフォントの例を作り上げましょう。 埋め込まれたライブの例を使用してこれをデモすることは困難なので、代わりに、以下のセクションで詳述されている手順に従うことでプロセスを理解してください。

+ +

コードを追加するための出発点として、web-font-start.html ファイルと web-font-start.css ファイルを使用する必要があります(ライブの例を見る)。 ここで、これらのファイルのコピーをコンピュータの新しいディレクトリに作成します。 web-font-start.css ファイルには、この例の基本的なレイアウトと組版を処理するための最小限の CSS がいくつかあります。

+ +

フォントを探す

+ +

この例では、見出し用と本文テキスト用の2つのウェブフォントを使用します。 まず最初に、フォントを含むフォントファイルを見つける必要があります。 フォントはフォント製造元によって作成され、さまざまなファイル形式で保存されます。 フォントを入手できるサイトは、一般的に3種類あります。

+ + + +

いくつかのフォントを見つけましょう! Font Squirrel に行き、2つのフォントを選択します — 見出しには素敵で面白いフォント(多分素敵な display や slab serif フォント)、段落にはやや派手で読みやすいフォントです。 各フォントが見つかったら、download(ダウンロード)ボタンを押して、先ほど保存した HTML ファイルと CSS ファイルと同じディレクトリ内にファイルを保存します。 TTF(True Type Fonts)か OTF(Open Type Fonts)かは関係ありません。

+ +

いずれの場合も、フォントパッケージを解凍します(ウェブフォントは通常、フォントファイルとライセンス情報を含む ZIP ファイルで配布されます)。 パッケージの中に複数のフォントファイルを見つけるかもしれません — 例えば、thin(細字)、medium(中字)、bold(太字)、italic(イタリック)、thin italic(細字イタリック)など、利用可能なさまざまな異形(variant)を持つファミリーとして配布されるフォントがあります。 この例では、それぞれの選択に対して 1つのフォントファイルを使用することを考慮してください。

+ +
+

: 右側の列の "Find fonts"(フォントの検索)セクションで、さまざまな tags(タグ)や classifications(分類)をクリックして表示された選択肢を絞り込むことができます。 (訳注:残念なことに現在のところ日本語フォントはないようです。)

+
+ +

必要なコードの生成

+ +

今、必要なコード(そしてフォント形式)を生成する必要があります。 フォントごとに、次の手順に従います。

+ +
    +
  1. 商用やウェブのプロジェクトでこれを使用する場合は、ライセンス要件をすべて満たしていることを確認してください。
  2. +
  3. Font Squirrel の Webfont Generator(ウェブフォントジェネレータ)に行きます。
  4. +
  5. Upload Fonts(フォントのアップロード)ボタンを使って2つのフォントファイルをアップロードします。
  6. +
  7. "Yes, the fonts I'm uploading are legally eligible for web embedding." (はい、アップロードしたフォントはウェブの埋め込みに法的に適格です。)というチェックボックスをオンにします。
  8. +
  9. Download your kit(キットをダウンロードする)をクリックします。
  10. +
+ +

ジェネレータの処理が完了したら、ZIP ファイルをダウンロードする必要があります — それを HTML と CSS と同じディレクトリに保存してください。

+ +

デモでのコードの実装

+ +

この時点で、生成したばかりのウェブフォントのキットを解凍します。 解凍したディレクトリ内には、3つの便利なアイテムがあります。

+ + + +

デモにこれらのフォントを実装するには、次の手順に従います。

+ +
    +
  1. 解凍したディレクトリの名前を fonts のように簡単でシンプルなものに変更します。
  2. +
  3. stylesheet.css ファイルを開き、その中に含まれている両方の @font-face ブロックを web-font-start.css ファイルにコピーします — フォントはサイトで使用する前にインポートする必要があるため、CSS のどれよりも前の一番上に配置する必要があります。
  4. +
  5. url() 関数は CSS にインポートしたいフォントファイルを指しています — ファイルへのパスが正しいことを確認する必要があるので、各パスの先頭に fonts/ を追加します(必要に応じて調整します)。
  6. +
  7. これで、ウェブセーフフォントやデフォルトのシステムフォントと同じように、これらのフォントをフォントスタックで使用できます。 例えば、 +
    font-family: 'zantrokeregular', serif;
    +
  8. +
+ +

いくつかの素敵なフォントが実装されたデモページができあがるはずです。異なるフォントは異なるサイズで作成されるため、サイズや間隔などを調整して、ルック・アンド・フィールを調整する必要があります。

+ +

+ +
+

: これがうまくいかない場合は、あなたのバージョンと完成したファイルとを比較してみてください — web-font-finished.htmlweb-font-finished.css を見てください(完成した例をライブで実行してください)。

+
+ +

オンラインフォントサービスの使用

+ +

オンラインフォントサービスは一般的にあなたのためにフォントを保存して提供するので、@font-face コードを書くことを心配する必要はなく、一般的にサイトに1行か2行の単純なコードを挿入するだけですべてがうまくいきます。例としては、Adobe FontsCloud.typography などが挙げられます。これらのサービスのほとんどはサブスクリプションベースですが、特に迅速なテスト作業やデモを書くのに便利な無料のサービスである Google Fonts は例外です。

+ +

これらのサービスのほとんどは使いやすいので、詳細には説明しません。 Google のフォントを簡単に見てみましょう。 そうすれば、アイデアを得ることができます。 ここでも、出発点として web-font-start.htmlweb-font-start.css のコピーを使用してください。

+ +
    +
  1. Google Fonts に行きます。
  2. +
  3. 左側のフィルタを使って、選択したいフォントの種類を表示し、好きなフォントをいくつか選択します。 (訳注:Languages(言語)に Japanese(日本語)を選んでも、中国語のフォントも表示されます。 フォントによっては、存在しない文字があるようなので注意しましょう。 日本語環境なら文字は表示されますが、書体の統一感はなくなってしまいます。)
  4. +
  5. フォントファミリーを選択するには、その横にある ⊕ ボタンを押します。
  6. +
  7. フォントファミリーを選択したら、ページ下部の [選択数] Families Selected バーを押します。
  8. +
  9. 表示された画面で、最初に表示された HTML コードの行をコピーして、それを HTML ファイルの先頭に貼り付ける必要があります。 フォントを CSS で使用する前にインポートされるように、既存の {{htmlelement("link")}} 要素の上に配置します。 (訳注:{{cssxref("@import")}} を選択すれば、CSS ファイルに貼り付けることもできます。)
  10. +
  11. 次に、カスタムフォントを HTML に適用するために、リストされている CSS 宣言を必要に応じて CSS にコピーする必要があります。
  12. +
+ +
+

: あなたの作品を私たちの作品と照合する必要がある場合は、完成版を google-font.html および google-font.css で見ることができます(それをライブで見る)。

+
+ +

@font-face の詳細

+ +

Font Squirrel によって生成された @font-face 構文を調べてみましょう。 これは、ブロックの1つがどのように見えるかです。

+ +
@font-face {
+  font-family: 'ciclefina';
+  src: url('fonts/cicle_fina-webfont.eot');
+  src: url('fonts/cicle_fina-webfont.eot?#iefix') format('embedded-opentype'),
+         url('fonts/cicle_fina-webfont.woff2') format('woff2'),
+         url('fonts/cicle_fina-webfont.woff') format('woff'),
+         url('fonts/cicle_fina-webfont.ttf') format('truetype'),
+         url('fonts/cicle_fina-webfont.svg#ciclefina') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+ +

@font-face が普及し始めた頃の Paul Irish による投稿(Bulletproof @font-face Syntax)の後、これは "bulletproof  @font-face 構文" と呼ばれています。 それを見て、それが何をするのか見てみましょう。

+ + + +
+

: ウェブフォントに特定の {{cssxref("font-variant")}} および {{cssxref("font-stretch")}} の値を指定することもできます。 新しいブラウザーでは、unicode-range の値でウェブフォントで使用する特定の文字範囲を指定することもできます — サポートしているブラウザーでは、指定された文字のみがダウンロードされ、不要なダウンロードを節約できます。 Drew McLellan による unicode-range を使ったカスタムフォントスタックの作成(英語)は、これをどのように利用するかについていくつかの役に立つアイデアを提供します。

+
+ +

可変フォント

+ +

これは、幅、太さ、スタイルごとに別のフォントファイルを用意するのではなく、書体のさまざまなバリエーションを一つのファイルに組み込むことができるフォントです。これらのフォントは初心者向けのコースにしてはやや高度なものですが、もしあなたが自分自身を伸ばして調べたいと思っているのであれば、可変フォントガイドを読んでみてください。

+ +

ブラウザでは、可変フォントと呼ばれる新しいフォントテクノロジーがあります。これらは、幅、太さ、スタイルごとに個別のフォントファイルを用意するのではなく、書体のさまざまなバリエーションを1つのファイルに組み込むことができるフォントです。 初心者コースでは多少上級ですが、調べてみたい場合は、Variable フォントガイドをお読みください。

+ +

あなたのスキルをテストしてください!

+ +

あなたはこの記事の最後に到達し、すでに私たちのアクティブラーニングのセクションでいくつかのスキルテストを行いましたが、今後の最も重要な情報を覚えていますか?あなたがこの情報を保持していることを確認するための評価をモジュールの最後に見つけることができます。コミュニティスクールのホームページの組版を参照してください。

+ +

まとめ

+ +

テキストの装飾の基本についての記事を読み終えたので、今度はモジュール「コミュニティスクールのホームページの組版」の評価で理解度をテストします。

+ +

{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text/Typesetting_a_homepage", "Learn/CSS/Styling_text")}}

+ + + +

このモジュール内の文書

+ + diff --git a/files/ja/learn/forms/advanced_styling_for_html_forms/index.html b/files/ja/learn/forms/advanced_styling_for_html_forms/index.html new file mode 100644 index 0000000000..1d04415369 --- /dev/null +++ b/files/ja/learn/forms/advanced_styling_for_html_forms/index.html @@ -0,0 +1,556 @@ +--- +title: HTML フォームへの高度なスタイル設定 +slug: Learn/Forms/Advanced_styling_for_HTML_forms +tags: + - Advanced + - CSS + - Forms + - HTML + - Web + - ガイド + - 例 +translation_of: Learn/Forms/Advanced_form_styling +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Forms/Styling_web_forms", "Learn/Forms/UI_pseudo-classes", "Learn/Forms")}}
+ +

本記事では、スタイル設定が難しい一部の(不良なものと劣悪なもの)フォームコントロールで CSS を使用する方法を見ていきます。前の記事で見たように、テキストフィールドやボタンでの CSS 使用はまったく問題がありません。ここからは、HTML フォームへのスタイル設定の闇の部分を見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーと、HTMLCSS の基本的な理解。
目的:フォームのどの部分をスタイル設定するのが難しいのか、またなぜなのかを理解する。そこをカスタマイズするのに何ができるかを学ぶ。
+ +

始める前に、2 種類の HTML フォームウィジェットについておさらいしましょう:

+ +

不良: スタイルの設定が難しく複雑なトリックが必要であり、時に CSS3 の高度な知識が必要である要素:

+ + + +

劣悪: いくつかの要素は CSS でスタイル設定できません。これらが含まれます:

+ + + +

見た目: OS レベルのスタイル制御

+ +

前の記事では歴史的に、ウェブフォームのスタイル設定は OS で行われており、それがこのコントロールの見た目のカスタマイズの問題の一部となっていました。

+ +

{{cssxref("appearance")}} プロパティは OS やシステムレベルでウェブフォームのスタイル設定を制御する方法としてい作成されました。不運なことに、そのプロパティの元々の実装の動作はブラウザー間で大きく異なっており、そんなに便利ではありませんでした。最近の実装ではもっと動作が一貫してきており、十分興味深く、それは Chromium-ベースのブラウザー (Chrome, Opera, Edge), Safari, Firefox のいずれも -webkit-  のプレフィックスつきバージョン (-webkit-appearance)をサポートしています。Firefox は、ウェブ開発者の大半が -webkit- プレフィックスバージョンをサポート使っていて互換性が良いため、このように決めました。

+ +

リファレンスページを見ると -webkit-appearance の多くの値がありますが、最も便利で、おそらく唯一使うのは none です。これはあらゆるコントロールがシステムレベルのスタイル設定するのをできるだけ防止して、CSS を用いた独自のスタイル設定をできるようにします。

+ +

例えば、次のコントロールを見てみます:

+ +
<form>
+  <p>
+    <label for="search">search: </label>
+    <input id="search" name="search" type="search">
+  </p>
+  <p>
+    <label for="text">text: </label>
+    <input id="text" name="text" type="text">
+  </p>
+  <p>
+    <label for="date">date: </label>
+    <input id="date" name="date" type="datetime-local">
+  </p>
+  <p>
+    <label for="radio">radio: </label>
+    <input id="radio" name="radio" type="radio">
+  </p>
+  <p>
+    <label for="checkbox">checkbox: </label>
+    <input id="checkbox" name="checkbox" type="checkbox">
+  </p>
+  <p><input type="submit" value="submit"></p>
+  <p><input type="button" value="button"></p>
+</form>
+ +

次の CSS を適用してシステムレベルのスタイル設定を削除します。

+ +
input {
+  -webkit-appearance: none;
+  appearance: none;
+}
+ +
+

: プレフィックスつきのプロパティを使っているときでも、両方の定義を常に入れておくのが良いです — プレフィックス付きとなしと。プレフィックスつきのものは通常は"作業中"を意味するため、将来のブラウザーベンダーはプレフィックスを落とすよう合意することもあるでしょう。上記のコードではそのような結末となった将来でも耐用できます。

+
+ +

下記の例ではあなたのシステムでどのように見えるかを示します — デフォルトでは左で、上記の CSS が適用されると右です (その他のシステムでテストしたい場合はここも探してください)。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/appearence-tester.html", '100%', 400)}}

+ +

たいていの場合、効果は枠線を除去し、CSS でのスタイル設定を少し簡単にしますが、それは本質できありません。いくつかの場合 — 検索やラジオボタン/チェックボックスでは、もっと便利です。これを見ていきましょう。

+ +

検索ボックスを変更する

+ +

<input type="search"> は基本的に単なるテキスト入力のため、なぜ appearance: none; が便利なのでしょうか? 答えは macOS での Chromium ベースのブラウザーでは、検索ボックスはスタイル設定の制限があります — 例えば heightfont-size を自在に調整できません。この理由は macOS以外の Chrome ブラウザーはもう WebKit レンダリングエンジンを使っていません 、これは既定では、いくつかのフォームコントロールで Aqua の見た目が有効です。Aqua が有効だと、いくつかのフォームコントロールは scalable となりません。

+ +

これは デフォルトの Aqua を無効にする appearance: none;で修正できます:

+ +
input[type="search"] {
+    -webkit-appearance: none;
+    appearance: none;
+}
+ +

下記の例では、2 つのスタイル設定された検索ボックスが見えます。右のものは appearance: none; が適用され、左はそうでありません。macOS Chrome で見ると左のものは正しいサイズでないように見えます。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/search-appearence.html", '100%', 200)}}

+ +

興味深いことに、検索フィールドで border/background をセットしてもこの問題を解決できます、なぜならそれも Aqua を無効化や "破壊する" からです。下記のスタイル設定された検索ボックスは appearance: none; が適用されていませんが、前の例と同じ macOS Chrome の問題に悩まされていません。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/styled-search.html", '100%', 200)}}

+ +
+

: 検索フィールドでは、Edge と Chrome で入力がフォーカスされないときに "x" の削除アイコンが消えるが、Safari では残ることに気づくこともあるでしょう。CSS で消すには、input[type="search"]::-webkit-search-cancel-button { display: none; }を使用できますが、フォーカス時のアイコンも取り除き、見た目が元に戻らないようです。

+
+ +

チェックボックスとラジオボタン

+ +

チェックボックスやラジオボタンのスタイリングは難しい場合があります。たとえば、チェックボックスやラジオボタンのサイズはデフォルトのデザインの変更が意図されておらず、ブラウザーで試してみると非常に異なる反応を示します。

+ +

例えば、シンプルなテストケースを考えてみます:

+ +
<span><input type="checkbox"></span>
+ +
span {
+    display: inline-block;
+    background: red;
+}
+
+input[type=checkbox] {
+    width : 100px;
+    height: 100px;
+}
+ +

さまざまなブラウザーでの処理方法は以下のとおりです:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ブラウザー描画結果
Firefox 71 (macOS)
Firefox 57 (Windows 10)
Chrome 77 (macOS), Safari 13, Opera
Chrome 63 (Windows 10)
Internet Explorer 11 (Windows 10)
Edge 16 (Windows 10)
+ +

ラジオボタン/チェックボックスで appearance: none を使う

+ +

これまで見てきたように、チェックボックスやラジオボタンのデフォルトの見た目を {{cssxref('appearance')}}:none; で削除できます。この HTML の例を見てみましょう:

+ +
<form>
+  <fieldset>
+    <legend>Fruit preferences</legend>
+
+    <p>
+      <label>
+        <input type="checkbox" name="fruit-1" value="cherry">
+        I like cherry
+      </label>
+    </p>
+    <p>
+      <label>
+        <input type="checkbox" name="fruit-2" value="banana" disabled>
+        I can't like banana
+      </label>
+    </p>
+    <p>
+      <label>
+        <input type="checkbox" name="fruit-3" value="strawberry">
+        I like strawberry
+      </label>
+    </p>
+  </fieldset>
+</form>
+ +

さて、カスタムチェックボックスデザインでこれらのスタイルを設定しましょう。元のチェックボックスを解除することから始めましょう:

+ +
input[type=checkbox] {
+  -webkit-appearance: none;
+  appearance: none;
+}
+ +

{{cssxref(":checked")}} と {{cssxref(":disabled")}} 擬似クラスを使用して、状態の変化に合わせてカスタムチェックボックスの外観を変更します:

+ +
input[type=checkbox] {
+  position: relative;
+  width: 1em;
+  height: 1em;
+  border: 1px solid gray;
+  /* Adjusts the position of the checkboxes on the text baseline */
+  vertical-align: -2px;
+  /* Set here so that Windows' High-Contrast Mode can override */
+  color: green;
+}
+
+input[type=checkbox]::before {
+  content: "✔";
+  position: absolute;
+  font-size: 1.2em;
+  right: 0;
+  top: -0.3em;
+  visibility: hidden;
+}
+
+input[type=checkbox]:checked::before {
+  /* Use `visibility` instead of `display` to avoid recalculating layout */
+  visibility: visible;
+}
+
+input[type=checkbox]:disabled {
+  border-color: black;
+  background: #ddd;
+  color: gray;
+}
+ +

こうした疑似クラスなどは、次の記事で見つけられますが、上記は次のことをしています:

+ + + +

実際の結果が表示されます。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/checkboxes-styled.html", '100%', 200)}}

+ +

もっと理解できるよう別の例もあります:

+ + + +

{{cssxref("appearance")}} や をサポートしていないブラウザーでこれらのチェックボックスを表示できます。カスタムデザインは失われますが、チェックボックスのままに見えて使用できます。

+ +
+

注記: Internet Explorer はどのバージョンの appearance もサポートしませんが、input[type=checkbox]::-ms-check にて IE のみチェックボックスをターゲットにできます。この手法は、-ms-check という名前にもかかわらず、ラジオボタンでも機能します。

+
+ +

"劣悪な"要素に何ができるか?

+ +

今度は"劣悪な"コントロールに注目しましょう — これは完全にスタイル設定するのが本当に難しいものです。簡単にいうと、これはドロップダウンボックス、colordatetime-local のような複合コントロールタイプ、フィードバック —  {{HTMLElement("progress")}} や {{HTMLElement("meter")}}のような指向性コントロールです。

+ +

問題は、要素はブラウザー同士でいろいろな既定の見た目があって、それにスタイル設定できても、内部のいくつかはスタイル設定できないことです。

+ +

別のルック&フィールに生きる準備がある場合、サイズ変更が一貫していて、background-colors のような単一スタイル設定、システムレベルのスタイル設定を除去できる見た目を使うシンプルなスタイル設定を持って逃げることもできます。

+ +

例を見てみましょう、たくさんの"劣悪な" フォーム機能をつぎつぎに表示しています:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/ugly-controls.html", '100%', 750)}}

+ +

この例では下記の CSS を適用しています:

+ +
body {
+  font-family: 'Josefin Sans', sans-serif;
+  margin: 20px auto;
+  max-width: 400px;
+}
+
+form > div {
+  margin-bottom: 20px;
+}
+
+select {
+  -webkit-appearance: none;
+  appearance: none;
+}
+
+.select-wrapper {
+  position: relative;
+}
+
+.select-wrapper::after {
+  content: "▼";
+  font-size: 1rem;
+  top: 6px;
+  right: 10px;
+  position: absolute;
+}
+
+button, label, input, select, progress, meter {
+  display: block;
+  font-family: inherit;
+  font-size: 100%;
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+  width: 100%;
+  padding: 5px;
+  height: 30px;
+}
+
+input[type="text"], input[type="datetime-local"], input[type="color"], select {
+  box-shadow: inset 1px 1px 3px #ccc;
+  border-radius: 5px;
+}
+
+label {
+  margin-bottom: 5px;
+}
+
+button {
+  width: 60%;
+  margin: 0 auto;
+}
+ +
+

注記: 多数のブラウザーで同時にこの例をテストしたい場合、live版をここで見つけてください (ソースコードも見てください)。

+ +

また JavaScript をページに追加してコントロール自身の下にあるファイルピッカー自身で選択されたファイルを一覧しているのを心に留めておいてください。これは <input type="file"> リファレンスページの例を簡単にしたバージョンです。

+
+ +

見ていくうちに、この見た目がモダンブラウザーのようになっていくのが上手になるでしょう。

+ +

すべてのコントロールとそのラベルに対してグローバルな CSS の正規化を適用し、サイズを同様にして、親のフォントを適用するなどを行っています。これは前の記事で述べたようなことです:

+ +
button, label, input, select, progress, meter {
+  display: block;
+  font-family: inherit;
+  font-size: 100%;
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+  width: 100%;
+  padding: 5px;
+  height: 30px;
+}
+ +

コントロールに統一した影と角丸も与えて、意味のあるようにします:

+ +
input[type="text"], input[type="datetime-local"], input[type="color"], select {
+  box-shadow: inset 1px 1px 3px #ccc;
+  border-radius: 5px;
+}
+ +

範囲や、プログレスバーや、メーターはコントロールエリアの周りに美しくないボックスができるだけなので、意味はありません。

+ +

これらのコントロールタイプそれぞれの仕様と、ハイライトの難しさをこれからお話ししましょう。

+ +

Select とデータリスト

+ +

モダンブラウザーでは、select とデータリストは一般的に、デフォルトからルック&フィールを大きく変えたくないようにスタイル設定する場合、悪くないものです。

+ +

これまで boxe を、とても統一されて一貫した見た目にしてきました。とにかくデータリストコントロールは <input type="text"> なので、問題にならないことがわかっています。

+ +

2 つのものが多少問題をはらんでいます。まず最初に、select がドロップダウンであることを示す "矢印" アイコンは、ブラウザーによって異なります。また select ボックスのサイズを増やしたり、変更したりすると、醜くなりがちです。これを修正するため、例では最初に旧友の appearance: none を使ってアイコンを除去しています:

+ +
select {
+  -webkit-appearance: none;
+  appearance: none;
+}
+ +

次に生成されたコンテンツを使って独自のアイコンを作成します。コントロールの周りに特別なラッパーを置いていて、その理由は::before/::after<select> 要素では動作しなしためです (これは生成されたコンテンツが要素がフォーマットするボックスに対し相対的に配置されますが、フォーム入力は置換された要素 — 表示がブラウザーによって生成されて順番に配置されるもの — として動作するので、1 つもないためです):

+ +
<div class="select-wrapper"><select id="select" name="select">
+  <option>Banana</option>
+  <option>Cherry</option>
+  <option>Lemon</option>
+</select></div>
+ +

次に生成されたコンテンツを使って小さな下向き矢印を作り、正しい場所にポジショニングします:

+ +
.select-wrapper {
+  position: relative;
+}
+
+.select-wrapper::after {
+  content: "▼";
+  font-size: 1rem;
+  top: 6px;
+  right: 10px;
+  position: absolute;
+}
+ +

2 つ目のもう少し有名な問題は、<select> ボックスをクリックして開いたときに出てくる、オプションを含んだボックスを制御できないことです。オプションが親でセットされたフォントを継承していないのに気づくでしょう。また余白スペースや色のようなものも一貫してセットできません。例えば、Firefox では<option> 要素に colorbackground-color を適用できますが、Chrome ではそうなりません。どちらも余白スペース (例 padding)を適用できません。同じことはデータリスト用に出てくるオートコンプリートのリストにも当てはまります。

+ +

本当にオプションをスタイル設定する必要がある場合、カスタムコントロールを生成するライブラリを使用するか、独自のカスタムコントロールを作成するかのどちらかが必要で、あるいは multiple属性を使う select の場合、これはページ上に出てくるすべてのオプションを作成し、この特殊な問題を避けることができます:

+ +
<select id="select" name="select" multiple>
+  ...
+</select>
+ +

もちろんこれでも進めているデザインにはフィットしないこともありますが、注目に値します!

+ +

日付入力タイプ

+ +

日付/時間の入力タイプ (datetime-local, time, week, month) にはすべて同じ重大な関連した問題があります。実際のボックスはテキスト入力と同じくスタイル設定が容易であり、デモ内で得たものの見た目は良いです。

+ +

しかし、コントロールの内部パーツ (例 日付をピックアップするのに使うポップアップカレンダー、値を増減するスピナー) はまったくスタイル設定できず、appearence: none;を使ってスタイルを除去できません。スタイル設定に完全なコントロールが必要な場合、カスタムコントロールを生成するライブラリを使うか、自分で作らねばなりません。

+ +
+

: ここでも<input type="number"> は触れる価値があります — これにも値を増減するスピナーがあるので、同じ問題に悩まさされます。しかし、number タイプを使った場合にデータは簡単に集められて、単に text 入力を (あるいはモバイルブラウザーで数字キーパッドを表示するのに tel を) 代わりに使うのも簡単です

+
+ +

Range 入力タイプ

+ +

<input type="range"> はスタイル設定が煩わしいです。下記のようなものを使ってデフォルトのスライダートラックを完全に削除してカスタムスタイル (ここでは、薄い赤のトラック)に置き換えます:

+ +
input[type="range"] {
+  appearance: none;
+  -webkit-appearance: none;
+  background: red;
+  height: 2px;
+  padding: 0;
+  outline: 1px solid transparent;
+}
+ +

しかし、range コントロールのドラッグハンドルをカスタマイズするのはとても難しいです — range のスタイル設定を完全完全にコントロールするには、その中に複数の非標準な、ブラウザー固有の疑似要素も含んだ、複雑な CSS コードが必要です。Styling Cross-Browser Compatible Range Inputs with CSS で必要なものを細かく書くための CSS トリックを確認します。

+ +

Color 入力タイプ

+ +

color 入力タイプはそこまでひどくないです。サポートされたブラウザーでは、単に小さな枠のある単色のブロックを提供します。

+ +

枠を削除して、色のブロックだけにするには、次のようにします:

+ +
input[type="color"] {
+  border: 0;
+  padding: 0;
+}
+ +

しかし、カスタムソリューションは大きく異るようにする唯一の方法です。

+ +

ファイル入力タイプ

+ +

ファイル入力タイプは通常は OK です — 例で見てきたように、ページの残りの部分に問題なくフィットする何かを作るのはとても簡単です — コントロールの一部分でもある出力行は、入力にそう指示している場合は親のフォントを継承して、カスタムリストに名前やサイズをお好みでスタイル設定できます; 結局は作っています。

+ +

ファイルピッカーの唯一の問題は、ファイルピッカーを開くボタンは完全にスタイル設定できないことです— サイズや色設定は不可能で、別のフォントすら指定できません。

+ +

この回避法は、フォームコントロールに関連するラベルがある場合、ラベルをクリックするとコントロールがアクティブになるという事実を利用します。つまり実際のフォーム入力を次のように隠します:

+ +
input[type="file"] {
+  height: 0;
+  padding: 0;
+  opacity: 0;
+}
+ +

次にボタンのように動作するラベルをスタイル設定し、そのラベルが押された時にファイルピッカーが期待通り開くようにします:

+ +
label[for="file"] {
+  box-shadow: 1px 1px 3px #ccc;
+  background: linear-gradient(to bottom, #eee, #ccc);
+  border: 1px solid rgb(169, 169, 169);
+  border-radius: 5px;
+  text-align: center;
+  line-height: 1.5;
+}
+
+label[for="file"]:hover {
+  background: linear-gradient(to bottom, #fff, #ddd);
+}
+
+label[for="file"]:active {
+  box-shadow: inset 1px 1px 3px #ccc;
+}
+ +

上記の CSS スタイル設定の結果は、下記のライブ実行の例で見ることができます (styled-file-picker.html のライブと、ソースコードも見てください)。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/styled-file-picker.html", '100%', 200)}}

+ +

メーターとプログレスバー

+ +

<meter><progress> は多くの中で最悪かもしれません。前の例で見たように、希望する幅にだいたい正確に設定できました。しかしそれを超えると、どんな方法でもスタイル設定が本当に難しいです。高さの設定をお互いに、ブラウザー間で一貫して処理できず、背景は色付けできるものの、前面のバーはできず、appearance: none を設定すると良くならず、より悪くなります。

+ +

スタイル設定を制御したい場合は、この機能のカスタムソリューションを作ったり、progressbar.js のようなサードパーティのソリューションを使うのは簡単です。

+ +

よりよいフォームへの道: 役に立つライブラリとポリフィル

+ +

すでにいくつか見てきたように、"劣悪な"コントロールを完全にコントロールしたい場合は、JavaScript に頼るしかありません。カスタムフォームウィジェットをビルドする方法の記事では、独自のフォームウィジェットを作成する方法を見ていきますが、そこには役に立つ便利なライブラリがいくつかあります。

+ + + +

次のライブラリはフォームだけではありませんが、HTML フォームを処理するための非常に興味深い機能を備えています:

+ + + +

CSS と JavaScript には副作用があることに注意してください。したがって、それらのライブラリのいずれかを使用することを選択した場合は、スクリプトが失敗した場合に備えて、堅牢なフォールバック HTML を用意する必要があります。スクリプトが失敗する理由はたくさんあります。特にモバイル環境では、これらのケースを可能な限り最善に処理するようにウェブサイトやアプリケーションを設計する必要があります。

+ +

スキルをテストしましょう!

+ +

この記事の最後に到達しましたが、重要な情報を覚えていますか?次に進む前に、この情報を保持しているか検証するテストがあります — Test your skills: Advanced styling を見てください。心に留めておくこととして、この評価シリーズでの質問は、次の記事の知識も前提していてるので、試す前にその記事に取り組むとよいかもしれません。

+ +

まとめ

+ +

HTML フォームで CSS を使用するのはまだ困難ですが、しばしばそれらを回避する方法があります。クリーンでユニバーサルな解決方法はありませんが、最新のブラウザーでは新しい可能性があります。今のところ、最良の解決策は、HTML フォームウィジェットに適用されたときに異なるブラウザーが CSS をサポートする方法の詳細を学ぶことです。

+ +

このガイドの次の記事では、モダンブラウザーでさまざまな状態のフォームをスタイル設定できるさまざまな UI 疑似クラスを見ていきます。

+ +

{{PreviousMenuNext("Learn/Forms/Styling_web_forms", "Learn/Forms/UI_pseudo-classes", "Learn/Forms")}} 

+ +

このモジュール

+ + + +

Advanced Topics

+ + diff --git a/files/ja/learn/forms/form_validation/index.html b/files/ja/learn/forms/form_validation/index.html new file mode 100644 index 0000000000..ea6887ba21 --- /dev/null +++ b/files/ja/learn/forms/form_validation/index.html @@ -0,0 +1,840 @@ +--- +title: クライアント側のフォームデータ検証 +slug: Learn/Forms/Form_validation +tags: + - HTML + - Intermediate + - JavaScript + - Web + - ウェブ + - ガイド + - フォーム + - フォーム検証 + - 中級者向け + - 例 +translation_of: Learn/Forms/Form_validation +--- +
+
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}
+
+ +

データをサーバーへ送信する前に、必須のフォームコントロールが記入され、すべてのフォームコントロールが正しい書式で記入されていることを保証することが重要です。このクライアント側フォーム検証validationは、送信されるデータが様々なフォームコントロールで指定されている要件を満たしていることを保証します。この記事では、クライアント側フォーム検証の基本概念と例を紹介します。

+ + + + + + + + + + + + +
前提知識:コンピューターリテラシー、適度な HTMLCSSJavaScript の理解。
目的:フォーム検証とは何か、なぜ重要なのか、どのように実装するのかを理解すること。
+ +

クライアント側検証は最初のチェックであり、ユーザーの使い勝手を良くするために重要な機能ですクライアント側で不当なデータを捕捉することで、ユーザーはすぐに修正できます。無効なデータがサーバーに送られるて拒否されると、サーバーへ往復してユーザーにデータ修正するよう連絡することによってかなり時間を浪費します。

+ +

しかし、クライアント側の検証はセキュリティ対策とは考えられません!アプリは常にサーバー側でもクライアント側と同様に送信されたデータのセキュリティをチェックします。なぜならクライアント側の検証は容易に回避することができて、悪意のユーザーは簡単に、サーバーへ不正なデータを送信できます。何が起こり得るかは ウェブサイトセキュリティを見てください。サーバー側検証はこのガイドの範囲を超えますが、覚えておいてください。

+ +

フォーム検証とは何か

+ +

有名なサイトの登録フォームに行き、データを求められている書式で入力しなかいと、フィードバックがあることに気づくでしょう。次のようなメッセージが表示されます。

+ + + +

これはフォーム検証と呼ばれます。データを入力したとき、ブラウザー、またはウェブアプリケーションは、そのデータが正しい書式であり、アプリケーションに設定された制約に合っているかをチェックします。ブラウザーで行われる検証はクライアント側検証と、サーバー側で行われるものはサーバー側検証と呼ばれます。この章では、クライアント側検証に集中します。

+ +

情報が正しい書式であれば、アプリケーションはデータのサーバーへの送信を許可し、(ふつうは) データベースに保存されます。正しい書式でなければ、何を修正する必要があるかを説明するメッセージを表示し、ユーザーに再入力させます。

+ +

私たちはできるだけ簡単にフォームを埋めてもらいたいわけですが、なぜフォームを検証する必要があるのでしょうか?理由は主に三つあります。

+ + + +

様々な種類のフォーム検証

+ +

ウェブで見かけるフォーム検証には二つの種類があります。

+ + + +

内蔵フォーム検証の利用

+ +

HTML5 のフォーム制御の機能の一つに JavaScript に頼らない多くのユーザーデータの検証があります。これはフォーム要素の validation属性を使って行います。これまで多くを見てきましたが、まとめ直すと:

+ + + +

入力データをこの指定されたルールに基いて検証します。検証にパスすれば妥当で検証にパスしなければ妥当ではないと考えます。

+ +

要素が妥当な場合は、次のようになります。

+ + + +

要素が不正なときは、次のようになります。

+ + + +
+

注: サーバーへの送信を中断するエラーがいくつかあります。次のものが含まれます: {{domxref('validityState.badInput', 'badInput')}}、{{domxref('validityState.patternMismatch','patternMismatch')}}、{{domxref('validityState.rangeOverflow','rangeOverflow')}} または{{domxref('validityState.rangeUnderflow','underFlow')}}、{{domxref('validityState.stepMismatch','stepMismatch')}}、フォームの制御の {{domxref('validityState.tooLong','tooLong')}} または{{domxref('validityState.tooShort','tooShort')}}、{{domxref('validityState.typeMismatch','typeMismatch')}}、と 必要とされた値の{{domxref('validityState.valueMissing','valueMissing')}}、また {{domxref('validityState.customError','customError')}}も含まれる。

+
+ +

入力要素の制約の検証

+ +

この節では、これまで述べてきたいくつかの属性をテストします。

+ +

簡単な最初のファイル

+ +

簡単な例から始めましょう。― 好きな果物を banana(バナナ)か cherry(サクランボ)から選べる入力欄があるとします。単純なテキストの {{HTMLElement("input")}} とそれに合わせたラベル、送信の {{htmlelement("button")}} から成ります。ソースコードは GitHub の fruit-start.html で、ライブサンプルは次の通りです。

+ +
<form>
+  <label for="choose">banana と cherry のどちらが好き?</label>
+  <input id="choose" name="i_like">
+  <button>Submit</button>
+</form>
+ +
input:invalid {
+  border: 2px dashed red;
+}
+
+input:valid {
+  border: 2px solid black;
+}
+ +

{{EmbedLiveSample("Validation_constraints_on_input_elements", "100%", 80)}}

+ +

始めるにあたって、ハードディスク内の新しいディレクトリーに fruit-start.html のコピーを作成してください。

+ +

required 属性

+ +

required 属性は、使うのがもっとも簡単な HTML5 の検証機能です。入力欄を必須にしたい場合は、この属性を使用して要素をマークすることができます。この属性が設定されていて、要素が {{cssxref(':required')}} にマッチすると、UI疑似クラスとフォームは送信されず、入力が空の場合のエラーメッセージが表示されるでしょう。空のままでは、この入力は不正とみなされ、{{cssxref(':invalid')}} 疑似クラスにマッチします。

+ +

以下のように、required 属性を入力欄に追加しましょう。

+ +
<form>
+  <label for="choose">banana と cherry のどちらが好き? (要入力)</label>
+  <input id="choose" name="i_like" required>
+  <button>Submit</button>
+</form>
+ +

このサンプルファイルの中に含まれている CSS も書いておきましょう。

+ +
input:invalid {
+  border: 2px dashed red;
+}
+
+input:invalid:required {
+  background-image: linear-gradient(to right, pink, lightgreen);
+}
+
+input:valid {
+  border: 2px solid black;
+}
+ +

この CSS によって、入力が妥当でない場合には、入力を赤の破線で境界線を描きますが、入力が妥当な場合には、黒の直線で境界線を描きます。要求された値があり、値が妥当でないときは背景にグラディエーションを追加します。つぎの例の動作を確認しましょう。

+ +

{{EmbedLiveSample("The_required_attribute", "100%", 80)}}

+ +
+

: この例は GitHub の fruit-validation.html で見ることができます (ソースコードも見てください)。

+
+ +

値のないままフォームを送信してみましょう。妥当ではない入力がどのようにフォーカスされるか注意しましょう。デフォルトのエラーメッセージ("Please fill out this field") が表示され、フォームの送信を阻止します。

+ +

required 属性をサポートしている要素にこの属性がある場合、その要素に値があるかないかによって、要素が {{cssxref(':required')}} 疑似クラスに一致するかどうかが決まります。もし {{HTMLElement("input")}} に値がなければ、input は{{cssxref(':invalid')}} 疑似クラスに一致します。

+ +
+

注意: よりよいユーザーエクスペリエンスのために、フォームのフィールドが必要なときにはユーザーに通知しましょう。これはユーザーエクスペリエンスだけに良いというわけではなく、WCAG アクセシビリティ ガイドラインで求められています。また、あなたが本当に必要とする場合にのみ必須にしましょう。例えばあなたは誰かの性別や肩書などの情報は本当に必要でしょうか?

+
+ +

正規表現での検証

+ +

もう一つとてもよく使われる機能は pattern 属性で、値として正規表現を取ります。正規表現 (regex) はテキスト文字列の中の文字の組み合わせに一致させるために使うことができ、フォームの検証には理想的です (JavaScript と同様に様々な利用ができます) 。

+ +

正規表現はかなり複雑です。このモジュールでは正規表現のすべてを説明する意図はありません。いくつかの例を挙げますのでどのように動作するか基本的なアイディアを把握してください。

+ + + +

正規表現には多くの組合せがあるので例はここまでとする。完全な一覧や多くの例は、正規表現ドキュメントを参照してください。

+ +

使用例を実装しましょう。HTML を更新して pattern 属性を追加しましょう:

+ +
<form>
+  <label for="choose">banana と cherry のどちらが好き?</label>
+  <input id="choose" name="i_like" required pattern="[Bb]anana|[Cc]herry">
+  <button>Submit</button>
+</form>
+ +
input:invalid {
+  border: 2px dashed red;
+}
+
+input:valid {
+  border: 2px solid black;
+}
+ +

これは下記の更新があります。次のものを使ってみてください:

+ +

{{EmbedLiveSample("Validating_against_a_regular_expression", "100%", 80)}}

+ +
+

: GitHub の fruit-pattern.html でライブサンプルを見ることができます(ソースコードも見てください)

+
+ +

この例では、{{HTMLElement("input")}} 要素は "banana"、"Banana"、"cherry" または "Cherry" という 4 つの文字列値のうち 1 つを受け付けます。正規表現は大文字小文字を区別しますが、中括弧にはさまれた"Aa"のパターンを使って小文字と同様に先頭が大文字のバージョンをサポートします。

+ +

この時点で、pattern 属性の中の値を以前に見たいくつかの例と同じ値に変更してみて、入力欄が有効になるように入力する値がどのように影響するかを確認してください。自分で考えた値も書いてみて、どのようになるか確認しましょう。果物に関する値を可能にすれば、例が分かりやすくなります。

+ +

もし {{HTMLElement("input")}} の空ではない値が正規表現パターンに一致しなかった場合、この input は {{cssxref(':invalid')}} 疑似クラスに一致します。

+ +
+

メモ: {{HTMLElement("input")}} 要素の型によっては、検証のために pattern 属性が必要ないことがあります。例えば email 型を指定すると、入力された文字列を、妥当な形式のメールアドレスまたは、 multiple 属性がある場合はカンマで区切られたメールアドレスのリストであることを確認する正規表現で検証します。

+
+ +
+

メモ: {{HTMLElement("textarea")}} 要素は pattern 属性に対応していません。

+
+ +

入力欄の長さの制約

+ +

あなたが、{{HTMLElement("input")}} または {{HTMLElement("textarea")}} によって作成してすべてのテキストフィールドで文字数を制限したいときには minlength 属性と maxlength 属性が使用できます。フィールドが値をもっており、その文字数が minlength の値より少ないか、文字数が maxlength の値より大きい場合は、フィールドは不正です。

+ +

ブラウザーはよくテキストフィールドに期待している以上に入力させないことがあります。単に maxlength を使うよりも良いユーザーエクスペリエンスは、入力文字数のフィードバックを提供してサイズ以下でコンテンツを編集できるようにもしておくことです。例えば、Twitter の文字入力の制限があります。これは JavaScript と maxlength を使った解決策の組合せで実現できます。

+ +

入力欄の値に制約を加える

+ +

数値のフィールド (例えば <input type="number">) の場合、min 属性と max 属性によって入力に制限を加えられます。もしそのフィールドの値がこの範囲を超える場合、そのフィールドは妥当ではありません。

+ +

他の例を見てみましょう。fruit-start.html ファイルの新しいコピーを作成してください。

+ +

では、<body> 要素の中身を削除して、以下のように置き換えてください。

+ +
<form>
+  <div>
+    <label for="choose">banana と cherry のどちらが好き?</label>
+    <input type="text" id="choose" name="i_like" required minlength="6" maxlength="6">
+  </div>
+  <div>
+    <label for="number">どのくらい要ります?</label>
+    <input type="number" id="number" name="amount" value="1" min="1" max="10">
+  </div>
+  <div>
+    <button>Submit</button>
+  </div>
+</form>
+ + + +
input:invalid {
+  border: 2px dashed red;
+}
+
+input:valid {
+  border: 2px solid black;
+}
+
+div {
+  margin-bottom: 10px;
+}
+ +

例をライブで実行してみましょう。

+ +

{{EmbedLiveSample("Constraining_the_length_of_your_entries", "100%", 100)}}

+ +
+

: GitHub の fruit-length.html でライブサンプルを見ることができます(ソースコードも見てください)

+
+ +
+

: <input type="number"> (及び rangedate のような他の型)は step 属性を取ることもでき、入力コントロール(数値の増加・減少ボタンなど)を使用するときに上げ下げすることができる値の刻みを設定することができます。上の例では step 属性を入れていませんので、既定値の 1 となります。つまり 3.2 のような浮動小数でも、不正になります。

+
+ +

サンプル全体

+ +

HTML の内蔵検証機能の使い方を示す例の全体を示します。まずは HTML から:

+ +
<form>
+  <p>
+    <fieldset>
+      <legend>Do you have a driver's license?<abbr title="This field is mandatory" aria-label="required">*</abbr></legend>
+      <!-- While only one radio button in a same-named group can be selected at a time,
+           and therefore only one radio button in a same-named group having the "required"
+           attribute suffices in making a selection a requirement -->
+      <input type="radio" required name="driver" id="r1" value="yes"><label for="r1">Yes</label>
+      <input type="radio" required name="driver" id="r2" value="no"><label for="r2">No</label>
+    </fieldset>
+  </p>
+  <p>
+    <label for="n1">How old are you?</label>
+    <!-- pattern 属性は number 型の入力欄を実装していないものの、pattern
+         属性には対応しているブラウザー向けの代替策として動作できます。
+         なお、pattern 属性に対応しているブラウザーでは、number 型の入力欄
+         で使用すると暗黙に失敗します。
+         ここでは代替策としての使い方のみです。-->
+    <input type="number" min="12" max="120" step="1" id="n1" name="age"
+           pattern="\d+">
+  </p>
+  <p>
+    <label for="t1">What's your favorite fruit?<abbr title="This field is mandatory" aria-label="required">*</abbr></label>
+    <input type="text" id="t1" name="fruit" list="l1" required
+           pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range">
+    <datalist id="l1">
+      <option>Banana</option>
+      <option>Cherry</option>
+      <option>Apple</option>
+      <option>Strawberry</option>
+      <option>Lemon</option>
+      <option>Orange</option>
+    </datalist>
+  </p>
+  <p>
+    <label for="t2">What's your e-mail address?</label>
+    <input type="email" id="t2" name="email">
+  </p>
+  <p>
+    <label for="t3">Leave a short message</label>
+    <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea>
+  </p>
+  <p>
+    <button>Submit</button>
+  </p>
+</form>
+ +

この HTML をスタイル設定する CSS は:

+ +
form {
+  font: 1em sans-serif;
+  max-width: 320px;
+}
+
+p > label {
+  display: block;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="number"],
+textarea,
+fieldset {
+  width : 100%;
+  border: 1px solid #333;
+  box-sizing: border-box;
+}
+
+input:invalid {
+  box-shadow: 0 0 5px 1px red;
+}
+
+input:focus:invalid {
+  box-shadow: none;
+}
+ +

これで次のようにレンダリングされます。

+ +

{{EmbedLiveSample("Full_example", "100%", 420)}}

+ +

入力値と、それをサポートする入力タイプの制約に使える属性の完全なリストは、検証関連の属性を見てください。

+ +
+

: GitHub の fruit-length.html でライブサンプルを見ることができます(ソースコードも見てください)

+
+ +

JavaScript を使用したフォーム検証

+ +

内蔵のエラーメッセージの見かけを制御したい場合や、HTML5 のフォーム検証に対応していないブラウザーに対処したい場合は、JavaScript を使用する必要があります。この節では、このようにするさまざまな方法を見ていきます。

+ +

HTML5 の制約検証 API

+ +

多くのブラウザーが 制約検証API  に対応しています。この API は各フォーム要素で使用できる一連のメソッドやプロパティで構成されています。

+ + + +

制約検証 API には、上記の要素で利用できる、次のプロパティがあります。

+ + + +

制約検証 API には、上記の要素で利用できる、次のメソッドがあります。

+ + + +

独自のエラーメッセージを実装する

+ +

上記の HTML5 の検証制約の例で見てきたように、ユーザーが不正なフォームを送信しようとするたびにブラウザーはエラーメッセージを表示します。このメッセージを表示する方法は、ブラウザーにより異なります。

+ +

これらの自動のメッセージには、2 つの欠点があります。

+ + + +

Example of an error message with Firefox in French on an English page

+ +

これらのメッセージの外見やテキストを変更するには、制約検証 API の最も一般的なユースケースです。この使用法を例で詳しく見てみましょう。

+ +

いくつかの簡単な HTML で開始します (空の HTML ファイルにこれを入力します; もしよければ、fruit-start.html を基礎としてもいいでしょう):

+ +
<form>
+  <label for="mail">私にメールアドレスを教えてください:</label>
+  <input type="email" id="mail" name="mail">
+  <button>Submit</button>
+</form>
+ +

このページに次の JavaScript を追加します:

+ +
const email = document.getElementById("mail");
+
+email.addEventListener("input", function (event) {
+  if (email.validity.typeMismatch) {
+    email.setCustomValidity("I am expecting an e-mail address!");
+  } else {
+    email.setCustomValidity("");
+  }
+});
+ +

ここでメールアドレス入力への参照を保管して、入力値が変更されるたびに制約コードが走るためのイベントリスナーを追加します。

+ +

制約コードの中で、メールアドレス入力の validity.typeMismatch プロパティが trueかどうか、つまり値がメールアドレスの形式のパターンにマッチしていないかを確認します。その場合、カスタムメッセージとともに setCustomValidity() を呼び出して、フォームを送信するときに、送信が失敗してカスタムエラーメッセージが表示されます。

+ +

validity.typeMismatchfalseの場合、空文字で setCustomValidity() メソッドを呼び出します。これは入力が妥当となり、フォームが送信されます。

+ +

次のもので試すことができます:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/form-validation/custom-error-message.html", '100%', 80)}}

+ +
+

: この例は GitHub の custom-error-message.html で見ることができます (ソースコードも見てください)。

+
+ +

制約検証 API の使用例

+ +

これまでほんとうに簡単な例を見てきましたので、少し複雑な独自の検証を作成するために API を使用する方法を見ていきましょう。

+ +

始めに、HTML です。また、次のものに沿ってみてください:

+ +
<form novalidate>
+  <p>
+    <label for="mail">
+      <span>メールアドレスを入力してください。</span>
+      <input type="email" id="mail" name="mail">
+      <span class="error" aria-live="polite"></span>
+    </label>
+  </p>
+  <button>Submit</button>
+</form>
+ +

この簡単なフォームでは、ブラウザーの自動検証を無効にするために novalidate 属性を使用しています。これで、検証を制御するためにスクリプトを使用できます。ただし、これは制約検証 API の対応や CSS の疑似クラス {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}}, {{cssxref(":out-of-range")}} の適用を無効にするわけではありません。つまり、データを送信する前にブラウザーが自動的なフォームの妥当性確認を行わないとしても、あなた自身で確認を行って、フォームの状態に応じたスタイル設定ができます。

+ +

検証する入力は <input type="email">で、これは required(入力必須)で、8文字の minlength があります。これをわれわれのコードで確認して、それぞれカスタムエラーメッセージを表示させてみましょう。

+ +

<span>要素の中にエラーメッセージを表示させようとしています。 <span>にセットされた aria-live 属性は、スクリーンリーダーのような支援技術を使用している人々を含む皆に、独自のエラーメッセージを提示するようにします。

+ +
+

: ここでの要点は、フォームに novalidate 属性をつけると、フォームがエラーメッセージのバブルを表示するのを停止して、その代わりDOM内にカスタムエラーメッセージを選択した方法で表示させられることです。

+
+ +

この CSS はフォームの見栄えを少し良くして、入力データが無効なときの見た目のフィードバックを提供します。

+ +
/* これはサンプルの見栄えをよくするスタイルです */
+body {
+  font: 1em sans-serif;
+  width: 200px;
+  padding: 0;
+  margin : 0;
+}
+
+p * {
+  display: block;
+}
+
+input[type=email]{
+  -webkit-appearance: none;
+  appearance: none;
+
+  width: 100%;
+  border: 1px solid #333;
+  margin: 0;
+
+  font-family: inherit;
+  font-size: 90%;
+
+  box-sizing: border-box;
+}
+
+/* これは不正なフィールド向けのスタイルです */
+input:invalid{
+  border-color: #900;
+  background-color: #FDD;
+}
+
+input:focus:invalid {
+  outline: none;
+}
+
+/* これはエラーメッセージ向けのスタイルです */
+.error {
+  width  : 100%;
+  padding: 0;
+
+  font-size: 80%;
+  color: white;
+  background-color: #900;
+  border-radius: 0 0 5px 5px;
+
+  box-sizing: border-box;
+}
+
+.error.active {
+  padding: 0.3em;
+}
+ +

以下の JavaScript コードは独自のエラー検証を制御します。

+ +
// DOM ノードの選択法はたくさんあります。ここではフォーム自体、メールアドレス
+// 入力ボックス、そしてエラーメッセージを配置する span 要素を取得しています。
+const form  = document.getElementsByTagName('form')[0];
+
+const email = document.getElementById('mail');
+const error = document.querySelector('#mail + span.error');
+
+email.addEventListener("input", function (event) {
+  // ユーザーが何かを入力するたびに、メールアドレスのフィールドが妥当かを
+  // 確認します。
+  if (email.validity.valid) {
+    // エラーメッセージを表示している場合に、フィールドが妥当になれば
+    // エラーメッセージを取り除きます。
+    error.innerHTML = ""; // メッセージの内容物をリセットします
+    error.className = "error"; // メッセージの表示状態をリセットします
+  } else {
+    // If there is still an error, show the correct error
+    showError();
+  }
+});
+
+form.addEventListener("submit", function (event) {
+  // ユーザーがデータを送信しようとするたびに、メールアドレスの
+  // フィールドが妥当かをチェックします。
+  if (!email.validity.valid) {
+
+    // フィールドが妥当ではない場合、独自のエラーメッセージを
+    // 表示します。
+    showError();
+    // また、イベントをキャンセルしてフォームの送信を止めます。
+    event.preventDefault();
+  }
+});
+
+function showError() {
+  if(email.validity.valueMissing) {
+    // If the field is empty
+    // display the following error message.
+    emailError.textContent = 'You need to enter an e-mail address.';
+  } else if(email.validity.typeMismatch) {
+    // If the field doesn't contain an email address
+    // display the following error message.
+    emailError.textContent = 'Entered value needs to be an e-mail address.';
+  } else if(email.validity.tooShort) {
+    // If the data is too short
+    // display the following error message.
+    emailError.textContent = `Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
+  }
+
+  // Set the styling appropriately
+  emailError.className = 'error active';
+}
+ +

コメントがよく説明していますが、簡単にいうと:

+ + + +

こちらが実際の結果です。

+ +

{{EmbedGHLiveSample("learning-area/html/forms/form-validation/detailed-custom-validation.html", '100%', 150)}}

+ +
+

: GitHub の detailed-custom-validation.html に例があります(ソースコード見てください)

+
+ +

制約検証 API はフォーム検証を制御するための強力なツールであり、HTML および CSS のみで検証を行うよりもはるかにユーザーインターフェイスをコントロールできます。

+ +
+

: さらなる情報は、制約検証ガイド制約検証 API リファレンスを見てください。

+
+ +

組み込み API を使用しないフォーム検証

+ +

古いブラウザーやカスタムコントロールにおいて、制約検証 API を使用できない (または使用したくない)ことがあるでしょう。このような場合でも、フォームを検証するために JavaScript が使用できます。フォームを検証には、実際のデータの検証よりもユーザーインターフェイスの疑問が多くなります。

+ +

フォームを検証するために、あなたはいくつかの疑問を考えなければなりません。

+ +
+
どのような検証を実施するべきか
+
どのようにデータを検証するかを決めなければなりません。文字列演算、型変換、正規表現など。これはあなた次第です。フォームのデータは常にテキストであり、スクリプトには常に文字列として渡されることを忘れないようにしてください。
+
フォームが妥当でない場合に何をするべきか
+
これは明らかにユーザーインターフェイスの問題です。フォームがどのように動作するかを決めなければなりません。どのような場合でもフォームのデータを送信しますか?エラー状態の入力欄を強調しますか?エラーメッセージを表示しますか?
+
ユーザーが不正なデータを修正することをどのように支援できるか
+
ユーザーの不満を軽減するためには、ユーザーに入力内容の修正を案内するために、できるだけ多くの役立つ情報を提供することがとても重要です。明確なエラーメッセージはもちろん、ユーザーが何を求められているか理解できるように前向きの提案をするべきです。フォーム検証のユーザーインターフェイスの要件について深く知りたいのであれば、ぜひ読むべきである有用な記事があります(英語)。 + +
+
+ +

制約検証 API を使用しない例

+ +

これまでのことを説明するため、古いブラウザーでも動作するように前出のサンプルを作り直してみましょう。

+ +

ご覧の通り、HTML はほとんど同じであり、HTML5 の validation機能を取り除いただけです

+ +
<form>
+  <p>
+    <label for="mail">
+        <span>メールアドレスを入力してください。</span>
+        <input type="text" class="mail" id="mail" name="mail">
+        <span class="error" aria-live="polite"></span>
+    </label>
+  <p>
+  <!-- 一部の古いブラウザーでは button 要素で、type 属性に明示的に
+       submit を設定する必要があります。-->
+  <button type="submit">Submit</button>
+</form>
+ +

同様に、CSS も大きく変更する必要はありません。{{cssxref(":invalid")}} 疑似クラスから実クラスへの変更と、Internet Explorer 6 で動作しない属性セレクターの使用を避けただけです。

+ +
/* これはサンプルの見栄えをよくするスタイルです */
+body {
+  font: 1em sans-serif;
+  padding: 0;
+  margin : 0;
+}
+
+form {
+  max-width: 200px;
+}
+
+p * {
+  display: block;
+}
+
+input.mail {
+  -webkit-appearance: none;
+
+  width: 100%;
+  border: 1px solid #333;
+  margin: 0;
+
+  font-family: inherit;
+  font-size: 90%;
+
+  box-sizing: border-box;
+}
+
+/* これは不正なフィールド向けのスタイルです */
+input.invalid{
+  border-color: #900;
+  background-color: #FDD;
+}
+
+input:focus.invalid {
+  outline: none;
+}
+
+/* これはエラーメッセージ向けのスタイルです */
+.error {
+  width  : 100%;
+  padding: 0;
+
+  font-size: 80%;
+  color: white;
+  background-color: #900;
+  border-radius: 0 0 5px 5px;
+  box-sizing: border-box;
+}
+
+.error.active {
+  padding: 0.3em;
+}
+ +

JavaScript コードでは大きな変更があり、多くの面倒な作業が必要です。

+ +
// 古いブラウザーで DOM ノードを選択する方法は少ない
+const form  = document.getElementsByTagName('form')[0];
+const email = document.getElementById('mail');
+
+// 以下は DOM 内で次の兄弟要素にたどり着くための技です。
+// これは容易に無限ループになることがあるため、危険です。
+// 新しいブラウザーでは、element.nextElementSibling を使用しましょう。
+let error = email;
+while ((error = error.nextSibling).nodeType != 1);
+
+// HTML5 仕様書より
+const emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
+
+// 多くの古いブラウザーは addEventListener メソッドをサポートしていません。
+// 以下はこれを扱うためのシンプルな方法です。なお唯一の方法ではありません。
+function addEvent(element, event, callback) {
+  let previousEventCallBack = element["on"+event];
+  element["on"+event] = function (e) {
+    const output = callback(e);
+
+    // `false` を返すコールバックはコールバックチェーンを止めて、
+    // イベントコールバックの実行を中断します。
+    if (output === false) return false;
+
+    if (typeof previousEventCallBack === 'function') {
+      output = previousEventCallBack(e);
+      if(output === false) return false;
+    }
+  }
+};
+
+// ここから検証制約の再構築ができます。
+// CSS の疑似クラスに頼ることはできないため、メールアドレスフィールドで
+// valid/invalid クラスを明示的に設定しなければなりません。
+addEvent(window, "load", function () {
+  // ここで、フィールドが空かを確認しています (フィールドは必須入力ではありません)
+  // 空でなければ、内容部が適切な電子メールアドレスかを確認します。
+  const test = email.value.length === 0 || emailRegExp.test(email.value);
+
+  email.className = test ? "valid" : "invalid";
+});
+
+// ユーザーがフィールドに入力したときに、何をするかを定義します。
+addEvent(email, "input", function () {
+  const test = email.value.length === 0 || emailRegExp.test(email.value);
+  if (test) {
+    email.className = "valid";
+    error.innerHTML = "";
+    error.className = "error";
+  } else {
+    email.className = "invalid";
+  }
+});
+
+// ユーザーがデータを送信しようとしたときに何をするかを定義します。
+addEvent(form, "submit", function () {
+  const test = email.value.length === 0 || emailRegExp.test(email.value);
+
+  if (!test) {
+    email.className = "invalid";
+    error.innerHTML = "I expect an e-mail, darling!";
+    error.className = "error active";
+
+    // 一部の古いブラウザーは event.reventDefault() メソッドをサポートしていません。
+    return false;
+  } else {
+    email.className = "valid";
+    error.innerHTML = "";
+    error.className = "error";
+  }
+});
+ +

結果は以下のようになります。

+ +

{{EmbedLiveSample("An_example_that_doesnt_use_the_constraint_validation_API", "100%", 130)}}

+ +

ご覧の通り、自分でで検証システムを構築するのは大変なことではありません。難しいのはクロスプラットフォームで、かつ作成するであろうあらゆるフォームで使用できる汎用的なものにすることです。フォーム検証を行うために利用できる、Validate.js のような多くのライブラリがあります。

+ +

まとめ

+ +

クライアント側のフォーム検証は、カスタムスタイル設定やエラーメッセージには複雑な JavaScript を必要としませんが、ユーザーについては注意深く考えることが必要です。ユーザーが正しいデータを入力できるよう支援することを、常に忘れないでください。最後に、以下のことを必ず行ってください。

+ + + +

フォームが正しく埋められたことをチェックしたら、送信することができます。次のデータ送信でカバーします。

+ +

{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/example_1/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_1/index.html new file mode 100644 index 0000000000..1515dc573f --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_1/index.html @@ -0,0 +1,415 @@ +--- +title: 例 1 +slug: Learn/Forms/How_to_build_custom_form_widgets/Example_1 +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_1 +--- +

これは、カスタムフォームウィジェットの作成方法を説明する最初のコード例です。

+ +

Basic state

+ +

HTML

+ +
<div class="select">
+  <span class="value">Cherry</span>
+  <ul class="optList hidden">
+    <li class="option">Cherry</li>
+    <li class="option">Lemon</li>
+    <li class="option">Banana</li>
+    <li class="option">Strawberry</li>
+    <li class="option">Apple</li>
+  </ul>
+</div>
+ +

CSS

+ +
/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+
+ +

Result for basic state

+ +
{{ EmbedLiveSample('Basic_state', 120, 130) }}
+ +

Active state

+ +

HTML

+ +
<div class="select active">
+  <span class="value">Cherry</span>
+  <ul class="optList hidden">
+    <li class="option">Cherry</li>
+    <li class="option">Lemon</li>
+    <li class="option">Banana</li>
+    <li class="option">Strawberry</li>
+    <li class="option">Apple</li>
+  </ul>
+</div>
+ +

CSS

+ +
/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

Result for active state

+ +
{{ EmbedLiveSample('Active_state', 120, 130) }}
+ +

Open state

+ +

HTML

+ +
<div class="select active">
+  <span class="value">Cherry</span>
+  <ul class="optList">
+    <li class="option highlight">Cherry</li>
+    <li class="option">Lemon</li>
+    <li class="option">Banana</li>
+    <li class="option">Strawberry</li>
+    <li class="option">Apple</li>
+  </ul>
+</div>
+ +

CSS

+ +
/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0, 0, 0, .45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFF;
+}
+ +

Result for open state

+ +
{{ EmbedLiveSample('Open_state', 120, 130) }}
diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/example_2/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_2/index.html new file mode 100644 index 0000000000..7a547909ce --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_2/index.html @@ -0,0 +1,212 @@ +--- +title: 例 2 +slug: Learn/Forms/How_to_build_custom_form_widgets/Example_2 +tags: + - Forms + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_2 +--- +

これは、カスタムフォームウィジェットの作成方法を説明する2番目の例です。

+ +

JS

+ +

HTML コンテンツ

+ +
<form class="no-widget">
+  <select name="myFruit">
+      <option>Cherry</option>
+      <option>Lemon</option>
+      <option>Banana</option>
+      <option>Strawberry</option>
+      <option>Apple</option>
+  </select>
+
+  <div class="select">
+    <span class="value">Cherry</span>
+    <ul class="optList hidden">
+      <li class="option">Cherry</li>
+      <li class="option">Lemon</li>
+      <li class="option">Banana</li>
+      <li class="option">Strawberry</li>
+      <li class="option">Apple</li>
+    </ul>
+  </div>
+<form>
+
+ +

CSS コンテンツ

+ +
.widget select,
+.no-widget .select {
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+
+/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

JavaScript コンテンツ

+ +
window.addEventListener("load", function () {
+  var form = document.querySelector('form');
+
+  form.classList.remove("no-widget");
+  form.classList.add("widget");
+});
+ +

JS の結果

+ +

{{ EmbedLiveSample('JS', 120, 130) }}

+ +

No JS

+ +

HTML コンテンツ

+ +
<form class="no-widget">
+  <select name="myFruit">
+      <option>Cherry</option>
+      <option>Lemon</option>
+      <option>Banana</option>
+      <option>Strawberry</option>
+      <option>Apple</option>
+  </select>
+
+  <div class="select">
+    <span class="value">Cherry</span>
+    <ul class="optList hidden">
+      <li class="option">Cherry</li>
+      <li class="option">Lemon</li>
+      <li class="option">Banana</li>
+      <li class="option">Strawberry</li>
+      <li class="option">Apple</li>
+    </ul>
+  </div>
+<form>
+ +

CSS コンテンツ

+ +
.widget select,
+.no-widget .select {
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+ +

No JS の結果

+ +

{{ EmbedLiveSample('No_JS', 120, 130) }}

diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/example_3/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_3/index.html new file mode 100644 index 0000000000..ac3763cb80 --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_3/index.html @@ -0,0 +1,246 @@ +--- +title: 例 3 +slug: Learn/Forms/How_to_build_custom_form_widgets/Example_3 +tags: + - Forms + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_3 +--- +

これは、カスタムフォームウィジェットの作成方法を説明する3番目の例です。

+ +

状態を変更する

+ +

HTML コンテンツ

+ +
<form class="no-widget">
+  <select name="myFruit" tabindex="-1">
+      <option>Cherry</option>
+      <option>Lemon</option>
+      <option>Banana</option>
+      <option>Strawberry</option>
+      <option>Apple</option>
+  </select>
+
+  <div class="select" tabindex="0">
+    <span class="value">Cherry</span>
+    <ul class="optList hidden">
+      <li class="option">Cherry</li>
+      <li class="option">Lemon</li>
+      <li class="option">Banana</li>
+      <li class="option">Strawberry</li>
+      <li class="option">Apple</li>
+    </ul>
+  </div>
+</form>
+ +

CSS コンテンツ

+ +
.widget select,
+.no-widget .select {
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+
+/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

JavaScript コンテンツ

+ +
// ------- //
+// HELPERS //
+// ------- //
+
+NodeList.prototype.forEach = function (callback) {
+  Array.prototype.forEach.call(this, callback);
+}
+
+// -------------------- //
+// Function definitions //
+// -------------------- //
+
+function deactivateSelect(select) {
+  if (!select.classList.contains('active')) return;
+
+  var optList = select.querySelector('.optList');
+
+  optList.classList.add('hidden');
+  select.classList.remove('active');
+}
+
+function activeSelect(select, selectList) {
+  if (select.classList.contains('active')) return;
+
+  selectList.forEach(deactivateSelect);
+  select.classList.add('active');
+};
+
+function toggleOptList(select, show) {
+  var optList = select.querySelector('.optList');
+
+  optList.classList.toggle('hidden');
+}
+
+function highlightOption(select, option) {
+  var optionList = select.querySelectorAll('.option');
+
+  optionList.forEach(function (other) {
+    other.classList.remove('highlight');
+  });
+
+  option.classList.add('highlight');
+};
+
+// ------------- //
+// Event binding //
+// ------------- //
+
+window.addEventListener("load", function () {
+  var form = document.querySelector('form');
+
+  form.classList.remove("no-widget");
+  form.classList.add("widget");
+});
+
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  selectList.forEach(function (select) {
+    var optionList = select.querySelectorAll('.option');
+
+    optionList.forEach(function (option) {
+      option.addEventListener('mouseover', function () {
+        highlightOption(select, option);
+      });
+    });
+
+    select.addEventListener('click', function (event) {
+      toggleOptList(select);
+    },  false);
+
+    select.addEventListener('focus', function (event) {
+      activeSelect(select, selectList);
+    });
+
+    select.addEventListener('blur', function (event) {
+      deactivateSelect(select);
+    });
+  });
+});
+ +

結果

+ +

{{ EmbedLiveSample('Change_states') }}

diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/example_4/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_4/index.html new file mode 100644 index 0000000000..51fa53c27a --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_4/index.html @@ -0,0 +1,296 @@ +--- +title: 例 4 +slug: Learn/Forms/How_to_build_custom_form_widgets/Example_4 +tags: + - Advanced + - Example + - Forms + - Guide + - HTML + - Web +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_4 +--- +

これは、カスタムフォームウィジェットの作成方法を説明する4番目の例です。

+ +

状態を変更する

+ +

HTML コンテンツ

+ +
<form class="no-widget">
+  <select name="myFruit">
+    <option>Cherry</option>
+    <option>Lemon</option>
+    <option>Banana</option>
+    <option>Strawberry</option>
+    <option>Apple</option>
+  </select>
+
+  <div class="select">
+    <span class="value">Cherry</span>
+    <ul class="optList hidden">
+      <li class="option">Cherry</li>
+      <li class="option">Lemon</li>
+      <li class="option">Banana</li>
+      <li class="option">Strawberry</li>
+      <li class="option">Apple</li>
+    </ul>
+  </div>
+</form>
+ +

CSS コンテンツ

+ +
.widget select,
+.no-widget .select {
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+
+/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

JavaScript コンテンツ

+ +
// ------- //
+// HELPERS //
+// ------- //
+
+NodeList.prototype.forEach = function (callback) {
+  Array.prototype.forEach.call(this, callback);
+}
+
+// -------------------- //
+// Function definitions //
+// -------------------- //
+
+function deactivateSelect(select) {
+  if (!select.classList.contains('active')) return;
+
+  var optList = select.querySelector('.optList');
+
+  optList.classList.add('hidden');
+  select.classList.remove('active');
+}
+
+function activeSelect(select, selectList) {
+  if (select.classList.contains('active')) return;
+
+  selectList.forEach(deactivateSelect);
+  select.classList.add('active');
+};
+
+function toggleOptList(select, show) {
+  var optList = select.querySelector('.optList');
+
+  optList.classList.toggle('hidden');
+}
+
+function highlightOption(select, option) {
+  var optionList = select.querySelectorAll('.option');
+
+  optionList.forEach(function (other) {
+    other.classList.remove('highlight');
+  });
+
+  option.classList.add('highlight');
+};
+
+function updateValue(select, index) {
+  var nativeWidget = select.previousElementSibling;
+  var value = select.querySelector('.value');
+  var optionList = select.querySelectorAll('.option');
+
+  nativeWidget.selectedIndex = index;
+  value.innerHTML = optionList[index].innerHTML;
+  highlightOption(select, optionList[index]);
+};
+
+function getIndex(select) {
+  var nativeWidget = select.previousElementSibling;
+
+  return nativeWidget.selectedIndex;
+};
+
+// ------------- //
+// Event binding //
+// ------------- //
+
+window.addEventListener("load", function () {
+  var form = document.querySelector('form');
+
+  form.classList.remove("no-widget");
+  form.classList.add("widget");
+});
+
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  selectList.forEach(function (select) {
+    var optionList = select.querySelectorAll('.option');
+
+    optionList.forEach(function (option) {
+      option.addEventListener('mouseover', function () {
+        highlightOption(select, option);
+      });
+    });
+
+    select.addEventListener('click', function (event) {
+      toggleOptList(select);
+    });
+
+    select.addEventListener('focus', function (event) {
+      activeSelect(select, selectList);
+    });
+
+    select.addEventListener('blur', function (event) {
+      deactivateSelect(select);
+    });
+  });
+});
+
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  selectList.forEach(function (select) {
+    var optionList = select.querySelectorAll('.option'),
+        selectedIndex = getIndex(select);
+
+    select.tabIndex = 0;
+    select.previousElementSibling.tabIndex = -1;
+
+    updateValue(select, selectedIndex);
+
+    optionList.forEach(function (option, index) {
+      option.addEventListener('click', function (event) {
+        updateValue(select, index);
+      });
+    });
+
+    select.addEventListener('keyup', function (event) {
+      var length = optionList.length,
+          index  = getIndex(select);
+
+      if (event.keyCode === 40 && index < length - 1) { index++; }
+      if (event.keyCode === 38 && index > 0) { index--; }
+
+      updateValue(select, index);
+    });
+  });
+});
+ +

結果

+ +

{{ EmbedLiveSample('Change_states') }}

diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/example_5/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_5/index.html new file mode 100644 index 0000000000..4bad8016bb --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/example_5/index.html @@ -0,0 +1,289 @@ +--- +title: 例 5 +slug: Learn/Forms/How_to_build_custom_form_widgets/Example_5 +tags: + - Forms + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_5 +--- +

これが、カスタムフォームウィジェットの作成方法を説明する最後の例です。

+ +

状態を変更する

+ +

HTML コンテンツ

+ +
<form class="no-widget">
+  <select name="myFruit">
+    <option>Cherry</option>
+    <option>Lemon</option>
+    <option>Banana</option>
+    <option>Strawberry</option>
+    <option>Apple</option>
+  </select>
+
+  <div class="select" role="listbox">
+    <span class="value">Cherry</span>
+    <ul class="optList hidden" role="presentation">
+      <li class="option" role="option" aria-selected="true">Cherry</li>
+      <li class="option" role="option">Lemon</li>
+      <li class="option" role="option">Banana</li>
+      <li class="option" role="option">Strawberry</li>
+      <li class="option" role="option">Apple</li>
+    </ul>
+  </div>
+</form>
+ +

CSS コンテンツ

+ +
.widget select,
+.no-widget .select {
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+
+/* --------------- */
+/* Required Styles */
+/* --------------- */
+
+.select {
+  position: relative;
+  display : inline-block;
+}
+
+.select.active,
+.select:focus {
+  box-shadow: 0 0 3px 1px #227755;
+  outline: none;
+}
+
+.select .optList {
+  position: absolute;
+  top     : 100%;
+  left    : 0;
+}
+
+.select .optList.hidden {
+  max-height: 0;
+  visibility: hidden;
+}
+
+/* ------------ */
+/* Fancy Styles */
+/* ------------ */
+
+.select {
+  font-size   : 0.625em; /* 10px */
+  font-family : Verdana, Arial, sans-serif;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : 0.2em solid #000; /* 2px */
+  border-radius : 0.4em; /* 4px */
+
+  box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  background : #F0F0F0;
+  background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+
+  white-space   : nowrap;
+  text-overflow : ellipsis;
+  vertical-align: top;
+}
+
+.select:after {
+  content : "▼";
+  position: absolute;
+  z-index : 1;
+  height  : 100%;
+  width   : 2em; /* 20px */
+  top     : 0;
+  right   : 0;
+
+  padding-top : .1em;
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  text-align : center;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+}
+
+.select .optList {
+  z-index : 2;
+
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  background: #f0f0f0;
+  border: .2em solid #000;
+  border-top-width : .1em;
+  border-radius: 0 0 .4em .4em;
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4);
+
+  -moz-box-sizing : border-box;
+  box-sizing : border-box;
+
+  min-width : 100%;
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+.select .option {
+  padding: .2em .3em;
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

JavaScript コンテンツ

+ +
// ------- //
+// HELPERS //
+// ------- //
+
+NodeList.prototype.forEach = function (callback) {
+  Array.prototype.forEach.call(this, callback);
+}
+
+// -------------------- //
+// Function definitions //
+// -------------------- //
+
+function deactivateSelect(select) {
+  if (!select.classList.contains('active')) return;
+
+  var optList = select.querySelector('.optList');
+
+  optList.classList.add('hidden');
+  select.classList.remove('active');
+}
+
+function activeSelect(select, selectList) {
+  if (select.classList.contains('active')) return;
+
+  selectList.forEach(deactivateSelect);
+  select.classList.add('active');
+};
+
+function toggleOptList(select, show) {
+  var optList = select.querySelector('.optList');
+
+  optList.classList.toggle('hidden');
+}
+
+function highlightOption(select, option) {
+  var optionList = select.querySelectorAll('.option');
+
+  optionList.forEach(function (other) {
+    other.classList.remove('highlight');
+  });
+
+  option.classList.add('highlight');
+};
+
+function updateValue(select, index) {
+  var nativeWidget = select.previousElementSibling;
+  var value = select.querySelector('.value');
+  var optionList = select.querySelectorAll('.option');
+
+  optionList.forEach(function (other) {
+    other.setAttribute('aria-selected', 'false');
+  });
+
+  optionList[index].setAttribute('aria-selected', 'true');
+
+  nativeWidget.selectedIndex = index;
+  value.innerHTML = optionList[index].innerHTML;
+  highlightOption(select, optionList[index]);
+};
+
+function getIndex(select) {
+  var nativeWidget = select.previousElementSibling;
+
+  return nativeWidget.selectedIndex;
+};
+
+// ------------- //
+// Event binding //
+// ------------- //
+
+window.addEventListener("load", function () {
+  var form = document.querySelector('form');
+
+  form.classList.remove("no-widget");
+  form.classList.add("widget");
+});
+
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  selectList.forEach(function (select) {
+    var optionList = select.querySelectorAll('.option'),
+        selectedIndex = getIndex(select);
+
+    select.tabIndex = 0;
+    select.previousElementSibling.tabIndex = -1;
+
+    updateValue(select, selectedIndex);
+
+    optionList.forEach(function (option, index) {
+      option.addEventListener('mouseover', function () {
+        highlightOption(select, option);
+      });
+
+      option.addEventListener('click', function (event) {
+        updateValue(select, index);
+      });
+    });
+
+    select.addEventListener('click', function (event) {
+      toggleOptList(select);
+    });
+
+    select.addEventListener('focus', function (event) {
+      activeSelect(select, selectList);
+    });
+
+    select.addEventListener('blur', function (event) {
+      deactivateSelect(select);
+    });
+
+    select.addEventListener('keyup', function (event) {
+      var length = optionList.length,
+          index  = getIndex(select);
+
+      if (event.keyCode === 40 && index < length - 1) { index++; }
+      if (event.keyCode === 38 && index > 0) { index--; }
+
+      updateValue(select, index);
+    });
+  });
+});
+
+ +

結果

+ +

{{ EmbedLiveSample('Change_states') }}

diff --git a/files/ja/learn/forms/how_to_build_custom_form_widgets/index.html b/files/ja/learn/forms/how_to_build_custom_form_widgets/index.html new file mode 100644 index 0000000000..7bbd20b511 --- /dev/null +++ b/files/ja/learn/forms/how_to_build_custom_form_widgets/index.html @@ -0,0 +1,901 @@ +--- +title: カスタムフォームコントロールの作成方法 +slug: Learn/Forms/How_to_build_custom_form_widgets +tags: + - Advanced + - Example + - Forms + - Guide + - HTML + - Web +translation_of: Learn/Forms/How_to_build_custom_form_controls +--- +
{{LearnSidebar}}
+ +

HTML フォームで使用可能なコントロールだけでは十分でない場合が多くあります。例えば、{{HTMLElement("select")}} 要素のようなコントロールに高度なスタイル設定を行いたい場合や、独自の動作を提供したい場合は、あなた独自のコントロールを作成するしかありません。

+ +

本記事では、そのようなコントロールの作り方を見ていきます。その目的のため、次の例に取り組みます: {{HTMLElement("select")}} 要素の再構築です。このほかに独自コントロール作成をどういう方法でするか、いつするか、またそれが意味をなすのかや、コントロール作成が必須なときに何に気をつけるべきかを扱います。

+ +
+

注記: ここではコントロールの構築に注目しており、汎用かつ再利用可能なコードの作成法は見ていきません。それには JavaScript の重要なコードや未知のコンテキストでの DOM 操作が組み合わされており、本記事の対象から外れます。

+
+ +

デザイン、構造、セマンティクス

+ +

カスタムコントロールを作成する前に、何をしたいかをはっきりと理解することから始めるべきです。これはあなたの貴重な時間を節約するでしょう。特に、コントロールの全状態を明確に定義することが重要です。これを行うには、状態や動作がよく知られている既存のコントロールからスタートするとよいでしょう。この結果、簡単に可能な限りの模倣を行えます。

+ +

本記事の例では、{{HTMLElement("select")}} 要素を再構築します。以下が、私たちが実現したい成果です:

+ +

The three states of a select box

+ +

このスクリーンショットでは、コントロールの主要な状態 3 つを示しています: 通常状態 (左)、アクティブ状態 (中央)、そして開いた状態 (右) です。

+ +

動作の点では、ネイティブな HTML用要素を再作成します。このため、ネイティブ HTML要素と同様な動作や意味を持たせるべきです。独自のコントロールもネイティブコントロールと同様に、キーボードだけでなくマウスでも使用できるように、またスクリーンリーダーに理解できるようにしたいと考えます。コントロールがどのように各状態に達するかを定義することから始めましょう:

+ +
+
コントロールは以下のときに通常状態になります:
+
+
    +
  • ページを読み込む
  • +
  • コントロールはアクティブであったが、ユーザーがコントロール以外のどこかをクリックした
  • +
  • コントロールはアクティブであったが、キーボードを使用して別のコントロールにフォーカスを移した (例 Tab キー)
  • +
+
+
コントロールは以下のときにアクティブ状態になります:
+
+
    +
  • ユーザーがコントロール上でクリックする
  • +
  • ユーザーが Tab キーを押下して、コントロールがフォーカスを得る
  • +
  • コントロールが開いた状態で、ユーザーがコントロールをクリックする
  • +
+
+
コントロールは以下のときに開いた状態になります:
+
+
    +
  • コントロールが開いた状態ではないときに、ユーザーがコントロールをクリックした
  • +
+
+
+ +

状態をどのように変えるかを理解したら、コントロールの値をどのように変えるかの定義が重要になります:

+ +
+
以下のときに値が変わります:
+
+
    +
  • コントロールが開いた状態であるときに、ユーザーが選択肢をクリックする
  • +
  • コントロールがアクティブ状態であるときに、ユーザーが上下矢印キーを押下する
  • +
+
+
+ +
+
以下のときには値は変わりません:
+
+
    +
  • 最初のオプションが選択済みのときに、ユーザーが上矢印をクリックする
  • +
  • 最後のオプションが選択済みのときに、ユーザーが下矢印をクリックする
  • +
+
+
+ +

最後に、コントロールの選択肢がどのように動作するかを定義しましょう:

+ + + +

この例の用途としては、ここまでです。しかし注意深い読者の方は、いくつかの動作が欠けていることに気づくでしょう。例えば、コントロールが開いた状態であるときにユーザーが Tab キーを押すと何が起きると考えますか? その答えは... 何も起きません。正しい動作は明らかでしょうが、実際は私たちの仕様で定義されていないため、とても見逃されやすいのです。これは、コントロールの動作を設計する人と実装する人が異なるチーム環境で特に当てはまります。

+ +

別のおもしろい例です: コントロールが開いた状態であるときに上下矢印キーを押すと何が起きるのでしょうか? こちらはやや難しくなります。アクティブ状態と開いた状態をまったく別のものと考えるなら、その答えはやはり "何も起きません" です。これは、開いた状態でのキーボードの作用を定義していないためです。一方、アクティブ状態と開いた状態が少し重なると考えるなら、値は替わるかもしれませんがそれに対応して選択肢が強調されることはないでしょう。繰り返しになりますが、これはコントロールが開いた状態の選択肢に対するキーボードの作用を定義していないためです (コントロールが開いた状態で何が起きるかだけを定義しており、その後がないためです)。

+ +

もう少し突っ込んで考えてみます: エスケープキーはどうでしょう? Esc キーを押すと開いた select が閉じます。ネイティブの{{htmlelement('select')}}と同じ機能を提供する場合、キーボードやマウスやスクリーンリーダーへのタッチ、その他あらゆる入力デバイスまで、全てのユーザーにとっての select の動作と全く同じようにふるまうべきです。

+ +

この例では欠けている仕様が明らかですので対処するでしょうが、めずらしい新たなコントロールでは真の問題になり得ます。標準要素では、{{htmlelement('select')}} もその 1 つですが、仕様の作成者は膨大な時間をかけて全てのユースケースの全ての入力デバイスの全ての操作を指定します。新コントロールの作成は簡単ではなく、特にそれが作成されたことのないものの場合は、どのような動作が正しいかについて、わずかなアイデアですら誰も持っていないため簡単ではないです。少なくとも select はこれまでやってきたため、どうふるまうかはわかっています!

+ +

一般的に、新しい操作を設計するのは、標準を作成するに十分なリーチを持った、とても大きな産業プレイヤーだけの選択肢です。例えば、Apple は 2001年に iPod にスクロールホイールを導入しました。完全に新しい操作方法のデバイスを導入するのに成功するマーケットシェアがありましたが、たいていのデバイス会社はそうはいきません。

+ +

新しいユーザーインタラクションを発明しないのがベストです。インタラクションを追加する場合、設計段階で時間を使うのが重要です。動作の定義が貧弱であったり定義もれがあったりした場合、いったんユーザーが使い始めると動作を再定義するのが非常に困難になると思われますので、設計段階に時間をかけることは賢明です。もし疑っているのでしたら、他の人に意見を聞きましょう。また予算を持っているのでしたら、ユーザーテストの実施をためらってはいけません。このプロセスは、UX デザインと呼ばれます。この点について詳しく学びたいのでしたら、以下の役に立つリソースをご覧になるとよいでしょう:

+ + + +
+

注記: さらにほとんどのシステムでは、使用できる選択肢すべてを見るために {{HTMLElement("select")}} 要素を開く手段があります (これは {{HTMLElement("select")}} 要素をマウスでクリックするのと同じです)。これは Windows では Alt + Down  キー で実現できますが、この例では実装しません。しかし、仕組みはすでに click イベント向けに実装されていますので、行うのは簡単です。

+
+ +

HTML の構造とセマンティクスの定義

+ +

コントロールの基本的な機能が決まりましたので、構築を始めるときが来ました。最初のステップはコントロールの HTML 構造の定義と、基本的なセマンティクスの付与です。こちらが、{{HTMLElement("select")}} 要素の再構築に必要な HTML です:

+ +
<!-- これはコントロールの中心的なコンテナです。
+     tabindex 属性は、ユーザーがコントロールにフォーカスを当てられるようにするものです。
+     これを JavaScript で設定する方がよいことは、後で見ていきます。-->
+<div class="select" tabindex="0">
+
+  <!-- このコンテナは、コントロールの現在の値を表示するために使用します。-->
+  <span class="value">Cherry</span>
+
+  <!-- このコンテナは、コントロールで使用できるすべての選択肢を包含します。
+       これはリストですから、ul 要素を使用するとよいでしょう。-->
+  <ul class="optList">
+    <!-- 各々の選択肢は表示される値だけを包含しており、フォームのデータで送信される
+         実際の値を処理する方法は後で見ていきます。-->
+    <li class="option">Cherry</li>
+    <li class="option">Lemon</li>
+    <li class="option">Banana</li>
+    <li class="option">Strawberry</li>
+    <li class="option">Apple</li>
+  </ul>
+
+</div>
+ +

クラス名の使い方に注目してください。これらは基盤となる実際の HTML とは関係なく、フォームに関するそれぞれの部分を示します。これは CSS や JavaScript を強固な HTML の構造と結びつけないようにするために重要であり、そのためにコントロールを扱うコードを壊すことなく、後から実装を変更することができます。例えば {{HTMLElement("optgroup")}} 要素と同等の機能を実装したい場合などです。

+ +

クラス名は、しかしながら、意味のある値ではありません。現在の状態では、スクリーンリーダーのユーザーのみがリストを"見る"ことができます。ARIA セマンティクスを少し追加します。

+ +

CSS でルックアンドフィールを作成する

+ +

構造ができましたので、コントロールのデザインを始められます。カスタムコントロールを作成する上でのポイントは、望むとおりにコントロールへスタイルを設定できることです。そのために、CSS を 2 つの部分に分けます: ひとつはコントロールが {{HTMLElement("select")}} 要素のように動作するために欠かせない CSS ルールであり、もうひとつは希望する見た目にするための好みのスタイルで構成されます。

+ +

必須のスタイル

+ +

必須のスタイルは、コントロールの 3 つの状態を扱うために欠かせないものです。

+ +
.select {
+  /* 選択肢のリスト向けのポジショニングコンテキストを作成します;
+     adding this to .select{{cssxref(':focus-within')}} will be a better option when fully supported
+  */
+  position: relative;
+
+  /* コントロールをテキストフローの一部かつまとまった大きさにします */
+  display : inline-block;
+}
+ +

アクティブ状態であるコントロールのルックアンドフィールを定義するため、追加で active クラスが必要です。このコントロールはフォーカスを得ることができますので、同様に動作させるためにカスタムスタイルを {{cssxref(":focus")}} 疑似クラスにも適用します。

+ +
.select.active,
+.select:focus {
+  outline: none;
+
+  /* box-shadow プロパティは必須ではありませんが、これをデフォルト値として使用するのは
+     アクティブ状態を見えるようにするために重要です。自由に書き換えてください。*/
+  box-shadow: 0 0 3px 1px #227755;
+}
+ +

次に、選択肢のリストを扱いましょう:

+ +
/* .select セレクタは、私たちが定義するクラスがコントロールの内部にあることを
+   確実にするためのシンタックスシュガーです。*/
+.select .optList {
+  /* 選択肢のリストが値の下部かつ HTML フローの外側に表示される
+     ようにします。*/
+  position : absolute;
+  top      : 100%;
+  left     : 0;
+}
+ +

選択肢のリストが隠れている状態を扱うための追加クラスも必要です。これはアクティブ状態と開いた状態で完全には一致しない相違点を扱うために必要です。

+ +
.select .optList.hidden {
+  /* これはアクセシブルな方法でリストを隠すための簡単な方法です。
+     アクセシビリティについては最後に説明します。*/
+  max-height: 0;
+  visibility: hidden;
+}
+ +
+

: 選択肢のリストに高さと幅を与えないように transform: scale(1, 0) も使えます。

+
+ +

美化

+ +

基本的な機能性を適切に置きましたので、戯れを始められます。以下は何ができるかの例であり、本記事の冒頭で示したスクリーンショットに一致するものです。とはいえ、自由に実験して何ができるかを見てみるとよいでしょう。

+ +
.select {
+  /* アクセシビリティのため、すべてのサイズは em 単位の値で表します
+     (ユーザーがテキストのみのモードでブラウザーのズーム機能を使用したときに、
+     コントロールをリサイズ可能にします)。算出結果は、ほとんどのブラウザーで
+     デフォルト値である 1em == 16px を想定します。
+     px から em への変換がわからない場合は http://riddle.pl/emcalc/ を試してください */
+  font-size   : 0.625em; /* この値 (10px) は、本コンテキストにおける新たなフォントサイズの em 単位値です。*/
+  font-family : Verdana, Arial, sans-serif;
+
+  box-sizing : border-box;
+
+  /* 後で追加する下向き矢印のためのスペースが必要です */
+  padding : .1em 2.5em .2em .5em; /* 1px 25px 2px 5px */
+  width   : 10em; /* 100px */
+
+  border        : .2em solid #000; /* 2px */
+  border-radius : .4em; /* 4px */
+  box-shadow    : 0 .1em .2em rgba(0,0,0,.45); /* 0 1px 2px */
+
+  /* 最初の宣言は、線形グラデーションをサポートしないブラウザー向けのものです。*/
+  background : #F0F0F0;
+  background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0);
+}
+
+.select .value {
+  /* 値がコントロールの幅より大きくなる可能性があるため、コントロールの幅を
+     変更しないようにすることが必要です。内容物がオーバーフローした場合は、
+     省略記号をつけるとよいでしょう。*/
+  display  : inline-block;
+  width    : 100%;
+  overflow : hidden;
+  white-space : nowrap;
+  text-overflow: ellipsis;
+  vertical-align: top;
+}
+ +

下向き矢印をデザインするための追加要素は不要です。代わりに {{cssxref(":after")}} 疑似要素を使用します。ただし、select クラスでシンプルな背景画像を使用することによる実装も可能です。

+ +
.select:after {
+  content : "▼"; /* Unicode 文字 U+25BC を使用します。http://www.utf8-chartable.de をご覧ください */
+  position: absolute;
+  z-index : 1; /* これは、矢印が選択肢のリストに重ならないようにするために重要です */
+  top     : 0;
+  right   : 0;
+
+  box-sizing : border-box;
+
+  height  : 100%;
+  width   : 2em;
+  padding-top : .1em;
+
+  border-left  : .2em solid #000;
+  border-radius: 0 .1em .1em 0;
+
+  background-color : #000;
+  color : #FFF;
+  text-align : center;
+}
+ +

次に、選択肢のリストにスタイルを設定しましょう:

+ +
.select .optList {
+  z-index : 2; /* 選択肢のリストが下向き矢印より上になるよう、明示的に示します。*/
+
+  /* ul 要素のデフォルトスタイルを初期化します。*/
+  list-style: none;
+  margin : 0;
+  padding: 0;
+
+  box-sizing : border-box;
+
+  /* 値の幅がコントロールの幅より小さい場合でも、選択肢のリストの幅が
+     コントロール自体と同じになるようにします。*/
+  min-width : 100%;
+
+  /* リストが長すぎる場合に、内容物が垂直方向にはみ出します (自動的に
+     垂直スクロールバーを表示します) が、水平方向にはみ出しません
+     (幅を指定しないため、リストは自身の幅へ自動的に調整されます。
+     それができない場合は、内容物が切り詰められます) 。*/
+  max-height: 10em; /* 100px */
+  overflow-y: auto;
+  overflow-x: hidden;
+
+  border: .2em solid #000; /* 2px */
+  border-top-width : .1em; /* 1px */
+  border-radius: 0 0 .4em .4em; /* 0 0 4px 4px */
+
+  box-shadow: 0 .2em .4em rgba(0,0,0,.4); /* 0 2px 4px */
+  background: #f0f0f0;
+}
+ +

選択肢向けに、ユーザーが選択しようとしている (あるいは選択した) 値を示せるようにするための highlight クラスを追加しなければなりません。

+ +
.select .option {
+  padding: .2em .3em; /* 2px 3px */
+}
+
+.select .highlight {
+  background: #000;
+  color: #FFFFFF;
+}
+ +

これで、3 つの状態の結果は以下のようになります:

+ + + + + + + + + + + + + + + + + + + +
通常状態アクティブ状態開いた状態
{{EmbedLiveSample("Basic_state",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_1")}}{{EmbedLiveSample("Active_state",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_1")}}{{EmbedLiveSample("Open_state",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_1")}}
ソースコードを確認する
+ +

JavaScript でコントロールに命を吹き込む

+ +

デザインや構造の準備ができましたので、コントロールが実際に動作するようにするための JavaScript コードを記述できます。

+ +
+

警告: 以下は教育目的のコードであり、そのままで使用するべきではありません。ご覧のとおり、さまざまな箇所に将来性のないものや古いブラウザーで動作しないものがあります。また、本番のコードでは最適化すべき冗長な箇所もあります。

+
+ +

なぜ動作しないのか?

+ +

始める前に、重要事項を覚えておくことが大切です: ブラウザー内の JavaScript は信頼できる技術ではありません。カスタムコントロールを作成するとき、すべてをつなぎ合わせるために必要であることから JavaScript に頼らなければならないでしょう。ところが、JavaScript をブラウザーで実行できない場合がいくつもあります:

+ + + +

このようなリスクがあるため、JavaScript が動作しない場合に何が起きるかを注意深く考えることが重要です。この問題について詳しく扱うのは、スクリプトをどれだけ汎用および再利用可能にしたいかと密接に関わりますので本記事の範囲を外れますが、本サンプルでは基本的な部分について考えていきます。

+ +

本記事の例では、JavaScript コードが実行されない場合に標準の {{HTMLElement("select")}} 要素にフォールバックします。われわれのコントロールと {{HTMLElement("select")}}を導入し、いずれが表示されるかは body 要素のり class に依存します。読み込みに成功したとき、body 要素の class がコントロールの関数をなす script により更新されます。

+ +

これを実現するには、2 つのことが必要です。

+ +

第一に、カスタムコントロールを使用する前に通常の {{HTMLElement("select")}} 要素を追加することが必要です。実際は、これは残りのフォームデータと共にカスタムコントロールのデータを送信できるようにするために必要です。詳しくは後述します。

+ +
<body class="no-widget">
+  <form>
+    <select name="myFruit">
+      <option>Cherry</option>
+      <option>Lemon</option>
+      <option>Banana</option>
+      <option>Strawberry</option>
+      <option>Apple</option>
+    </select>
+
+    <div class="select">
+      <span class="value">Cherry</span>
+      <ul class="optList hidden">
+        <li class="option">Cherry</li>
+        <li class="option">Lemon</li>
+        <li class="option">Banana</li>
+        <li class="option">Strawberry</li>
+        <li class="option">Apple</li>
+      </ul>
+    </div>
+  </form>
+
+</body>
+ +

第二に、不要な要素 (すなわち、スクリプトを実行する場合における "本物の" {{HTMLElement("select")}} 要素や、実行しない場合におけるカスタムコントロール) を隠せるようにするための新たなクラスが 2 つ必要です。デフォルトでは、HTML コードでカスタムコントロールを隠すことに注意してください。

+ +
.widget select,
+.no-widget .select {
+  /* この CSS セレクタの基本的な意味は:
+     - body のクラスを "widget" に設定して、本物の {{HTMLElement("select")}} 要素を隠す
+     - または body のクラスを変更せずに "no-widget" のままにしておくことで、
+       クラスが "select" である要素が隠される */
+  position : absolute;
+  left     : -5000em;
+  height   : 0;
+  overflow : hidden;
+}
+ +

この CSS は要素の 1 つを見えなくしますが、スクリーンリーダーからは利用できます。

+ +

ここで、スクリプトを実行するか否かを判断するための JavaScript スイッチが必要になります。このスイッチはとても簡単です: ページを読み込むときにスクリプトを実行したら、no-widget クラスを削除して widget クラスを追加します。これにより {{HTMLElement("select")}} 要素やカスタムコントロールの可視性を切り替えます。

+ +
window.addEventListener("load", function () {
+  document.body.classList.remove("no-widget");
+  document.body.classList.add("widget");
+});
+ + + + + + + + + + + + + + + + + +
JS なしJS あり
{{EmbedLiveSample("No_JS",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_2")}}{{EmbedLiveSample("JS",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_2")}}
ソースコードを確認する
+ +
+

注記: コードを本当に汎用かつ再利用可能にしたい場合はクラスを切り替えるのではなく、単に {{HTMLElement("select")}} 要素を隠すためのコントロールのクラスを追加して、ページ内にあるすべての {{HTMLElement("select")}} 要素の後ろにカスタムコントロールを表す DOM ツリーを動的に追加する方がはるかによいでしょう。

+
+ +

作業をより簡単に

+ +

作成しようとしているコードでは、必要な作業すべてのために標準の JavaScript と DOM API を使用するでしょう。ここで使用するつもりである機能は以下のとおりです:

+ +
    +
  1. {{domxref("element.classList","classList")}}
  2. +
  3. {{domxref("EventTarget.addEventListener","addEventListener")}}
  4. +
  5. forEach
  6. +
  7. {{domxref("element.querySelector","querySelector")}} および {{domxref("element.querySelectorAll","querySelectorAll")}}
  8. +
+ +

これら特定機能を利用できるかに加えて、作業を始める前に残されている問題があります。{{domxref("element.querySelectorAll","querySelectorAll()")}} 関数が返すオブジェクトは Array ではなく {{domxref("NodeList")}} です。これは、Array オブジェクトは forEach 関数をサポートしているが {{domxref("NodeList")}} はサポートしていないために重要な問題です。{{domxref("NodeList")}} は Array ととても似ており、また forEach はとても便利であることから、作業を楽にするため以下のように {{domxref("NodeList")}} で forEach をサポートさせることができます:

+ +
NodeList.prototype.forEach = function (callback) {
+  Array.prototype.forEach.call(this, callback);
+}
+ +

古いブラウザーをサポートする必要がある場合、そのブラウザーがこうした機能をサポートしているか確かめてください。そうでない場合、リスト内を繰り返すか、ライブラリーや pollyfill を使う必要があります。

+ +

イベントコールバックを作成する

+ +

基盤が整いましたので、ユーザーがコントロールと対話するたびに使用されるすべての関数を定義し始めることができます。

+ +
// この関数は、カスタムコントロールを非アクティブにしたいときに使用します。
+// 引数は 1 つあります。
+// select : 非アクティブにする `select` クラスの DOM ノード
+function deactivateSelect(select) {
+
+  // コントロールがアクティブではないときは何もしません。
+  if (!select.classList.contains('active')) return;
+
+  // カスタムコントロールの選択肢のリストを取得することが必要です。
+  var optList = select.querySelector('.optList');
+
+  // 選択肢のリストを閉じます。
+  optList.classList.add('hidden');
+
+  // そして、カスタムコントロール自身を非アクティブにします。
+  select.classList.remove('active');
+}
+
+// この関数は、ユーザーがコントロールをアクティブ/非アクティブにしたがっているときに使用します。
+// 引数は 2 つあります:
+// select : アクティブにする `select` クラスの DOM ノード
+// selectList : `select` クラスであるすべての DOM ノードのリスト
+function activeSelect(select, selectList) {
+
+  // コントロールがすでにアクティブであるときは何もしません。
+  if (select.classList.contains('active')) return;
+
+  // すべてのカスタムコントロールを非アクティブにすることが必要です。
+  // deactivateSelect 関数は forEach コールバック関数の要件を
+  // すべて満たしていますので、仲介する無名関数を使用せずに
+  // 直接使用しています。
+  selectList.forEach(deactivateSelect);
+
+  // そして、指定されたコントロールをアクティブ状態にします。
+  select.classList.add('active');
+}
+
+// この関数は、ユーザーが選択肢のリストを開く/閉じることを求めたときに使用します。
+// 引数は 1 つあります:
+// select : 表示を切り替えるリストの DOM ノード
+function toggleOptList(select) {
+
+  // リストはコントロールから確保します。
+  var optList = select.querySelector('.optList');
+
+  // リストのクラスを表示/非表示に切り替えます。
+  optList.classList.toggle('hidden');
+}
+
+// この関数は、選択肢を強調したいときに使用します。
+// 引数は 2 つあります:
+// select : 強調する選択肢を包含する `select` クラスの DOM ノード
+// option : 強調する `option` クラスの DOM ノード
+function highlightOption(select, option) {
+
+  // カスタムコントロールで使用可能なすべての選択肢のリストを取得します。
+  var optionList = select.querySelectorAll('.option');
+
+  // すべての選択肢から強調効果を取り除きます。
+  optionList.forEach(function (other) {
+    other.classList.remove('highlight');
+  });
+
+  // 適切な選択肢を強調します。
+  option.classList.add('highlight');
+};
+ +

以上が、カスタムコントロールのさまざまな状態を制御するために必要なもののすべてです。

+ +

次に、これらの関数と適切なイベントを関連づけます:

+ +
// ドキュメントが読み込まれたときのイベントの関連づけを制御します。
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  // 各々のコントロールは初期化が必要です。
+  selectList.forEach(function (select) {
+
+    // すべての `option` も同様です。
+    var optionList = select.querySelectorAll('.option');
+
+    // ユーザーが選択肢にマウスポインタを乗せるたびに、その選択肢を強調します。
+    optionList.forEach(function (option) {
+      option.addEventListener('mouseover', function () {
+        // 注記: 変数 `select` および `option` は、関数呼び出しのスコープ内でのみ
+        // 使用可能なクロージャです。
+        highlightOption(select, option);
+      });
+    });
+
+    // ユーザーが独自の select 要素でクリックするたびに
+    select.addEventListener('click', function (event) {
+      // 注記: 変数 `select` は、関数呼び出しのスコープ内でのみ
+      // 使用可能なクロージャです。
+
+      // 選択肢のリストの可視性を切り替えます。
+      toggleOptList(select);
+    });
+
+    // コントロールが再びフォーカスを得た場合
+    // ユーザーがコントロールをクリックしたり、コントロールへアクセスするために
+    // Tab キーを使用するたびに、コントロールはフォーカスを得ます。
+    select.addEventListener('focus', function (event) {
+      // 注記: 変数 `select` および `selectList` は、関数呼び出しのスコープ内でのみ
+      // 使用可能なクロージャです。
+
+      // コントロールをアクティブにします。
+      activeSelect(select, selectList);
+    });
+
+    // コントロールがフォーカスを失った場合
+    select.addEventListener('blur', function (event) {
+      // 注記: 変数 `select` は、関数呼び出しのスコープ内でのみ
+      // 使用可能なクロージャです。
+
+      // コントロールを非アクティブにします。
+      deactivateSelect(select);
+    });
+
+    // ユーザーが`esc`を押した場合にフォーカスを外す
+    select.addEventListener('keyup', function (event) {
+
+      // deactive on keyup of `esc`
+      if (event.keyCode === 27) {
+         deactivateSelect(select);
+      }
+    });
+});
+ +

この時点でコントロールは設計どおりに状態が変わりますが、コントロール値はまだ更新されません。次の章でこれを扱います。

+ + + + + + + + + + + + + + + +
Live example
{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_3")}}
ソースコードを確認する
+ +

コントロールの値を制御する

+ +

コントロールが動作するようになりましたので、ユーザーの入力に従って値を更新して、フォームデータと共にその値を送信できるようにするコードを追加しなければなりません。

+ +

これを行うもっとも簡単な方法は、覆い隠したネイティブコントロールを使用することです。そのようなコントロールはブラウザーが提供するすべての組み込みのコントロールと共に値の経過を保持しており、フォームを送信するときは通常どおりに値を送信します。これらすべてを行えるようにするために、車輪の再発明を行うのは無駄です。

+ +

先ほど見たように、アクセシビリティの理由からフォールバック手段としてすでにネイティブの select コントロールを使用しています。単純に、その値をカスタムコントロールの値と同期することができます:

+ +
// この関数は、表示される値を更新してネイティブコントロールの値と同期します。
+// 引数は 2 つあります:
+// select : 更新する値を持つ `select` クラスの DOM ノード
+// index  : 選択される値のインデックス
+function updateValue(select, index) {
+  // 指定されたカスタムコントロール向けのネイティブコントロールを取得することが必要です。
+  // この例では、ネイティブコントロールはカスタムコントロールの兄弟です。
+  var nativeWidget = select.previousElementSibling;
+
+  // カスタムコントロールの値のプレースホルダーの取得も必要です。
+  var value = select.querySelector('.value');
+
+  // そして、選択肢の全リストが必要です。
+  var optionList = select.querySelectorAll('.option');
+
+  // 選択した値のインデックスを、selectedIndex に設定します。
+  nativeWidget.selectedIndex = index;
+
+  // 上記に応じて、値のプレースホルダーも更新します。
+  value.innerHTML = optionList[index].innerHTML;
+
+  // そして、カスタムコントロールで対応する選択肢を強調します。
+  highlightOption(select, optionList[index]);
+};
+
+// この関数は、ネイティブコントロールで現在選択されているインデックスを返します。
+// 引数は 1 つあります:
+// select : ネイティブコントロールに関係する `select` クラスの DOM ノード
+function getIndex(select) {
+  // 指定されたカスタムコントロール向けのネイティブコントロールにアクセスすることが必要です。
+  // この例では、ネイティブコントロールはカスタムコントロールの兄弟です。
+  var nativeWidget = select.previousElementSibling;
+
+  return nativeWidget.selectedIndex;
+};
+ +

これら 2 つの関数で、ネイティブコントロールとカスタムコントロールを関連づけることができます:

+ +
// ドキュメントが読み込まれたときのイベントの関連づけを制御します。
+window.addEventListener('load', function () {
+  var selectList = document.querySelectorAll('.select');
+
+  // 各々のコントロールは初期化が必要です。
+  selectList.forEach(function (select) {
+    var optionList = select.querySelectorAll('.option'),
+        selectedIndex = getIndex(select);
+
+    // カスタムコントロールがフォーカスを得られるようにします。
+    select.tabIndex = 0;
+
+    // ネイティブコントロールがフォーカスを得ないようにします。
+    select.previousElementSibling.tabIndex = -1;
+
+    // デフォルトで選択されている値が正しく表示されるようにします。
+    updateValue(select, selectedIndex);
+
+    // ユーザーが選択肢をクリックするのに応じて値を更新します。
+    optionList.forEach(function (option, index) {
+      option.addEventListener('click', function (event) {
+        updateValue(select, index);
+      });
+    });
+
+    // フォーカスがあるコントロールでユーザーがキーボードを使用するのに応じて、値を更新します。
+    select.addEventListener('keyup', function (event) {
+      var length = optionList.length,
+          index  = getIndex(select);
+
+      // ユーザーが下矢印キーを押すと、次の選択肢にジャンプします。
+      if (event.keyCode === 40 && index < length - 1) { index++; }
+
+      // ユーザーが上矢印キーを押すと、前の選択肢にジャンプします。
+      if (event.keyCode === 38 && index > 0) { index--; }
+
+      updateValue(select, index);
+    });
+  });
+});
+ +

上記のコードで、tabIndex プロパティを使用していることは注目に値します。このプロパティは、ネイティブコントロールにフォーカスが当たらないようにすることと、ユーザーがキーボードやマウスを使用するとカスタムコントロールがフォーカスを得るようにするために必要です。

+ +

これで完了です! 結果は以下のとおりです:

+ + + + + + + + + + + + + + + +
Live example
{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_4")}}
ソースコードを確認する
+ +

ちょっと待ってください、本当に終わったのでしょうか?

+ +

アクセシブルにする

+ +

フル機能のセレクトボックスとはかけ離れていますが動作するものはできましたし、よく動作しています。しかし、私たちが行ってきたことは DOM の操作にすぎません。これには実際のセマンティクスがなく、またセレクトボックスのように見えていてもブラウザーの視点からはそうではないため、支援技術はそれがセレクトボックスであるとは理解できません。つまり、このきれいなセレクトボックスはアクセシブルではありません!

+ +

幸いなことに解決策があり、それは ARIA と呼ばれます。ARIA は "Accessible Rich Internet Application" を表し、その W3C 仕様 は私たちがここで行っていることに特化して設計されています: ウェブアプリケーションやカスタムコントロールをアクセシブルにします。これは基本的には、私たちが作り出した要素がネイティブコントロールとして通るかのように、役割や状態や特性をより説明できるようにするために HTML を拡張する属性のセットです。これらの属性の使用はとても簡単ですので、行ってみましょう。

+ +

role 属性

+ +

ARIA で使用される主要な属性が、role 属性です。role 属性は、要素を何に使用するかを定義する値を受け入れます。それぞれのロールは、自身の要件や動作を定義します。本記事の例では、ロール listbox を使用します。これは "composite role" であり、このロールの要素は子要素を持ち、またそれぞれの子要素も特定のロールを持ちます (この例では、ロール option の子要素が少なくとも 1 つ)。

+ +

また、ARIA は標準の HTML マークアップにデフォルトで適用されるロールを定義することも特筆に値します。例えば、{{HTMLElement("table")}} 要素はロール grid に、{{HTMLElement("ul")}} 要素はロール list にマッチします。{{HTMLElement("ul")}} 要素を使用しているため、私たちのコントロールのロール listbox が、{{HTMLElement("ul")}} 要素のロール list を置き換えるようにしなければなりません。そのために、ロール presentation を使用します。このロールは要素に特別な意味はないことを示せるようにするためのものであり、単に情報を与えるために使用されます。これを {{HTMLElement("ul")}} 要素に適用します。

+ +

ロール listbox をサポートするため、HTML を以下のように更新することが必要です:

+ +
<!-- 最初の要素に role="listbox" 属性を追加します -->
+<div class="select" role="listbox">
+  <span class="value">Cherry</span>
+  <!-- ul 要素に role="presentation" を追加します -->
+  <ul class="optList" role="presentation">
+    <!-- すべての li 要素に role="option" 属性を追加します -->
+    <li role="option" class="option">Cherry</li>
+    <li role="option" class="option">Lemon</li>
+    <li role="option" class="option">Banana</li>
+    <li role="option" class="option">Strawberry</li>
+    <li role="option" class="option">Apple</li>
+  </ul>
+</div>
+ +
+

注記: role 属性と class 属性の両方を含める方法は、CSS 属性セレクタに対応しない古いブラウザーをサポートしたい場合にのみ必要です。

+
+ +

aria-selected 属性

+ +

role を使用するだけでは不十分です。ARIA は、状態や特性を表す多くの属性も提供します。これらをより多くまた適切に使用すると、コントロールが支援技術にもっと良く理解されるようになります。ここでは、使用する属性を 1 つに絞ります: aria-selected です。

+ +

aria-selected 属性は、どの選択肢が現在選択されているかを示すために使用します。これにより、支援技術はユーザーに現在何が選択されているかを伝えることができます。ここではユーザーが選択肢を選択するたびに、選択された選択肢を示すためにこの属性を JavaScript で動的に使用します。このために、updateValue() 関数の変更が必要です:

+ +
function updateValue(select, index) {
+  var nativeWidget = select.previousElementSibling;
+  var value = select.querySelector('.value');
+  var optionList = select.querySelectorAll('.option');
+
+  // すべての選択肢が選択されていないようにします。
+  optionList.forEach(function (other) {
+    other.setAttribute('aria-selected', 'false');
+  });
+
+  // 指定された選択肢が選択されているようにします。
+  optionList[index].setAttribute('aria-selected', 'true');
+
+  nativeWidget.selectedIndex = index;
+  value.innerHTML = optionList[index].innerHTML;
+  highlightOption(select, optionList[index]);
+};
+ +

スクリーンリーダーにオフスクリーンselectに焦点をあてて他のスタイルを無視するようにした法が簡単に見えますが、これはアクセシブルな解決策ではありません。スクリーンリーダーは盲目の人だけのものではありません。低視力や、完全な視力の人もこれを使います。このため、スクリーンリーダーをオフスクリーン要素だけに焦点をあてるようにはできません。

+ +

以下がこれらの変更を施した最終結果です (NVDAVoiceOver などの支援技術でコントロールを使用してみても、よい感触を得られるでしょう):

+ + + + + + + + + + + + + + + +
Live example
{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_controls/Example_5")}}
ソースコードを確認する
+ +

もっと先に進むには、この例でのコードは汎用性や再利用性に改善が必要です。これは課題として挑戦できます。この2つのヒントを挙げると:すべての関数で最初の引数は同じで、つまりこれらの関数は同じコンテキストが必要です。そのコンテキストを共有するオブジェクトを作るのが賢明です。

+ +

他の方法: ラジオボタンを使う

+ +

上の例では、非動的なHTML、CSS、JavaScript を使って {{htmlelement('select')}} 要素を再発明しました。このselectは限られた選択肢から1つが選択され、それは {{htmlelement('input/radio', 'radio')}} ボタンのグループと同様な機能です。

+ +

このため、代わりにラジオボタンを使って再発明できます。このオプションを見てみましょう。

+ +

We can start with

+ +

完全に意味のある、アクセシブルで、順序のない、関連する{{htmlelement('label')}}つきの{{htmlelement('input/radio','radio')}} ボタンのリストから始めます、グループ全体を適切な意味のある{{htmlelement('fieldset')}} と{{htmlelement('legend')}} のペアにラベルづけします。.

+ +
 <fieldset>
+  <legend>Pick a fruit</legend>
+    <ul class="styledSelect">
+      <li><input type="radio" name="fruit" value="Cherry" id="fruitCherry" checked><label for="fruitCherry">Cherry</label></li>
+      <li><input type="radio" name="fruit" value="Lemon" id="fruitLemon"><label for="fruitLemon">Lemon</label></li>
+      <li><input type="radio" name="fruit" value="Banana" id="fruitBanana"><label for="fruitBanana"">Banana</label></li>
+      <li><input type="radio" name="fruit" value="Strawberry" id="fruitStrawberry"><label for="fruitStrawberry">Strawberry</label></li>
+      <li><input type="radio" name="fruit" value="Apple" id="fruitApple"><label for="fruitApple">Apple</label></li>
+    </ul>
+  </fieldset>
+ +

(legend/fieldsetではなく)ラジオボタンリストに少しスタイルづけをして、前の例と同じ見た目にし、完了したことがわかるようにします:

+ +
.styledSelect {
+  display: inline-block;
+  padding: 0;
+}
+.styledSelect li {
+  list-style-type: none;
+  padding: 0;
+  display: flex;
+}
+.styledSelect [type=radio] {
+  position: absolute;
+  left: -100vw;
+  top: -100vh;
+}
+.styledSelect label {
+  margin: 0;
+  line-height: 2;
+  padding: 0 0 0 4px;
+}
+.styledSelect:not(:focus-within) input:not(:checked) + label {
+  height: 0;
+  outline: none;
+  overflow: hidden;
+}
+.styledSelect:not(:focus-within) input:checked + label {
+  border: .2em solid #000;
+  border-radius: .4em;
+  box-shadow: 0 .1em .2em rgba(0,0,0,.45);
+}
+.styledSelect:not(:focus-within) input:checked + label::after {
+  content : "▼";
+  background: black;
+  float: right;
+  color: white;
+  padding: 0 4px;
+  margin: 0 -4px 0 4px;
+}
+.styledSelect:focus-within {
+  border: .2em solid #000;
+  border-radius: .4em;
+  box-shadow: 0 .1em .2em rgba(0,0,0,.45);
+}
+.styledSelect:focus-within input:checked + label {
+  background-color: #333;
+  color: #fff;
+  width: 100%;
+}
+ +

JavaScriptなしで少しの CSSにて、ラジオボタンのリストをスタイルづけしてチェック済み項目のみを表示することができます。フォーカスが<fieldset>内の <ul> に来ると、リストは開いて、上下左右の矢印が前後の項目を選択するのに使えます。次で試してください:

+ +

{{EmbedLiveSample("An_alternative_approach_Using_radio_buttons",200,240)}}

+ +

これはある程度、JavaScriptなしで動作します。JavaScript が失敗しても動作する、われわれのカスタムコントロールど同じものを作ってきました。よい解決策でしょう?これはキーボードでは動作しますが、マウスクリックではそうなりません。ネイティブな意味づけのない要素を作るフレームワークに依存する代わりに、ウェブ標準をカスタムコントロールの基礎として使った方が意味があります。しかし、われわれのコントロールは <select> が自ずと持つ機能と同じものを備えていません。

+ +

いい面として、このコントロールはスクリーンリーダーにとって完全にアクセシブルでキーボードで完全に操作できます。しかし、このコントロールは {{htmlelement('select')}} 要素の置き換えではありません。異なる機能や足りない機能があります。例えば、4つの矢印は選択肢を操作できますが、最後のボタンで下を押すと最初のボタンに移動します。<select> のように上端、下端で止まりません。

+ +

この足りない機能の追加は、読者の課題としておきます。

+ +

まとめ

+ +

独自のフォームコントロールの作成方法を見てきましたが、ご覧いただいたようにこれは容易なことではありません。独自のカスタムコントロールを作る前に、HTMLに要求を十分に満たす代替要素がないかを検討してください。本当にカスタムコントロールを作成する必要がある場合、サードパーティのライブラリに頼るほうが簡単かつよいことも少なくありません。独自作成する場合、既存の要素を編集するか、準備されたコントロールを実装するフレームワークを使うようにして、実用的でアクセシブルなフォームコントロールの作成は見た目より複雑であることを忘れないでください。

+ +

自分でコーディングする前に検討するとよいライブラリをいくつか紹介します:

+ + + +

ラジオボタン、独自JavaScript 、またはサードパーティライブラリで代替コントロールを作る場合、アクセシブルかつ機能への耐性を高めましょう。すなわち Web 標準の実装状況がまちまちである、多様なブラウザーで良好に動作できるようにすることが必要です。楽しんでください!

+ +

このモジュール

+ +

学習コース

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/how_to_structure_an_html_form/example/index.html b/files/ja/learn/forms/how_to_structure_an_html_form/example/index.html new file mode 100644 index 0000000000..2c97485087 --- /dev/null +++ b/files/ja/learn/forms/how_to_structure_an_html_form/example/index.html @@ -0,0 +1,164 @@ +--- +title: '例: お支払いフォーム' +slug: Learn/Forms/How_to_structure_an_HTML_form/Example +translation_of: Learn/Forms/How_to_structure_a_web_form/Example +--- +

これは記事 HTML フォームの構築方法の基本的なお支払いフォームの例です。

+ +

お支払いフォーム

+ +

HTML コンテンツ

+ +
<form>
+        <h1>Payment form</h1>
+        <p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
+        <section>
+            <h2>Contact information</h2>
+            <fieldset>
+              <legend>Title</legend>
+              <ul>
+                  <li>
+                    <label for="title_1">
+                      <input type="radio" id="title_1" name="title" value="M." >
+                      Mister
+                    </label>
+                  </li>
+                  <li>
+                    <label for="title_2">
+                      <input type="radio" id="title_2" name="title" value="Ms.">
+                      Miss
+                    </label>
+                  </li>
+              </ul>
+            </fieldset>
+            <p>
+              <label for="name">
+                <span>Name: </span>
+                <strong><abbr title="required">*</abbr></strong>
+              </label>
+              <input type="text" id="name" name="username">
+            </p>
+            <p>
+              <label for="mail">
+                <span>E-mail: </span>
+                <strong><abbr title="required">*</abbr></strong>
+              </label>
+              <input type="email" id="mail" name="usermail">
+            </p>
+            <p>
+              <label for="password">
+                <span>Password: </span>
+                <strong><abbr title="required">*</abbr></strong>
+              </label>
+              <input type="password" id="pwd" name="password">
+            </p>
+        </section>
+        <section>
+            <h2>Payment information</h2>
+            <p>
+              <label for="card">
+                <span>Card type:</span>
+              </label>
+              <select id="card" name="usercard">
+                <option value="visa">Visa</option>
+                <option value="mc">Mastercard</option>
+                <option value="amex">American Express</option>
+              </select>
+            </p>
+            <p>
+              <label for="number">
+                <span>Card number:</span>
+                <strong><abbr title="required">*</abbr></strong>
+              </label>
+                <input type="number" id="number" name="cardnumber">
+            </p>
+            <p>
+              <label for="date">
+                <span>Expiration date:</span>
+                <strong><abbr title="required">*</abbr></strong>
+                <em>formatted as mm/yy</em>
+              </label>
+              <input type="date" id="date" name="expiration">
+            </p>
+        </section>
+        <section>
+            <p> <button type="submit">Validate the payment</button> </p>
+        </section>
+    </form>
+ +

CSS コンテンツ

+ +
      h1 {
+          margin-top: 0;
+      }
+
+      ul {
+          margin: 0;
+          padding: 0;
+          list-style: none;
+      }
+
+      form {
+          margin: 0 auto;
+          width: 400px;
+          padding: 1em;
+          border: 1px solid #CCC;
+          border-radius: 1em;
+      }
+
+      div+div {
+          margin-top: 1em;
+      }
+
+      label span {
+          display: inline-block;
+          width: 120px;
+          text-align: right;
+      }
+
+      input, textarea {
+          font: 1em sans-serif;
+          width: 250px;
+          box-sizing: border-box;
+          border: 1px solid #999;
+      }
+
+      input[type=checkbox], input[type=radio] {
+          width: auto;
+          border: none;
+      }
+
+      input:focus, textarea:focus {
+          border-color: #000;
+      }
+
+      textarea {
+          vertical-align: top;
+          height: 5em;
+          resize: vertical;
+      }
+
+      fieldset {
+          width: 250px;
+          box-sizing: border-box;
+          margin-left: 136px;
+          border: 1px solid #999;
+      }
+
+      button {
+          margin: 20px 0 0 124px;
+      }
+
+      label {
+        position: relative;
+      }
+
+      label em {
+        position: absolute;
+        right: 5px;
+        top: 20px;
+      }
+ +

結果

+ +

{{ EmbedLiveSample('A_payment_form', '100%', 620) }}

diff --git a/files/ja/learn/forms/how_to_structure_an_html_form/index.html b/files/ja/learn/forms/how_to_structure_an_html_form/index.html new file mode 100644 index 0000000000..ca3865643f --- /dev/null +++ b/files/ja/learn/forms/how_to_structure_an_html_form/index.html @@ -0,0 +1,329 @@ +--- +title: フォームの構築方法 +slug: Learn/Forms/How_to_structure_an_HTML_form +tags: + - CodingScripting + - HTML + - Web + - ガイド + - フォーム + - 例 + - 初心者 + - 学習 + - 構造 +translation_of: Learn/Forms/How_to_structure_a_web_form +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Forms/Your_first_form", "Learn/Forms/Basic_native_form_controls", "Learn/Forms")}}
+ +

基本から外れて、ここでは色々なフォームのパーツを構造化し、意味をつけるのに使われる要素を詳しく見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーと、HTML の基本的な理解
目的:HTML フォームを構造化して意味を与えて使いやすくアクセシブルにする方法を理解すること。
+ +

フォームは柔軟性があるため、HTML で最も複雑な構造の 1 つとなっています。専用のフォーム要素と属性を使用して、あらゆる種類の基本フォームを作成できます。HTML フォームを構築するときに正しい構造を使用すると、フォームが使用可能でアクセスしやすいことを確実にするのに役立ちます。

+ +

<form> 要素

+ +

{{HTMLElement("form")}} 要素はフォームを正式に定義するとともに、自身の属性でフォームの動作を定義します。HTML フォームを作成しようとするたびに、この要素から始めて、すべてのコンテンツをその中に入れなければなりません。多くの支援技術やブラウザープラグインは {{HTMLElement("form")}} 要素を検出でき、またフォームを使いやすくするための特別なフックを実装できます。

+ +

前の記事ですでにこれを見ています。

+ +
警告: フォームの中にフォームを入れ子にすることは厳格に禁じられています。これは予期せぬ動作を発生するおそれがあるので、悪い方針です。
+ +

{{HTMLElement("form")}} 要素の外部でもフォームウィジェットを使用できますが、そのフォームウィジェットは form 属性を用いて関連付けなければ、どのフォームに対しても何も行わないことに注意してください。これは、実際には {{ HTMLElement("form") }} に包含されていない要素であっても明示的にフォームへ紐付けることを可能にします。

+ +

  次に、フォームに含まれる構造的な要素を見ていきましょう。

+ +

<fieldset> および <legend> 要素

+ +

{{HTMLElement("fieldset")}} 要素は、スタイルや意味付けのために、同じ目的を持つウィジェットのグループの作成に便利です。{{HTMLElement("fieldset")}} 要素は、<fieldset> タグのすぐ下に {{HTMLElement("legend")}} 要素を入れてラベルを付与できます。{{HTMLElement("legend")}} 要素は、{{HTMLElement("fieldset")}} 要素の目的を正式に説明します。

+ +

多くの支援技術は {{HTMLElement("legend")}} 要素を、対応する {{HTMLElement("fieldset")}} 要素内にある各ウィジェットのラベルの一部であるかのように扱うでしょう。例えば JawsNVDA といったスクリーンリーダーは、各ウィジェットのラベルを読み上げる前に legend の内容を読み上げます。

+ +

以下に小さなサンプルを挙げます:

+ +
<form>
+  <fieldset>
+    <legend>Fruit juice size</legend>
+    <p>
+      <input type="radio" name="size" id="size_1" value="small">
+      <label for="size_1">Small</label>
+    </p>
+    <p>
+      <input type="radio" name="size" id="size_2" value="medium">
+      <label for="size_2">Medium</label>
+    </p>
+    <p>
+      <input type="radio" name="size" id="size_3" value="large">
+      <label for="size_3">Large</label>
+    </p>
+  </fieldset>
+</form>
+ +
+

: この例は fieldset-legend.html で見ることができます(ライブ版も見てください)。

+
+ +

この例では、スクリーンリーダーは最初のウィジェットを "Fruit juice size small"、2 番目を "Fruit juice size medium"、3 番目を "Fruit juice size large" と読み上げるでしょう。

+ +

このサンプルでのユースケースは、もっとも重要なことのひとつです。ラジオボタンのセットを置くたびに、それらを {{HTMLElement("fieldset")}} 要素内へ入れ子にするようにしましょう。ユースケースは他にもあり、通常は {{HTMLElement("fieldset")}} 要素でフォームを明確に区分するために使用できます。理想的には長いフォームは複数ページに分けるべきですが、フォームが長くなっても1つのページに収めないといけない場合、別々の関連セクションを別々の fieldset に入れることは使いやすさを改善します。

+ +

支援技術への影響力により、{{HTMLElement("fieldset")}} 要素はアクセシブルなフォームを作成するために重要な要素のひとつです。しかし、それを誤用しないようにするのはあなたの責務です。できれば、フォームを作成するたびにスクリーンリーダーがどのように解釈するか聞いてみましょう。変に聞こえるのであれば、フォームの構造を改善するためのよいヒントになります。

+ +

<label> 要素

+ +

これまでの記事で見てきたように、{{HTMLElement("label")}} 要素は、HTML フォームウィジェットのラベルを定義する正式な方法です。これは、アクセシブルなフォームを作成したい場合にもっとも重要な要素です — 適切に実装された時は、スクリーンリーダーはフォーム要素のラベルと関連する指示を一緒に読み上げます。前の記事で見てきたこの例を見てみます:

+ +
<label for="name">Name:</label> <input type="text" id="name" name="user_name">
+ +

<label><input> とがそれぞれ forid 属性により正し関連付けられると (label の for 属性は対応するウィジェットの id 属性を参照します)、スクリーンリーダーは "Name, edit text"のように読み上げます。

+ +

フォームコントロールとラベルを関連付けるもう 1 つの方法は、フォームコントロールを <label> の中でネストすることで、暗黙的に関連付けることです。

+ +
<label for="name">
+  Name: <input type="text" id="name" name="user_name">
+</label>
+ +

この場合でも for 属性を設定することがベストプラクティスと考えられています。これは、ラベルとウィジェットの暗黙的な関係を理解できない支援技術があるためです。

+ +

ラベルがなかったり、フォームコントロールが明示的/暗黙にラベルに関連付けられていない場合、スクリーンリーダーは全く役立たない "Edit text blank" のような読み上げを行います。

+ +

ラベルもクリック可能です!

+ +

ラベルをセットアップするもう 1 つの利点は、ユーザーがラベルをクリックするとウィジェットをアクティブにすることが、あらゆるブラウザーで可能になります。これは例えば、テキスト入力で、入力と同様にラベルをクリックしてフォーカスさせることができますし、ラジオボタンやチェックボックスで特に有用です — このコントロールのヒットエリアはとても小さく、できるだけ大きくしておくのは便利です。

+ +

例えば、次の例で "I like cherry" の テキストをクリックすると選択された taste_cherry チェックボックスの状態が切り替わります:

+ +
<form>
+  <p>
+    <input type="checkbox" id="taste_1" name="taste_cherry" value="cherry">
+    <label for="taste_1">I like cherry</label>
+  </p>
+  <p>
+    <input type="checkbox" id="taste_2" name="taste_banana" value="banana">
+    <label for="taste_2">I like banana</label>
+  </p>
+</form>
+ +
+

: この例は checkbox-label.html で見ることができます(ライブ版も見てください)。

+
+ +

複数のラベル

+ +

厳密に言うと、1 つのウィジェット内に複数のラベルを入れることができますが、複数のラベルを持つウィジェットの扱いに問題がある支援技術があるかもしれません。複数のラベルがある場合、アクセシブルなフォームを作成するには1つの {{htmlelement("label")}} 要素内にウィジェットを入れ子にするとよいでしょう。

+ +

以下のサンプルについて考えてみましょう:

+ +
<p>Required fields are followed by <abbr title="required">*</abbr>.</p>
+
+<!-- 2 つの例をご覧ください: -->
+<div>
+  <label for="username">Name:</label>
+  <input id="username" type="text" name="username">
+  <label for="username"><abbr title="required" aria-label="required">*</abbr></label>
+</div>
+
+<!-- 前出の例よりは良いです: -->
+<div>
+  <label for="username">
+    <span>Name: </span>
+    <input id="username" type="text" name="username">
+    <abbr title="required" aria-label="required">*</abbr>
+  </label>
+</div>
+
+<!-- これが最も良いでしょう: -->
+<div>
+  <label for="username">Name: <abbr title="required" aria-label="required">*</abbr></label>
+  <input id="username" type="text" name="username">
+</div>
+ +

{{EmbedLiveSample("Multiple_labels", 120, 120)}}

+ +

このサンプルでは、最初の段落で入力必須の要素の規則を定義しています。ユーザーが入力必須の要素を見つける前にスクリーンリーダーのような支援技術が注意事項を表示したり読み上げたりするためには、規則をはじめに置かなければなりません。これがユーザーにアスタリスクの意味を知らせても、それに依存することはできません。スクリーンリーダーはアスタリスクが出てくると "スター" と読み上げます。視力のあるユーザーがマウスを持ってくると、title 属性によって"必須"と表示されます。タイトルはスクリーンリーダーの設定により読み上げられるので、常にスクリーンリーダーに読み上げられる aria-label 属性を入れておくのがより信頼性が高いでしょう。

+ +

上記の違いをふまえると、以降を効率よく見ていけるでしょう:

+ + + +
+

: スクリーンリーダーによっては、少し異なる結果になる場合もあります。これは VoiceOver (と同様に動作する NVDA)でテストしています。あなたの体験を聞きたいです。

+
+ +
+

: この例は GitHub の required-labels.html で見ることができます(ライブ版も見てください)。2 や 3 のコメントを外したバージョンの例を実行しないでください — 複数の label と複数の同じ input ID があると、スクリーンリーダーは確実に混乱します!

+
+ +

フォームで使用される一般的な HTML 構造

+ +

ウェブフォーム特有の構造の前提として、フォームは単に HTML であると覚えておくとよいでしょう。つまり、ウェブフォームを組み立てるために HTML のすべての力を利用できるのです。

+ +

サンプルでわかるように、ラベルとそのウィジェットを {{HTMLElement("ul")}} や {{HTMLElement("ol")}} リストの中の {{HTMLElement("li")}} 要素で包み込むのが一般的な慣習です。HTML リストにあるように、{{HTMLElement("p")}} 要素と {{HTMLElement("div")}} 要素も良く使われます。リストは複数のチェックボックスやラジオボタンを構造化するのに最もよく使われます。

+ +

{{HTMLElement("fieldset")}} 要素に加えて、複雑なフォームの構築に HTML の見出し (例{{htmlelement("h1")}}, {{htmlelement("h2")}}) やセクション (例 {{htmlelement("section")}}) を使うことも一般的です。

+ +

とりわけ、コーディングスタイルがどうあるのが心地よく、どれがアクセシブルで使いやすいフォームとなるのかを見つけるのはあなた次第です。別の機能セクションは別の {{htmlelement("section")}} 要素と、ラジオボタンを含む {{htmlelement("fieldset")}} にそれぞれ分けておくべきです。

+ +

アクティブラーニング: フォーム構造を構築する

+ +

これらのアイデアを実践し、もう少し複雑なフォーム構造、つまり支払いフォームを作成しましょう。このフォームはあなたがまだ理解していないかもしれないウィジェットタイプをいくつも含みますが、今はそのことを心配しないでください。次の記事 (ネイティブフォームウィジェット) でそれらがどのように機能するのかがわかります。今のところ、以下の説明に沿って説明を注意深く読み、フォームを構成するためにどのラッパー要素を使用しているか、そしてその理由を理解することから始めてください。

+ +
    +
  1. あらかじめ、空のテンプレートファイルお支払いフォームの CSS のローカルコピーをコンピューターの新しいディレクトリーに作成します。
  2. +
  3. まず最初に、HTML {{htmlelement("head")}} 内に次の行を追加して CSS を HTML に適用します。 +
    <link href="payment-form.css" rel="stylesheet">
    +
  4. +
  5. 次に、外側の {{htmlelement("form")}} 要素を追加してフォームを作成します: +
    <form>
    +
    +</form>
    +
  6. +
  7. <form> タグ内に、必須フィールドにマークを付ける方法をユーザーに通知するための見出しと段落を追加します: +
    <h1>Payment form</h1>
    +<p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
    +
  8. +
  9. 次に、前のエントリーの下に、より大きなコードセクションをフォームに追加します。ここでは、連絡先情報フィールドを個別の {{htmlelement("section")}} 要素内にラップしていることがわかります。さらに、2 つのラジオボタンのセットがあり、それぞれ独自のリスト ({{htmlelement("li")}}) 要素の中に入れています。最後に、2 つの標準テキスト {{htmlelement("input")}} とそれに関連する {{htmlelement("label")}} 要素があり、それぞれ {{htmlelement("p")}} の内側に含まれていて、パスワードを入力するためのパスワード入力があります。フォームにこのコードを追加してください: +
    <section>
    +    <h2>Contact information</h2>
    +    <fieldset>
    +      <legend>Title</legend>
    +      <ul>
    +          <li>
    +            <label for="title_1">
    +              <input type="radio" id="title_1" name="title" value="K" >
    +              King
    +            </label>
    +          </li>
    +          <li>
    +            <label for="title_2">
    +              <input type="radio" id="title_2" name="title" value="Q">
    +              Queen
    +            </label>
    +          </li>
    +          <li>
    +            <label for="title_3">
    +              <input type="radio" id="title_3" name="title" value="J">
    +              Joker
    +            </label>
    +          </li>
    +      </ul>
    +    </fieldset>
    +    <p>
    +      <label for="name">
    +        <span>Name: </span>
    +        <strong><abbr title="required">*</abbr></strong>
    +      </label>
    +      <input type="text" id="name" name="username">
    +    </p>
    +    <p>
    +      <label for="mail">
    +        <span>E-mail: </span>
    +        <strong><abbr title="required">*</abbr></strong>
    +      </label>
    +      <input type="email" id="mail" name="usermail">
    +    </p>
    +    <p>
    +      <label for="pwd">
    +        <span>Password: </span>
    +        <strong><abbr title="required">*</abbr></strong>
    +      </label>
    +      <input type="password" id="pwd" name="password">
    +    </p>
    +</section>
    +
  10. +
  11. それでは、フォームの 2 番目の <section> — 支払い情報に目を向けます。ここには 3 つの異なるウィジェットとそのラベルがあり、それぞれ <p> の中に含まれています。1 つ目は、クレジットカードの種類を選択するためのドロップダウンメニュー ({{htmlelement("select")}}) です。2 番目は、クレジットカード番号を入力するための tel 型の <input> 要素です。number 型を使うこともできますが、そのスピナーUIは望ましくありません。最後のものは、カードの有効期限を入力するための date 型の <input> 要素です。これは、サポートしているブラウザーでは日付選択ウィジェットが表示され、サポートしていないブラウザーでは通常のテキスト入力に戻ります。新しい入力タイプは HTML5 入力タイプで再度紹介されます。
    +
    + 前のセクションの下に次のように入力してください。 +
    <section>
    +    <h2>Payment information</h2>
    +    <p>
    +      <label for="card">
    +        <span>Card type:</span>
    +      </label>
    +      <select id="card" name="usercard">
    +        <option value="visa">Visa</option>
    +        <option value="mc">Mastercard</option>
    +        <option value="amex">American Express</option>
    +      </select>
    +    </p>
    +    <p>
    +      <label for="number">
    +        <span>Card number:</span>
    +        <strong><abbr title="required">*</abbr></strong>
    +      </label>
    +      <input type="tel" id="number" name="cardnumber">
    +    </p>
    +    <p>
    +      <label for="date">
    +        <span>Expiration date:</span>
    +        <strong><abbr title="required">*</abbr></strong>
    +        <em>formatted as mm/dd/yyyy</em>
    +      </label>
    +      <input type="date" id="date" name="expiration">
    +    </p>
    +</section>
    +
  12. +
  13. 最後に追加するセクションはもっと単純で、フォームデータを送信するための submit タイプの {{htmlelement("button")}} のみを含みます。これをフォームの一番下に追加してください: +
    <p> <button type="submit">Validate the payment</button> </p>
    +
  14. +
+ +

完成したフォームは以下のように動作しています (GitHub でも確認できます。payment-form.html ソースを参照してライブ実行してください)。

+ +

{{EmbedLiveSample("A_payment_form","100%",620, "", "Learn/HTML/Forms/How_to_structure_an_HTML_form/Example")}}

+ +

あなたのスキルをテストしてみましょう!

+ +

この記事はここまでですが、最も重要な情報を覚えていますか? 先に進む前に、この情報を保持しているかどうかを確認するためのテストがあります — Test your skills: Form structure を参照してください。

+ +

まとめ

+ +

ウェブフォームを適切に構築するためのあらゆる知識を得ることができました。これからここで出てきた機能を見ていき、次の記事では、ユーザーから情報を集めるのに使いたくなるすべての種類のフォームウィジェットの詳細な実装について詳しく見ていきます。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/HTML/Forms/Your_first_HTML_form", "Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/html5_input_types/index.html b/files/ja/learn/forms/html5_input_types/index.html new file mode 100644 index 0000000000..c825e48653 --- /dev/null +++ b/files/ja/learn/forms/html5_input_types/index.html @@ -0,0 +1,289 @@ +--- +title: HTML5 入力タイプ +slug: Learn/Forms/HTML5_input_types +tags: + - Beginner + - Controls + - Example + - Forms + - Guide + - HTML + - Web + - Widgets +translation_of: Learn/Forms/HTML5_input_types +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}
+ +

前の記事では {{htmlelement("input")}} 要素を見てきて、HTML の初期から利用できる type 属性の値をカバーしてきました。ここでは最近のフォームコントロールの機能、特定のデータを集めるのに HTML5 で追加された、新しい入力タイプを詳しく見ていきましょう。

+ + + + + + + + + + + + +
前提条件:コンピューターリテラシーの基本と、HTML の理解
目的:ネイティブフォームコントロールで利用できる新しい入力タイプの理解と、HTML を用いた実装方法。
+ +
+

: この記事のたいていの昨日はブラウザーを超えて広くサポートされています。例外は注記しておきます。ブラウザーサポートについての詳細は、HTML フォーム要素のリファレンス、特に <input> タイプリファレンスを見てください。

+
+ +

HTML フォームコントロールの見た目はデザイナーの仕様により全く異なるため、ウェブ開発者はときどき独自のフォームコントロールを作成します。これは上級のチュートリアル — カスタムフォームウィジェットの作成方法 — で扱います。

+ +

メールアドレスフィールド

+ +

このフィールドタイプは {{htmlattrxref("type","input")}}属性の email の値でセットされます:

+ +
<input type="email" id="email" name="email">
+ +

この {{htmlattrxref("type","input")}} が使われたとき、ユーザーは有効なメールアドレスをフィールドに入力することが必須です。その他のコンテンツでは、ブラウザーによってフォーム送信時にエラーが表示されます。この動作は下記のスクリーンショットで見ることができます。

+ +

An invalid email input showing the message "Please enter an email address."

+ +

email 入力タイプと multiple 属性を組み合わせて、複数のメールアドレスが同じ入力に (カンマ区切りで)入力させることもできます:

+ +
<input type="email" id="email" name="email" multiple>
+ +

いくつかの端末 — 特にスマートフォンのような動的キーボードつきのタッチデバイス — では、@ キーを含むメールアドレス入力に適した別の仮想キーパッドが現れることもあります。Android 版 Firefox のキーボードの例として下記のスクリーンショットを見てください:

+ +

firefox for android email keyboard, with ampersand displayed 既定では.

+ +
+

: 基本的なテキスト入力タイプの例は basic input examples にあります(ソースコード も見てください)。

+
+ +

これは新しい入力タイプを使う良い理由であり、こうした端末のユーザーのユーザー体験を向上させます。

+ +

クライアント側の検証

+ +

上で見てきたように、他の新しい input タイプと同様に、email は組み込みのクライアント側のエラー検証 — データがサーバーに送られる前にブラウザーで実行されるもの — があります。これはユーザーが正確に入力するのに役立ち、時間を短縮できます — データが正しくないことをサーバーとのラウンドトリップを待つことなくすぐに知ることは便利です。

+ +

しかしこれは完全なセキュリティ対策と考えるべきではありません! アプリは送信データのセキュリティ確認をクライアント側と同様にサーバー側でも行うべきで、なぜならクライアント側の検証は簡単にオフにできるため悪意のあるユーザーは簡単にサーバーに不正なデータを送信できるためです。起こりうることについては Website security を読んで下さい。サーバー側の検証を実装するのはこのモジュールの範囲を超えていますが、記憶しておくべきです。

+ +

既定の制約では a@b は有効なメールアドレスです。これは既定では email 入力タイプはイントラネットのメールアドレスを許可しているためです。異なる検証動作を実装するには、pattern 属性を用いたり、エラーメッセージをカスタムできます。この機能の使い方は後の クライアント側検証の記事で話します。

+ +
+

: 入力データがメールアドレスでない場合、{{cssxref(':invalid')}} 疑似クラスがマッチして、{{domxref('validityState.typeMismatch')}} プロパティは true を返します。

+
+ +

検索フィールド

+ +

検索フィールドは、ページやアプリの検索ボックス作成に使われるものです。このフィールドタイプは {{htmlattrxref("type","input")}}属性の search の値でセットされます:

+ +
<input type="search" id="search" name="search">
+ +

text フィールドと search フィールドの主な違いは、ブラウザーの見た目のスタイル設定方法です。よく、search フィールドは角丸で描画されます。また時折、値がクリックされたときに値をクリアする "Ⓧ"も表示されます。その他、ダイナミックキーボードのある端末では、キーボードの enter キーが "検索"、あるいは虫眼鏡アイコンで表示されることもあります。

+ +

下記のスクリーンショットでは macOS での Firefox 71, Safari 13, Chrome 79 と Windoes10 での Edge 18 と Chrome 79 での文字が入った検索フィールドを表示しています。注意として、クリアのアイコンはフィールドに値が入った場合のみ表示され、Safari を除いてフィールドにフォーカスが当たった場合のみ表示されます。

+ +

Screenshots of search fields on several platforms.

+ +

もう 1 つの注目すべき機能として、search フィールドの値は同一サイトの複数ページにまたがって、自動保存してオートコンプリートすることができます。これはたいていのモダンブラウザーでは自動的に起こる傾向があります

+ +

電話番号フィールド

+ +

{{htmlattrxref("type","input")}} 属性に tel の値を使って作られる電話番号の入力専用フィールド:

+ +
<input type="tel" id="tel" name="tel">
+ +

ダイナミックキーボードつきのタッチデバイスにアクセルしたとき、たいていの端末では type="tel" が出てくると数字のキーパッドを表示します、つまりこのタイプは数字キーパッドが使えるときに使えて、電話番号に使う必要があるだけではありません。

+ +

下記は Android 用 Firefox キーボードの例です:

+ +

firefox for android email keyboard, with ampersand displayed 既定では.

+ +

世界中にはいろいろな電話番号のフォーマットがあるため、このフィールドはユーザーが入力した値に制約を一切つけません (つまり、文字が入っていることなどがありえます)。

+ +

前に触れた通り、pattern 属性が制約を強化するのに使われて、これはクライアント側検証で学びます。

+ +

URL フィールド

+ +

{{htmlattrxref("type","input")}} 属性に url の値を使うことで作成できる URL 入力の専用フィールド:

+ +
<input type="url" id="url" name="url">
+ +

これはフィールドに特別な検証制約を追加します。ブラウザーは (http:のような) プロトコルがない場合や、URL の形式が良くない場合にエラーを報告します。ダイナミックキーボードのある端末ではよく、コロン、ピリオド、スラッシュの複数やすべてをデフォルトキーとして表示します。

+ +

例は下記のものを見てください (Android 用 Firefox の例):

+ +

firefox for android email keyboard, with ampersand displayed 既定では.

+ +
注: URL が正しい形式であっても、それが必ずしも実際存在する場所を参照しているとは限りません!
+ +

数値フィールド

+ +

{{HTMLElement("input")}} {{htmlattrxref("type","input")}} に number を指定して作成される数値入力用のコントロール。このコントロールはテキストフィールドのような見た目であるが、浮動小数値のみを許可し、通常は数値を増減するためのスピナー形式のボタンがあります。ダイナミックキーボードつきの端末では、一般的に数値キーボードが表示されます。

+ +

下記のスクリーンショット (Android 用 Firefox より) に例があります:

+ +

firefox for android email keyboard, with ampersand displayed 既定では.

+ +

number の入力タイプでは、{{htmlattrxref("min","input")}} と {{htmlattrxref("max","input")}} 属性をセットすることで最小値と最大値の制約をつけることができます。

+ +

スピナーボタンを押すことで増減させる増分を接とするのに step 属性を使うこともできます。既定では、number 入力タイプは数値が整数値の場合のみ検証します。浮動小数を許可するには、step="any"を指定します。省略された場合、step 値は既定で 1 となり、つまりすべての数値が有効です。

+ +

いくつか例を見てみましょう。次の最初の例では値が 110 の間に制限され、増減ボタンで値が 2 ずつ変更される数値コントロールを作成しています。

+ +
<input type="number" name="age" id="age" min="1" max="10" step="2">
+ +

2 つ目の例では値が 01 の間に制限され、増減ボタンで値が 0.01 ずつ変更される数値コントロールを作成しています。

+ +
<input type="number" name="change" id="pennies" min="0" max="1" step="0.01">
+ +

number 入力タイプは有効な値の範囲に制限されているときに意味を持ちます。例えば、ある人の年齢や身長です。範囲が大きすぎて増分が意味をなさない場合 (例えば USA の郵便番号は、00001 から 99999 の範囲です)、tel タイプがより良い選択となることもあります。これは数値のスピナーUI機能に対して、数値キーパッドを提供します。

+ +
+

: number 入力は Internet Explorer の 10 より前のバージョンではサポートされません。

+
+ +

スライダーコントロール

+ +

数字を選ぶもう1つの方法はスライダーです。家造りのようなサイトで資産の価格をフィルターするのによく見ることでしょう。これを示す例をライブで見てみましょう:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/range-example/index.html", '100%', 200)}}

+ +

使用からすると、スライダーはテキストフィールドより不正確です。このため、正確な値が必ずしも重要でない数値の選択に使われます。

+ +

スライダーは {{HTMLElement("input")}} に {{htmlattrxref("type","input")}} 属性を range にセットして作成します。スライダーはマウスやタッチや、キーパッドの矢印で移動できます。

+ +

スライダーを適切に設定するのは重要です。そのためには、それぞれ最小、最大、増分値を設定する min, max, step 属性を設定するのを強くお奨めします。

+ +

上の例の背後にあるコードを見て、どのように実現されるかを見てみましょう。まずは基本となる HTML:

+ +
<label for="price">Choose a maximum house price: </label>
+<input type="range" name="price" id="price" min="50000" max="500000" step="100" value="250000">
+<output class="price-output" for="price"></output>
+ +

この例では、値が 50000500000 までの範囲で、100 ずつ増減するスライダーを作成しています。デフォルトの値は value 属性を使って 250000 としています。

+ +

スライダーについての問題は、現在の値がいくつなのかのフィードバックが一切ないことです。これは、現在の値を入れている {{htmlelement("output")}} 要素を導入する理由です (この要素は次の記事でも見ていきます)。入力値や、あらゆる要素内の計算結果を表示できますが、<output> は特別です — <label>のように — for 属性を取って要素や出力値の元となる要素と関連付けることができます。

+ +

実際に現在の値を表示して、変更時に更新するには、JavaScript を使う必要がありますが、比較的に簡単です:

+ +
const price = document.querySelector('#price');
+const output = document.querySelector('.price-output');
+
+output.textContent = price.value;
+
+price.addEventListener('input', function() {
+  output.textContent = price.value;
+});
+ +

ここでは range 入力と output を 2 つの変数に保存しています。次に outputtextContent を入力の value ですぐにセットします。最後に、イベントリスナーをセットして、range スライダーが移動するといつも、outputtextContent を新しい値に更新します。

+ +
+

: range 入力は Internet Explorer 10以前のバージョンではサポートされません。

+
+ +

日付と時刻ピッカー

+ +

日付と時刻の値を集めるのはウェブ開発者にとってずっと悪夢でした。すばらしいユーザー体験のためには、カレンダー選択UIを与えるのが重要であり、それによってユーザーはネイティブのカレンダーアプリへのコンテキストスイッチや、パースするのが難しい違うフォーマットで入力する可能性を避けて日付選択ができます。前の千年紀の最後の分は、次のようにいろいろな表現ができます。例えば: 1999/12/31, 23:59 or 12/31/99T11:59PM.

+ +

HTML 日付コントロールは、カレンダーウィジェットを提供して統一されたデータを作成し、この種類のデータを扱うことができます。

+ +

日付と時刻コントロールは{{HTMLElement("input")}} 要素と、日付か時間かその両方かを集めたいのかにあわせて適当な {{htmlattrxref("type","input")}} 属性を使って作成できます。非サポートブラウザーで{{htmlelement("select")}} 要素にフォールバックするライブの例は次の通り:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/datetime-local-picker-fallback/index.html", '100%', 200)}}

+ +

利用できるいろいろなタイプを簡単に見ていきましょう。注意としては、このタイプの使用法はとても複雑で、特にブラウザーサポートを使う考えた場合そうです (下記を見てください); 完全な詳細情報は、各タイプのリファレンスページと、そこにある詳細な例を見てください。

+ +

datetime-local

+ +

<input type="datetime-local"> は特別なタイムゾーン情報のない日付と時刻を表示して選択するウィジェットを作成します。

+ +
<input type="datetime-local" name="datetime" id="datetime">
+ +

month

+ +

<input type="month"> は年と月を表示して選択するウィジェットを作成します。

+ +
<input type="month" name="month" id="month">
+ +

time

+ +

<input type="time"> は時刻の値を表示して選択するウィジェットを作成します。時刻は 12時間のフォーマットで表示されますが、戻り値は 24時間フォーマットです。

+ +
<input type="time" name="time" id="time">
+ +

week

+ +

<input type="week"> は本年の週の番号を表示して選択するウィジェットを作成します。

+ +

週は月曜始まりで日曜日で終わります。それに加えて、その年の最初の週はその年の最初の木曜日を含みます—これはその年の最初の日を含まないことも、前年の最後の数日を含むこともあります。

+ +
<input type="week" name="week" id="week">
+ +

date/time 値の制限

+ +

日付をと時刻のコントロールはすべて、minmax 属性で制約をつけることができて、さらに step 属性 (この値は入力タイプによって変わります)で追加の制約も可能です。

+ +
<label for="myDate">When are you available this summer?</label>
+<input type="date" name="myDate" min="2013-06-01" max="2013-08-31" step="7" id="myDate">
+ +

date/time 入力のブラウザーサポート

+ +

日付と時刻のウィジェットに最良のブラウザーサポートがないことに注意するべきです。現状では、Chrome, Edge, Opera ではよくサポートしていますが、Internet Explorerではサポートがなく、Safari にはモバイルのサポートがあり(しかしデスクトップサポートはなし)、Firefox では timedate のみサポートします。

+ +

上でリンクしているリファレンスページでは非サポートブラウザーでフォールバックするようプログラミングするヒントを提供しています; もう1つのオプションは日付選択を提供する JavaScript ライブラリの利用です。たいていのモダンなフレームワークには機能を利用できるコンポーネントがあり、またスタンドアローンのライブラリもあります (ヒントとなる Top date picker JavaScript plugins and libraries を見てください)。

+ +

色選択コントロール

+ +

色も扱いが難しいです。色の表現がたくさんあります: RGB 値 (10進数や16進数), HSL 値、キーワードなど。

+ +

color コントロールは {{HTMLElement("input")}} 要素を、 {{htmlattrxref("type","input")}} 属性に colorをつけて作成できます:

+ +
<input type="color" name="color" id="color">
+ +

サポートされている場合、色コントロールはOSのデフォルトの色選択機能を呼び出して選択できるようにする傾向があります。下記のスクリーンショットはmacOSの Firefox の例です:

+ +

firefox for android email keyboard, with ampersand displayed 既定では.

+ +

次のライブサンプルも試してみてください:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/color-example/index.html", '100%', 200)}}

+ +

戻り値は常に小文字で 6桁の16進数の色です。

+ +
+

: color 入力は Internet Explorerではサポートされていません。

+
+ +

スキルをテストしましょう!

+ +

この記事の最後に到着しましたが、最も大事な情報を覚えていますか?次に進む前に、この情報を保持しているか検証するテストがあります — Test your skills: HTML5 controls を見てください。

+ +

まとめ

+ +

ここで HTML5 フォーム入力タイプの旅が終了です。動作が特殊なため簡単に分類できないその他のコントロールタイプも少しあって、それを知るのも大事です。次の記事で扱います。

+ +

{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/html_forms_in_legacy_browsers/index.html b/files/ja/learn/forms/html_forms_in_legacy_browsers/index.html new file mode 100644 index 0000000000..edc9009df2 --- /dev/null +++ b/files/ja/learn/forms/html_forms_in_legacy_browsers/index.html @@ -0,0 +1,219 @@ +--- +title: 古いブラウザでの HTML フォーム +slug: Learn/Forms/HTML_forms_in_legacy_browsers +tags: + - Example + - Forms + - Guide + - HTML + - Intermediate + - Web +translation_of: Learn/Forms/HTML_forms_in_legacy_browsers +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms")}}
+ +

すべての Web 開発者は、Web が非常につらい場所であることをいち早く (時に痛いほど) 学びます。もっともいまいましいのは古いブラウザです。まあそれは受け入れて、我々が「古いブラウザ」と言うとき、みんなが古いバージョンの Internet Explorer を念頭に置いています...しかしそれだけではありません。ESR バージョンのような1年経過した Firefox もまた古いブラウザです。そしてモバイルの世界では? ブラウザも OS もアップデートできないときは?そう、最新ではない標準的なブラウザを搭載している多くの古い Android 携帯電話または iPhone があります。これらも古いブラウザです。

+ +

残念ながら、そのような困難に対処するのも仕事の一部です。幸い、古いブラウザによって起きる問題の 80% 程度を解決する助けになることがわかっている秘訣がいくつかあります。

+ +

問題について学ぶ

+ +

実のところもっとも重要なことは、一般的なパターンを理解するためにそれらのブラウザに関するドキュメントを読むことです。例えば、多くの場合 CSS のサポート状況が HTML フォームにおける最大の問題です。あなたはスタートとして適切な場所にいます。使用したい要素 (または DOM インターフェイス) のサポート状況を確認しましょう。MDN では Web ページで使用できる多くの要素、プロパティあるいは API について、実装状況の一覧表を入手できます。しかし、驚くほど役に立つであろうリソースが他にもあります:

+ +

ブラウザベンダーのドキュメント

+ + + +

独自のドキュメント

+ + + +

物事をシンプルに

+ +

HTML フォームは複雑なやりとりを伴うことから、一つの経験則があります: 可能な限りシンプルにしてください (日本語版)。フォームを "より立派に" あるいは "高機能に" したいケースはたくさんありますが、効率的なフォームの作成はデザインや技術の問題ではありません。それを忘れないように、UX For The Masses にあるフォームのユーザビリティに関する記事を読む時間をとってください。

+ +

Graceful Degradation は Web 開発者の最高の味方

+ +

Graceful Degradation と Progressive Enhancement は、一度に幅広いブラウザをサポートすることにより、すばらしいものを構築可能にする開発パターンです。新しいブラウザで何かを構築するときにそれが動作すると確信したい場合は、あれやこれやで古いブラウザにおいて Graceful Degradation を行っています。

+ +

HTML フォームに関する例をいくつか見ていきましょう。

+ +

HTML input のタイプ

+ +

HTML5 でもたらされた新たな input のタイプは、退行手段がとてもわかりやすいことから、すばらしいものです。ブラウザが {{HTMLElement("input")}} 要素の {{htmlattrxref("type","input")}} 属性の値を知らない場合は、値が text であるかのようにフォールバックします。

+ +
<label for="myColor">
+  Pick a color
+  <input type="color" id="myColor" name="color">
+</label>
+ + + + + + + + + + + + + + +
Chrome 24Firefox 18
Screen shot of the color input on Chrome for Mac OSXScreen shot of the color input on Firefox for Mac OSX
+ +

CSS 属性セレクタ

+ +

CSS の属性セレクタHTML フォーム でとても有用ですが、一部の古いブラウザはサポートしていません。その場合、慣例では type と同等の class で二重化します:

+ +
<input type="number" class="number">
+ +
input[type=number] {
+  /* こちらは一部のブラウザで機能しません */
+}
+
+input.number {
+  /* こちらはどのブラウザでも動作するでしょう */
+}
+ +

以下の記述では役に立たず (冗長であるため)、一部のブラウザで機能しない可能性があります:

+ +
input[type=number],
+input.number {
+  /* セレクタのひとつが理解できない場合は規則全体が無視されるため、
+     これは一部のブラウザで動作しません */
+}
+ +

フォームボタン

+ +

HTML フォームでボタンを定義する方法は 2 つあります:

+ + + +

{{HTMLElement("input")}} は、要素セレクタを使用して CSS を適用したい場合に若干難しいことになります:

+ +
<input type="button" class="button" value="click me">
+ +
input {
+  /* この規則は、input 要素で定義するボタンのデフォルトのレンダリングを無効にします */
+  border: 1px solid #CCC;
+}
+
+input.button {
+  /* これはデフォルトのレンダリングを復元しません */
+  border: none;
+}
+
+input.button {
+  /* こちらも同様です! 実際は、あらゆるブラウザでこれを行う標準的な方法はありません */
+  border: auto;
+}
+ +

{{HTMLElement("button")}} 要素は、起こりうる 2 つの問題に悩まされます:

+ + + +
<!-- ボタンをクリックすると "A" ではなく "<em>Do A</em>" を送信する場合があります -->
+<button type="submit" name="IWantTo" value="A">
+  <em>Do A</em>
+</button>
+ +

プロジェクトの制約に基づいて、どちらの解決策を選択するかはあなた次第です。

+ +

CSS を手放そう

+ +

HTML フォームと古いブラウザにおける最大の問題は CSS のサポートです。Property compatibility table for form widgets の記事の複雑さからおわかりいただけるとおり、これはとても難しい問題です。テキスト系の要素でいくらか調整が (サイズや文字色など) 可能であるとしても、それらには必ず副作用があります。残された最善の方法は、HTML フォームのウィジェットに一切スタイルを設定しないことです。ただし、それでも周囲のアイテムにはスタイルを設定してもかまいません。もしあなたがプロフェッショナルで、顧客が要求するようなことがあれば、JavaScript によるウィジェットの再構築といった難易度が高い技術について調査してみるとよいでしょう。しかしそのような場合でも、顧客の愚かさを変えることをためらってはいけません。

+ +

機能検出とポリフィル

+ +

JavaScript は新しいブラウザにおいてすばらしい技術ですが、古いブラウザでは多くの問題を抱えています。

+ +

控えめな JavaScript

+ +

最大の問題のひとつは、API を利用できるかです。そのため、"{{原語併記("控えめな", "unobtrusive")}}" JavaScript によって取り組むことベストプラクティスであると考えられています。これは、2 つの要件によって定義される開発パターンです:

+ + + +

The principles of unobtrusive JavaScript (原文は Peter-Paul Koch 氏によって Dev.Opera.com 向けに記述され、現在は Docs.WebPlatform.org に移動しました) で、これらのアイデアを明快に説明しています。

+ +

Modernizr ライブラリ

+ +

欠けている API を提供することで、すばらしい "ポリフィル" が大きな助けになるケースが多数あります。ポリフィルは、古いブラウザにおける機能性の "穴を埋める" 小さな JavaScript コードです。ポリフィルは任意の機能のサポート状況を改善するために使用できますが、JavaScript 向けに使用するのは CSS や HTML 向けより低リスクです。JavaScript が動作しない可能性は多数あります(ネットワークの問題、スクリプトの競合 など)。しかし JavaScript については、控えめな JavaScript を念頭に置いて取り組む場合はポリフィルが欠けたとしても、重大な問題にはなりません。

+ +

欠けている API に対してポリフィルを適用する最善の方法は、Modernizr ライブラリおよびそこからスピンオフしたプロジェクトである YepNope を使用することです。Modernizr は、機能が利用できるかを確認して適宜対応を行えるようにするためのライブラリです。YepNope は、条件付きで読み込みを行うライブラリです。

+ +

サンプルは以下のとおりです:

+ +
Modernizr.load({
+  // ブラウザが HTML5 の form validation API をサポートしているかを確認します
+  test : Modernizr.formvalidation,
+
+  // ブラウザがサポートしない場合は、指定したポリフィルを読み込みます
+  nope : form-validation-API-polyfill.js,
+
+  // どの場合でも、API に依存するコアアプリのファイルを読み込みます
+  both : app.js,
+
+  // 両方のファイルを読み込んだら、アプリを初期化するためにこの関数を呼び出します
+  complete : function () {
+    app.init();
+  }
+});
+ +

好都合なことに、Modernizr チームはすばらしいポリフィルのリストを管理しています。必要なポリフィルを選びましょう。

+ +
+

注記: Modernizr は、控えめな JavaScript や Graceful Degradation のテクニックに取り組むことを支援するためのすばらしい機能を搭載しています。Modernizr のドキュメントをご覧ください。

+
+ +

パフォーマンスに注意を払う

+ +

Modernizr のようなスクリプトはパフォーマンスを非常に意識していますが、200キロバイトのポリフィルをロードするとアプリケーションのパフォーマンスに影響を与えます。これは従来のブラウザでは特に重要です。多くは JavaScript エンジンが非常に遅く、すべての polyfill の実行はユーザにとって苦痛になります。パフォーマンスはそれ自体が課題ですが、従来のブラウザはそれに非常に敏感です。基本的にそれらは遅く、より多くのポリフィルが必要で、より多くの JavaScript を処理する必要があります。そのため現代のブラウザと比較して二重の負担をかけていることになります。従来のブラウザでコードをテストして、実際のパフォーマンスを確認しましょう。場合によっては、一部の機能を削除すると、すべてのブラウザでまったく同じ機能を使用するよりも優れたユーザーエクスペリエンスが得られます。最後に念のため、常にエンドユーザのことを考えるようにしてください。

+ +

おわりに

+ +

お分かりのように、従来のブラウザを扱うことは単にフォームに関することだけではありません。テクニック一式です。 しかし、それらすべてをマスターすることは、この記事の範囲を超えています。

+ +

この HTML フォームガイドのすべての記事を読んでいれば、フォームの使用に慣れているはずです。新しいテクニックやヒントを見つけた場合は、ガイドの改善にご協力ください。

+ +

{{PreviousMenuNext("Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms/Styling_HTML_forms", "Learn/HTML/Forms")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/forms/index.html b/files/ja/learn/forms/index.html new file mode 100644 index 0000000000..aa428b7db7 --- /dev/null +++ b/files/ja/learn/forms/index.html @@ -0,0 +1,96 @@ +--- +title: HTML フォーム +slug: Learn/Forms +tags: + - Beginner + - Featured + - Forms + - Guide + - HTML + - Landing + - Learn + - Web +translation_of: Learn/Forms +--- +
{{LearnSidebar}}
+ +

このモジュールでは、ウェブフォームの習得に役立つ一連の記事をそろえています。ウェブフォームは、ユーザーとやり取りするための強力なツールです — 通常、ユーザーデータを集めたり、ユーザーインターフェイスの制御に使われてきました。しかし歴史的および技術的な理由から、その能力を十分に生かして使用する方法は、必ずしも明確とは限りません。このガイドではウェブフォームの構造からスタイル、データの検証やサーバーへの送信まであらゆる本質的な側面を取り上げます。

+ +

前提条件

+ +

このモジュールを始める前に、少なくとも HTML 入門を一通り読んでおくべきです。ここでは簡単に理解できる{{anch("Introductory guides", "導入ガイド")}}が見つかり、ネイティブフォームコントロールガイドも利用できます。

+ +

しかしそれ以外のモジュールは HTML 知識よりも少し高度です — ページにフォームウィジェットを置くのは簡単ですが、高度なフォームの機能や CSS や JavaScript を使わないと実際に活用できません。このため、その他の節を見る前にまずは CSSJavaScript を学んでおくのをお勧めします。

+ +

上記のテキストは、ウェブフォームを HTML、CSS、JavaScript エリアに混ぜずに、独立したモジュールに置くことの良い指針です — フォーム要素は HTML要素より複雑で、最大限利用するには、関連する CSS と JavaScript テクニックを最大限活用する。

+ +
+

: 自分のファイルを作ることができないコンピューター/タブレット/その他の端末で作業している場合、(大半の) コード例を JSBinGlitch といったオンラインコーディングプログラムで試すことができます。

+
+ +

導入ガイド

+ +
+
初めてのウェブフォーム
+
このシリーズの最初の記事では ウェブフォーム作成のほんの最初を提供し、それには簡単なフォームのデザインや、適切な HTML 要素で実装することや、CSS で簡単なスタイルづけをすることや、データがサーバーに送られる方法などが含まれます。
+
HTML フォームの構築方法
+
基本的な話と共に、ここではフォームの色々な部分に構造と意味を与えるのに使う要素を詳しく見ていきます。
+
+ +

どんなフォームウィジェットが利用できますか?

+ +
+
ネイティブフォームウィジェット
+
オリジナルの HTML {{htmlelement("input")}}タイプの詳細や、色々なデータ型を集めるのにどんなオプションが使えるかを見ていきます。
+
HTML5 入力タイプ
+
ここでは <input> 要素を深く見ていき、HTML5 リリースにて追加された入力タイプや、さまざまな UI コントロールとデータコレクションの改良を見ます。さらには、{{htmlelement('output')}} 要素も見ます。
+
その他のフォームコントロール
+
次には<input> 以外のフォームコントロールと関連するツール、例えば {{htmlelement('select')}}、{{htmlelement('textarea')}}、{{htmlelement('meter')}}、{{htmlelement('progress')}} を見ていきます。
+
+ +

フォームのスタイルガイド

+ +
+
ウェブフォームをスタイリングする
+
この記事では基本的なスタイリング作業のために知るべき基本を含む、フォームを CSS でスタイリングするための入門を紹介します。
+
ウェブフォームの高度なスタイリング
+
ここでは、スタイルが難しい要素を扱うために必要な、さらに高度なフォームスタイリングテクニックを紹介します。
+
UI 擬似クラス
+
現在の状態に応じて制御される HTML フォームコントロールを可能とする、UI 擬似クラス の入門です。
+
+ +

フォームデータを検証して送信する

+ +
+
クライアント側のフォームデータ検証
+
データ送信だけで充分ではありません — ユーザーがフォームに記入したデータが、我々が処理に成功するような正しいフォーマットであり、アプリケーションが破綻しないかを確認する必要があります。またユーザーが正しくフォームを記入してアプリを使うのにイライラしないよう手助けしたいです。フォーム検証はこの目的を達成するのに役立ちます — この記事では知っておくべきことを教えます。
+
フォームデータの送信
+
この記事ではユーザーがフォームを送信するときに何が起こるのかを見ます — データがどこに行くのか、そしてそこでデータを受けたらどう扱うかなどです。また、フォームデータ送信に関連するセキュリティ上の懸念もその一部です。
+
+ +

高度なガイド

+ +

下記の記事は学習コースに必須ではないですが、上記のテクニックをマスターしてそれ以上知りたいときには、興味深く役立つものでしょう。

+ +
+
カスタムフォームコントロールの作成方法
+
場合によってはネイティブのフォームウィジェットが必要となるものを提供していないことがあるでしょう。例えばスタイリングや機能で。この場合、生の HTML から自分自身のフォームウィジェットを作る必要があります。この記事ではその方法と考慮すべき点を、実際のケーススタディと一緒に説明します。
+
JavaScript によるフォームの送信
+
この記事では、標準フォームの送信ではなく、カスタム JavaScript 内で HTTP リクエストを組み立てて送る方法を見ます。またそうしたい理由と、そうする意味も見ていきます(FormData オブジェクトの使用もご覧ください)。
+
+ +
+
フォームコントロール用の CSS プロパティ互換性テーブル
+
この最後の記事では、どの CSS プロパティがフォーム要素に互換性があるのかを引くことのできるハンディリファレンスを提供します。
+
+ +
+
+ +

関連情報

+ + diff --git a/files/ja/learn/forms/other_form_controls/index.html b/files/ja/learn/forms/other_form_controls/index.html new file mode 100644 index 0000000000..6c6f825de4 --- /dev/null +++ b/files/ja/learn/forms/other_form_controls/index.html @@ -0,0 +1,333 @@ +--- +title: その他のフォームコントロール +slug: Learn/Forms/Other_form_controls +tags: + - Beginner + - Controls + - Example + - Forms + - Guide + - HTML + - Web + - Widgets +translation_of: Learn/Forms/Other_form_controls +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/Forms/HTML5_input_types","Learn/Forms/Styling_HTML_forms", "Learn/Forms")}}
+ +

ドロップダウンリストや複数行のテキストフィールドから、{{htmlelement('output')}}要素(前の記事で見ました)やプログレスバーといったその他の役立つ機能まで、非-<input> 型のフォーム要素の機能を詳しく見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーと、HTML の基本的な理解。
目的:非-<input> 型のフォーム機能と、HTML を用いた実装方法の理解。
+ +

複数行のテキストフィールド

+ +

複数行のテキストフィールドは、{{HTMLElement("input")}}要素ではなく{{HTMLElement("textarea")}} 要素で指定されます。

+ +
<textarea cols="30" rows="8"></textarea>
+ +

これは次のように描画されます:

+ +

{{EmbedLiveSample("Multi-line_text_fields", 120, 120)}}

+ +

 <textarea> と通常の単一行テキストフィールドとの主な違いは、ユーザーが送信データの中に改行を (リターンを押すことで) 入れることができます。

+ +

<textarea> は閉じタグを取ることができて、既定のテキストは開始タグと終了タグの間にあるべきです。これに対し、{{HTMLElement("input")}} は閉じタグのない空要素です — value 属性の中に既定の値が入ります。

+ +

注意として、<textarea> 要素 (その他の HTML 要素、CSS、JavaScript を含む)には何でも入れられるものの、この性質により、プレーンテキストコンテンツのように描画されます(非フォームコントロールでの contenteditable を使うと、プレーンテキストの代わりに HTML/リッチコンテンツの API を使用できます)。

+ +

視覚的には、入力テキストは改行されて、既定ではフォームコントロールはリサイズ可能です。モダンブラウザーにはテキストエリアのサイズを増減できるドラッグハンドルがあります。

+ +

下記のスクリーンショットは macOS での Firefox 71 と Safari 13 、Windows10 での Edge 18, Yandex 14, Firefox 71, Chrome 79 における既定の、フォーカスされた、無効な<textarea> 要素を表示しています。

+ +

The default, focused, and disabled <textarea> element in Firefox 71 and Safari 13 on Mac OSX and Edge 18, Yandex 14, Firefox and Chrome on Windows 10.

+ +
+

: 多少は面白いテキストエリアの使用例は、このシリーズの最初の記事の が見つかります (ソースコードも見てください)。

+
+ +

複数行レンダリングの制御

+ +

{{htmlelement("textarea")}} では、複数行にまたがってレンダリングするのを制御する 3 つの属性を受け付けます:

+ +
+
{{htmlattrxref("cols","textarea")}}
+
テキストコントロールの (カラム) 幅を、平均的なキャラクター幅で指定します。これは <textarea>をリサイズすることで変更でき、また CSS で上書きもできるため、有効な開始時の幅です。何も指定されていない場合、デフォルト値は 20 です。
+
{{htmlattrxref("rows","textarea")}}
+
コントロールの行数を指定します。これは <textarea>をリサイズすることで変更でき、また CSS で上書きもできるため、有効な開始時の高さです。何も指定されていない場合、デフォルト値は 2 です。
+
{{htmlattrxref("wrap","textarea")}}
+
コントロールがどのようにテキストを改行するかを制御します。値は soft (デフォルト値)、この値では送信されるテキストは改行されないが、ブラウザーでレンダリングされるテキストは改行される、hard (この値を使うには cols 属性を指定する必要がある)、この値では送信テキストとレンダリングされるテキストの両方が改行される、off、この値では改行が停止、を取ります。
+
+ +

テキストエリアのリサイズの制御

+ +

<textarea> をリサイズできるかは CSS の resize プロパティで制御されます。とりうる値は次の通り:

+ + + +

これがどのように動作するのかのデモは、{{cssxref("resize")}} リファレンスページの最初にあるインタラクティブな例で遊んでみてください。

+ + + +

ドロップダウン コントロールは、ユーザー インターフェイスのスペースをあまり取らずに、ユーザーがさまざまなオプションから選択できるようにするためのシンプルな方法です。HTML には、選択ボックスオートコンプリート ボックスという 2 つの形式のドロップダウン コンテンツがあります。どちらの場合も相互作用は同じです。コントロールを有効にすると、ブラウザーにはユーザーが選択できる値のリストが表示されます。

+ +
+

: すべてのドロップダウンボックスの例は、GitHub の drop-down-content.html にあります (ライブでもご覧ください)。

+
+ +

選択ボックス

+ +

単純なセレクトボックスは、1 つ以上の {{HTMLElement("option")}} 要素を子要素として持つ {{HTMLElement("select")}}要素で作成され、それぞれが可能な値のうちの 1 つを指定します。

+ +
+
<select id="simple" name="simple">
+  <option>Banana</option>
+  <option selected>Cherry</option>
+  <option>Lemon</option>
+</select>
+
+ +

{{EmbedLiveSample("Simple", 120, 120)}}

+ +

必要に応じて、希望する {{HTMLElement("option")}}要素の{{htmlattrxref("selected", "option")}}属性を用いて、セレクトボックスのデフォルト値を設定することができます。
+ - このオプションは、ページが読み込まれたときにあらかじめ選択されています。

+ +

{{HTMLElement("option")}}要素は、{{HTMLElement("optgroup")}}要素の中に入れ子にすることができ、視覚的に関連付けられた値のグループを作成することができます。

+ +
+
<select id="groups" name="groups">
+  <optgroup label="fruits">
+    <option>Banana</option>
+    <option selected>Cherry</option>
+    <option>Lemon</option>
+  </optgroup>
+  <optgroup label="vegetables">
+    <option>Carrot</option>
+    <option>Eggplant</option>
+    <option>Potato</option>
+  </optgroup>
+</select>
+
+ +

{{EmbedLiveSample("groups", 120, 120)}}

+ +

{{HTMLElement("optgroup")}}要素では、label属性の値が入れ子になったオプションの値の前に表示されます。ブラウザーは通常、それらをオプションから視覚的に離して(すなわち太字にしたり、入れ子レベルを変えたりして)表示しますので、実際のオプションと混同される可能性は低くなります。

+ +

{{HTMLElement("option")}}要素に明示的な value属性が設定されている場合、そのオプションが選択された状態でフォームが送信された時にその値が送信されます。上の例のように value属性を省略した場合は、{{HTMLElement("option")}}要素の内容が値として使われます。そのため、value属性は必要ありませんが、セレクトボックスに視覚的に表示されている値とは異なる値を短くしたり、サーバーに送信したい理由があるかもしれません。

+ +

例えば、:

+ +
<select id="simple" name="simple">
+  <option value="banana">Big, beautiful yellow banana</option>
+  <option value="cherry">Succulent, juicy cherry</option>
+  <option value="lemon">Sharp, powerful lemon</option>
+</select>
+ +

デフォルトでは、選択ボックスの高さは、単一の値を表示するのに十分です。オプションの size 属性は、セレクトにフォーカスがない場合に表示されるオプションの数を制御します。

+ +

複数選択の選択ボックス

+ +

デフォルトでは、セレクトボックスは、ユーザーに単一の値を選択 さ せ る だけです。{{HTMLElement("select")}}要素に{{htmlattrxref("multiple", "select")}}属性を追加することで、オペレーティングシステムが提供するデフォルトのメカニズム(例えば、Cmd/Ctrl を押しながらデスクトップ上で複数の値をクリックするなど)を使用して、ユーザーが複数の値を選択できるようにすることができます。

+ +
<select id="multi" name="multi" multiple size="2">
+  <optgroup label="fruits">
+     <option>Banana</option>
+     <option selected>Cherry</option>
+     <option>Lemon</option>
+   </optgroup>
+   <optgroup label="vegetables">
+     <option>Carrot</option>
+     <option>Eggplant</option>
+     <option>Potato</option>
+   </optgroup>
+</select>
+ +

{{EmbedLiveSample("Multiple_choice_select_box", 120, 120)}}

+ +
+

: 複数選択可能なセレクトボックスの場合、セレクトボックスはドロップダウンコンテンツとして値を表示しないことに気づくでしょう - 代わりに、すべての値がリストに一度に表示され、オプションの size属性はウィジェットの高さを決定します。

+
+ +
注: {{HTMLElement("select")}}要素をサポートするすべてのブラウザーは、{{htmlattrxref("multiple", "select")}}属性もサポートしています。
+ +

オートコンプリートのボックス

+ +

You can provide suggested, automatically-completed values for form widgets using 表示する値を指定する {{HTMLElement("option")}} 子要素つきの {{HTMLElement("datalist")}} 要素を使って、フォームウィジェット用のオートコンプリートの提案値を提供できます。  <datalist> には idが必要です。

+ +

データリストは、 id の値が拘束するデータリストの値となる {{htmlattrxref("list","input")}} 属性を用いて、 {{htmlelement("input")}} 要素 (つまりtextemail の入力タイプ) に拘束されます。

+ +
+

データリストがフォームウィジェットに関連づけられると、オプションはユーザーが入力するオートコンプリートテキストに使われます。典型的には、これはユーザーが入力に打ち込んだものにマッチするドロップダウンボックスで表示されます。

+ +

例を見てみましょう。

+ +
<label for="myFruit">What's your favorite fruit?</label>
+<input type="text" name="myFruit" id="myFruit" list="mySuggestion">
+<datalist id="mySuggestion">
+  <option>Apple</option>
+  <option>Banana</option>
+  <option>Blackberry</option>
+  <option>Blueberry</option>
+  <option>Lemon</option>
+  <option>Lychee</option>
+  <option>Peach</option>
+  <option>Pear</option>
+</datalist>
+ +

{{EmbedLiveSample("first_autocomplete", 120, 120)}}

+
+ +

Datalist support and fallbacks

+ +

Almost all browsers support datalist, but if you are still supporting older browsers such as IE versions below 10, there is a trick to provide a fallback:

+ +
<label for="myFruit">What is your favorite fruit? (With fallback)</label>
+<input type="text" id="myFruit" name="fruit" list="fruitList">
+
+<datalist id="fruitList">
+  <label for="suggestion">or pick a fruit</label>
+  <select id="suggestion" name="altFruit">
+    <option>Apple</option>
+    <option>Banana</option>
+    <option>Blackberry</option>
+    <option>Blueberry</option>
+    <option>Lemon</option>
+    <option>Lychee</option>
+    <option>Peach</option>
+    <option>Pear</option>
+  </select>
+</datalist>
+
+ +

{{EmbedLiveSample("Datalist_support_and_fallbacks", 120, 120)}}

+ +

Browsers that support the {{HTMLElement("datalist")}} element will ignore all the elements that are not {{HTMLElement("option")}} elements, with the datalist working as expected. Old browsers that don't support the {{HTMLElement("datalist")}} element will display the label and the select box.

+ +

The following screenshot shows the datalist fallback as rendered in Safari 6:

+ +

Screenshot of the datalist element fallback with Safari on Mac OS

+ +

If you use this fallback, ensure the data for both the <input> and the <select> are collected server-side.

+ +

Less obvious datalist uses

+ +

According to the HTML specification, the {{htmlattrxref("list","input")}} attribute and the {{HTMLElement("datalist")}} element can be used with any kind of widget requiring a user input. This leads to some uses of it that might seem a little non-obvious.

+ +

例えば、in browsers that support {{htmlelement("datalist")}} on range input types, a small tick mark will be displayed above the range for each datalist {{htmlelement("option")}} value. You can see an implementation example of this on the <input type="range"> reference page.

+ +

And browsers that support {{htmlelement('datalist')}}s and <input type="color"> should display a customized palette of colors as the default, while still making the full color palette available.

+ +

In this case, different browsers behave differently from case to case, so consider such uses as progressive enhancement, and ensure they degrade gracefully.

+ +

その他のフォーム機能

+ +

There are a few other form features that are not as obvious as the ones we have already mentioned, but still useful in some situations, so we thought it would be worth giving them a brief mention.

+ +
+

: You can find the examples from this section on GitHub as other-examples.html (see it live also).

+
+ +

メーターとプログレスバー

+ +

Meters and progress bars are visual representations of numeric values.

+ +

Progress

+ +

A progress bar represents a value that changes over time up to a maximum value specified by the {{htmlattrxref("max","progress")}} attribute. Such a bar is created using a {{ HTMLElement("progress")}} element.

+ +
<progress max="100" value="75">75/100</progress>
+ +

{{EmbedLiveSample("Progress", 120, 120)}}

+ +

This is for implementing anything requiring progress reporting, such as the percentage of total files downloaded, or the number of questions filled in on a questionnaire.

+ +

The content inside the {{HTMLElement("progress")}} element is a fallback for browsers that don't support the element and for screen readers to vocalize it.

+ +

Meter

+ +

A meter bar represents a fixed value in a range delimited by {{htmlattrxref("max","meter")}} and {{htmlattrxref("min","meter")}} values. This value is visually rendered as a bar, and to know how this bar looks, we compare the value to some other set values:

+ + + +

All browsers that implement the {{HTMLElement("meter")}} element use those values to change the color of the meter bar:

+ + + +

Such a bar is created using a {{HTMLElement("meter")}} element. This is for implementing any kind of meter, 例えば、a bar showing total space used on a disk, which turns red when it starts to get full.

+ +
<meter min="0" max="100" value="75" low="33" high="66" optimum="50">75</meter>
+ +

{{EmbedLiveSample("Meter", 120, 120)}}

+ +

The content inside the {{HTMLElement("meter")}} element is a fallback for browsers that don't support the element and for assistive technologies to vocalize it.

+ +

Support for {{HTMLElement("progress")}} and {{HTMLElement("meter")}} is fairly good — there is no support in Internet Explorer, but other browsers support it well.

+ +

スキルをテストしよう!

+ +

この記事の終わりまで到達しましたが、最も重要な情報を覚えていますか?次に移る前に、この情報を保持しているか検証するテストがあります — Test your skills: Other controls を見てください。

+ +

まとめ

+ +

最も後のいくつかの記事で見てきたように、利用できるフォーム要素にはいろいろな種類がたくさんあります。一見してすべてを詳しく覚えておく必要はなく、詳細について調べたいだけ、記事に戻ることができます。

+ +

いろいろなフォームコントロールの背後にある HTML をざっと理解したので、それらのスタイル設定について見ていきましょう。

+ +

{{PreviousMenuNext("Learn/Forms/HTML5_input_types","Learn/Forms/Styling_HTML_forms", "Learn/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/property_compatibility_table_for_form_controls/index.html b/files/ja/learn/forms/property_compatibility_table_for_form_controls/index.html new file mode 100644 index 0000000000..c24af4a732 --- /dev/null +++ b/files/ja/learn/forms/property_compatibility_table_for_form_controls/index.html @@ -0,0 +1,2017 @@ +--- +title: フォームウィジェット向けプロパティ実装状況一覧 +slug: Learn/Forms/Property_compatibility_table_for_form_controls +tags: + - Advanced + - CSS + - Forms + - Guide + - HTML + - NeedsUpdate + - Web + - ウェブ + - ガイド + - フォーム + - 高度 +translation_of: Learn/Forms/Property_compatibility_table_for_form_controls +--- +
{{learnsidebar}}
+ +

以下の実装状況一覧表で、 HTML フォーム向けの CSS の対応状況を要約しています。 HTML フォームや CSS の複雑さにより、これらの表は完全なリファレンスであるとはいえません。それでも、何ができて何ができないかの見識を得られるでしょう。また、どうすればよいかを知る助けにもなるでしょう。

+ +

表の見方

+ +

+ +

それぞれのプロパティで取り得る値は 4 種類あります。

+ +
+
Yes
+
プロパティは各ブラウザー間で、一貫してほどよく対応されています。もっとも、特殊なケースでは奇妙な副作用に直面するかもしれません。
+
Partial
+
プロパティは動作しますが、たびたび奇妙な副作用や一貫性のなさに直面するかもしれません。まず副作用について熟知しているのでなければ、これらのプロパティは避けるべきでしょう。
+
No
+
プロパティは動作しない、または頼りにできるほどの一貫性がありません。
+
n.a.
+
当該ウィジェットに対して、そのプロパティは意味がありません。
+
+ +

レンダリング

+ +

それぞれのプロパティで可能なレンダリング方法は 2 種類あります:

+ +
+
N (Normal)
+
プロパティをそのまま適用することを表します。
+
T (Tweaked)
+
下記の追加ルールとともにプロパティを適用することを表します:
+
+ +
* {
+/* これは、WebKit ベースのブラウザーでネイティブのルックアンドフィールを無効にします */
+  -webkit-appearance: none;
+  appearance: none;
+
+/* Internet Explorer用 */
+  background: none;
+}
+ +

実装状況一覧表

+ +

全体的な動作

+ +

全体的なレベルで多くのブラウザーに共通する動作があります:

+ +
+
{{cssxref("border")}}, {{cssxref("background")}}, {{cssxref("border-radius")}}, {{cssxref("height")}}
+
これらのプロパティのいずれかを使用すると、一部のブラウザーでネイティブのルックアンドフィールが部分的に、あるいは全面的に無効になることがあります。これらを使用する際は注意してください。
+
{{cssxref("line-height")}}
+
このプロパティの対応状況は各ブラウザー間で一貫性がありませんので、避けるべきでしょう。
+
{{cssxref("text-decoration")}}
+
このプロパティはフォームウィジェットにおいて Opera が対応していません。
+
{{cssxref("text-overflow")}}
+
Opera、Safari および IE9 ではフォームウィジェットでこのプロパティに対応していません。
+
{{cssxref("text-shadow")}}
+
Opera は {{cssxref("text-shadow")}} をフォームウィジェットで対応していません。また、IE9 はまったく対応していません。
+
+ +

テキストフィールド

+ +

{{htmlelement("input/text", "text")}}, {{htmlelement("input/search", "search")}}, and {{htmlelement("input/password", "password")}} の入力タイプを見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}Partial[1][2]Yes +
    +
  1. WebKit ブラウザーは (主に Mac OSX や iOS で)、検索フィールドでネイティブのルックアンドフィールを使用します。従って、検索フィールドにこのプロパティを適用できるようにするために、-webkit-appearance:none を使用することが必要です。
  2. +
  3. Windows 7 で Internet Explorer 9 は、 background:none が適用されなければ境界を適用しません。
  4. +
+
{{cssxref("border")}}Partial[1][2]Yes +
    +
  1. WebKit ブラウザは (主に Mac OSX や iOS で)、検索フィールドでネイティブのルックアンドフィールを使用します。従って、検索フィールドにこのプロパティを適用できるようにするために、-webkit-appearance:none を使用することが必要です。
  2. +
  3. Windows 7 で Internet Explorer 9 は、background:none が適用されなければ境界を適用しません。
  4. +
+
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}Partial[1][2]Yes +
    +
  1. WebKit ブラウザは (主に Mac OSX や iOS で)、検索フィールドでネイティブのルックアンドフィールを使用します。従って、検索フィールドにこのプロパティを適用できるようにするために、-webkit-appearance:none を使用することが必要です。
  2. +
  3. Windows 7 で Internet Explorer 9 は、background:none が適用されなければ境界を適用しません。
  4. +
+
テキストとフォント
{{cssxref("color")}}[1]YesYes +
    +
  1. {{cssxref("border-color")}} プロパティが設定されていない場合、一部の WebKit ベースブラウザは {{htmlelement("textarea")}} において、フォントだけでなく境界にも {{cssxref("color")}} プロパティを適用します。
  2. +
+
{{cssxref("font")}}YesYes{{cssxref("line-height")}} の注意事項をご覧ください。
{{cssxref("letter-spacing")}}YesYes
{{cssxref("text-align")}}YesYes
{{cssxref("text-decoration")}}PartialPartialOpera に関する注意事項をご覧ください。
{{cssxref("text-indent")}}Partial[1]Partial[1] +
    +
  1. IE9 はこのプロパティを {{htmlelement("textarea")}} のみで、Opera は単一行のテキストフィールドのみで対応しています。
  2. +
+
{{cssxref("text-overflow")}}PartialPartial
{{cssxref("text-shadow")}}PartialPartial
{{cssxref("text-transform")}}YesYes
境界と背景
{{cssxref("background")}}Partial[1]Yes +
    +
  1. WebKit ブラウザは (主に Mac OSX や iOS で)、検索フィールドでネイティブのルックアンドフィールを使用します。従って、検索フィールドにこのプロパティを適用できるようにするために、-webkit-appearance:none を使用することが必要です。Windows 7 で Internet Explorer 9 は、background:none が適用されなければ境界を適用しません。
  2. +
+
{{cssxref("border-radius")}}Partial[1][2]Yes +
    +
  1. WebKit ブラウザは (主に Mac OSX や iOS で)、検索フィールドでネイティブのルックアンドフィールを使用します。従って、検索フィールドにこのプロパティを適用できるようにするために、-webkit-appearance:none を使用することが必要です。Windows 7 で Internet Explorer 9 は、background:none が適用されなければ境界を適用しません。
  2. +
  3. Opera では、明示的に境界が設定されている場合にのみ {{cssxref("border-radius")}} が適用されます。
  4. +
+
{{cssxref("box-shadow")}}NoPartial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
+ +

ボタン

+ +

{{htmlelement("input/button", "button")}}{{htmlelement("input/submit", "submit")}}, and {{htmlelement("input/reset", "reset")}} input types and the {{htmlelement("button")}} 要素を見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}Partial[1]Yes +
    +
  1. Mac OSX や iOS では、WebKit ベースブラウザでこのプロパティが適用されません。
  2. +
+
{{cssxref("border")}}PartialYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}Partial[1]Yes +
    +
  1. Mac OSX や iOS では、WebKit ベースブラウザでこのプロパティが適用されません。
  2. +
+
テキストとフォント
{{cssxref("color")}}YesYes
{{cssxref("font")}}YesYes{{cssxref("line-height")}} の注意事項をご覧ください。
{{cssxref("letter-spacing")}}YesYes
{{cssxref("text-align")}}NoNo
{{cssxref("text-decoration")}}PartialYes
{{cssxref("text-indent")}}YesYes
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}PartialPartial
{{cssxref("text-transform")}}YesYes
境界と背景
{{cssxref("background")}}YesYes
{{cssxref("border-radius")}}Yes[1]Yes[1] +
    +
  1. Opera では、明示的に境界が設定されている場合にのみ {{cssxref("border-radius")}} が適用されます。
  2. +
+
{{cssxref("box-shadow")}}NoPartial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
+ +

数値

+ +

 {{htmlelement("input/number", "number")}} 入力タイプを見てください。フィールドの値の変更に使用するスピンボタンのスタイルを変更するための、標準的な方法はありません。Safari では、スピンボタンがフィールドの外部にあることは知っておくべきです。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}Partial[1]Partial[1] +
    +
  1. Opera ではスピンボタンが拡大されて、フィールドの内容物を隠す場合があります。
  2. +
+
{{cssxref("border")}}YesYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}Partial[1]Partial[1] +
    +
  1. Opera ではスピンボタンが拡大されて、フィールドの内容物を隠す場合があります。
  2. +
+
テキストとフォント
{{cssxref("color")}}YesYes
{{cssxref("font")}}YesYes{{cssxref("line-height")}} の注意事項をご覧ください。
{{cssxref("letter-spacing")}}YesYes
{{cssxref("text-align")}}YesYes
{{cssxref("text-decoration")}}PartialPartial
{{cssxref("text-indent")}}YesYes
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}PartialPartial
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}NoNo +

対応していますが、ブラウザ間で頼りにできるほどの一貫性はありません。

+
{{cssxref("border-radius")}}NoNo
{{cssxref("box-shadow")}}NoNo
+ +

チェックボックスとラジオボタン

+ +

{{htmlelement("input/checkbox", "checkbox")}}{{htmlelement("input/radio", "radio")}} 入力タイプを見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}No[1]No[1] +
    +
  1. 一部のブラウザでは、マージンを追加したりウィジェットを引き伸ばしたりします。
  2. +
+
{{cssxref("height")}}No[1]No[1] +
    +
  1. 一部のブラウザでは、マージンを追加したりウィジェットを引き伸ばしたりします。
  2. +
+
{{cssxref("border")}}NoNo
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}NoNo
テキストとフォント
{{cssxref("color")}}N.A.N.A.
{{cssxref("font")}}N.A.N.A.
{{cssxref("letter-spacing")}}N.A.N.A.
{{cssxref("text-align")}}N.A.N.A.
{{cssxref("text-decoration")}}N.A.N.A.
{{cssxref("text-indent")}}N.A.N.A.
{{cssxref("text-overflow")}}N.A.N.A.
{{cssxref("text-shadow")}}N.A.N.A.
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}NoNo
{{cssxref("border-radius")}}NoNo
{{cssxref("box-shadow")}}NoNo
+ +

セレクトボックス (単一行)

+ +

{{htmlelement("select")}}{{htmlelement("optgroup")}}{{htmlelement("option")}} 要素を見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}Partial[1]Partial[1] +
    +
  1. このプロパティは {{htmlelement("select")}} 要素では問題ありませんが、 {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素では効果がありません。
  2. +
+
{{cssxref("height")}}NoYes
{{cssxref("border")}}PartialYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}No[1]Partial[2] +
    +
  1. プロパティは適用されますが、Mac OSX ではブラウザ間の一貫性がありません。
  2. +
  3. このプロパティは {{htmlelement("select")}} 要素には適用されますが、 {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素では処理に一貫性がありません。
  4. +
+
テキストとフォント
{{cssxref("color")}}Partial[1]Partial[1] +
    +
  1. Mac OSX では、WebKit ベースのブラウザがネイティブウィジェットでこのプロパティに対応せず、また {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素では Opera を含めてまったく対応していません。
  2. +
+
{{cssxref("font")}}Partial[1]Partial[1] +
    +
  1. Mac OSX では、WebKit ベースのブラウザがネイティブウィジェットでこのプロパティに対応せず、また {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素では Opera を含めてまったく対応していません。
  2. +
+
{{cssxref("letter-spacing")}}Partial[1]Partial[1] +
    +
  1. IE9 は {{HTMLElement("select")}}、 {{htmlelement("option")}} および {{htmlelement("optgroup")}} 要素でこのプロパティに対応していません。Mac OSX で WebKit ベースのブラウザは、 {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素でこのプロパティに対応していません。
  2. +
+
{{cssxref("text-align")}}No[1]No[1] +
    +
  1. Windows 7 で IE9 および Mac OSX で WebKit ベースのブラウザは、このウィジェットで本プロパティに対応していません。
  2. +
+
{{cssxref("text-decoration")}}Partial[1]Partial[1] +
    +
  1. Firefox のみがこのプロパティを完全対応しています。 Opera はこのプロパティに全く対応しておらず、また他のブラウザは {{htmlelement("select")}} 要素のみに対応しています。
  2. +
+
{{cssxref("text-indent")}}Partial[1][2]Partial[1][2] +
    +
  1. ほとんどのブラウザは、{{htmlelement("select")}} 要素のみでこのプロパティに対応しています。
  2. +
  3. IE9 はこのプロパティに対応していません。
  4. +
+
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}Partial[1][2]Partial[1][2] +
    +
  1. ほとんどのブラウザは、{{htmlelement("select")}} 要素のみでこのプロパティに対応しています。
  2. +
  3. IE9 はこのプロパティに対応していません。
  4. +
+
{{cssxref("text-transform")}}Partial[1]Partial[1] +
    +
  1. ほとんどのブラウザは、{{htmlelement("select")}}要素のみでこのプロパティに対応しています。
  2. +
+
境界と背景
{{cssxref("background")}}Partial[1]Partial[1] +
    +
  1. ほとんどのブラウザは、{{htmlelement("select")}}要素のみでこのプロパティに対応しています。
  2. +
+
{{cssxref("border-radius")}}Partial[1]Partial[1]
{{cssxref("box-shadow")}}NoPartial[1]
+ +

Firefox では{{htmlelement("select")}} 要素の下矢印を変更する方法はありません。.

+ +

セレクトボックス (複数行)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}YesYes
{{cssxref("border")}}YesYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}Partial[1]Partial[1] +
    +
  1. Opera は {{cssxref("padding-top")}} および {{cssxref("padding-bottom")}} に {{htmlelement("select")}} 要素で対応していません。
  2. +
+
テキストとフォント
{{cssxref("color")}}YesYes
{{cssxref("font")}}YesYes{{cssxref("line-height")}} の注意事項をご覧ください。
{{cssxref("letter-spacing")}}Partial[1]Partial[1] +
    +
  1. IE9 は {{htmlelement("select")}}{{htmlelement("option")}} および {{htmlelement("optgroup")}} 要素でこのプロパティに対応していません。Mac OSX で WebKit ベースのブラウザは、 {{htmlelement("option")}} 要素や {{htmlelement("optgroup")}} 要素でこのプロパティに対応していません。
  2. +
+
{{cssxref("text-align")}}No[1]No[1] +
    +
  1. Windows 7 で IE9 および Mac OSX で WebKit ベースのブラウザは、このウィジェットで本プロパティに対応していません。
  2. +
+
{{cssxref("text-decoration")}}No[1]No[1] +
    +
  1. Firefox および IE9 以上のみが対応しています。
  2. +
+
{{cssxref("text-indent")}}NoNo
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}NoNo
{{cssxref("text-transform")}}Partial[1]Partial[1] +
    +
  1. ほとんどのブラウザは、 {{htmlelement("select")}} 要素のみでこのプロパティに対応します。
  2. +
+
境界と背景
{{cssxref("background")}}YesYes
{{cssxref("border-radius")}}Yes[1]Yes[1] +
    +
  1. Opera では、明示的に境界が設定されている場合にのみ {{cssxref("border-radius")}} が適用されます。
  2. +
+
{{cssxref("box-shadow")}}NoPartial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
+ +

Datalist

+ +

  {{htmlelement("datalist")}} and {{htmlelement("input")}} 要素と list 属性を見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}NoNo
{{cssxref("height")}}NoNo
{{cssxref("border")}}NoNo
{{cssxref("margin")}}NoNo
{{cssxref("padding")}}NoNo
テキストとフォント
{{cssxref("color")}}NoNo
{{cssxref("font")}}NoNo
{{cssxref("letter-spacing")}}NoNo
{{cssxref("text-align")}}NoNo
{{cssxref("text-decoration")}}NoNo
{{cssxref("text-indent")}}NoNo
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}NoNo
{{cssxref("text-transform")}}NoNo
境界と背景
{{cssxref("background")}}NoNo
{{cssxref("border-radius")}}NoNo
{{cssxref("box-shadow")}}NoNo
+ +

ファイルピッカー

+ +

  {{htmlelement("input/file", "file")}} 入力タイプを見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}NoNo
{{cssxref("height")}}NoNo
{{cssxref("border")}}NoNo
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}NoNo
テキストとフォント
{{cssxref("color")}}YesYes
{{cssxref("font")}}No[1]No[1] +
    +
  1. 対応されていますが、ブラウザ間で頼りにできるほどの一貫性はありません。
  2. +
+
{{cssxref("letter-spacing")}}Partial[1]Partial[1] +
    +
  1. ほとんどのブラウザは、このプロパティを選択ボタンにも適用します。
  2. +
+
{{cssxref("text-align")}}NoNo
{{cssxref("text-decoration")}}NoNo
{{cssxref("text-indent")}}Partial[1]Partial[1] +
    +
  1. ウィジェットの外側に左マージンがあるような状態になります。
  2. +
+
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}NoNo
{{cssxref("text-transform")}}NoNo
境界と背景
{{cssxref("background")}}No[1]No[1] +
    +
  1. 対応されていますが、ブラウザ間で頼りにできるほどの一貫性はありません。
  2. +
+
{{cssxref("border-radius")}}NoNo
{{cssxref("box-shadow")}}NoPartial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
+ +

日付選択

+ +

{{htmlelement("input/date", "date")}}{{htmlelement("input/time", "time")}} 入力タイプを見てください。多くのプロパティが対応されていますが、ブラウザー間で頼りにできるほどの一貫性はありません。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}NoNo
{{cssxref("height")}}NoNo
{{cssxref("border")}}NoNo
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}NoNo
テキストとフォント
{{cssxref("color")}}NoNo
{{cssxref("font")}}NoNo
{{cssxref("letter-spacing")}}NoNo
{{cssxref("text-align")}}NoNo
{{cssxref("text-decoration")}}NoNo
{{cssxref("text-indent")}}NoNo
{{cssxref("text-overflow")}}NoNo
{{cssxref("text-shadow")}}NoNo
{{cssxref("text-transform")}}NoNo
境界と背景
{{cssxref("background")}}NoNo
{{cssxref("border-radius")}}NoNo
{{cssxref("box-shadow")}}NoNo
+ +

カラーピッカー

+ +

 {{htmlelement("input/color", "color")}} 入力タイプを見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}No[1]Yes +
    +
  1. Opera はこのプロパティを、select ウィジェットと同じ制限事項のもとに処理します。
  2. +
+
{{cssxref("border")}}YesYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}No[1]Yes +
    +
  1. Opera はこのプロパティを、select ウィジェットと同じ制限事項のもとに処理します。
  2. +
+
テキストとフォント
{{cssxref("color")}}N.A.N.A.
{{cssxref("font")}}N.A.N.A.
{{cssxref("letter-spacing")}}N.A.N.A.
{{cssxref("text-align")}}N.A.N.A.
{{cssxref("text-decoration")}}N.A.N.A.
{{cssxref("text-indent")}}N.A.N.A.
{{cssxref("text-overflow")}}N.A.N.A.
{{cssxref("text-shadow")}}N.A.N.A.
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}No[1]No[1] +
    +
  1. 対応されていますが、ブラウザ間で頼りにできるほどの一貫性はありません。
  2. +
+
{{cssxref("border-radius")}}No[1]No[1]
{{cssxref("box-shadow")}}No[1]No[1]
+ +

メーターとプログレスバー

+ +

{{htmlelement("meter")}}{{htmlelement("progress")}} 要素を見てください:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}YesYes
{{cssxref("border")}}PartialYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}YesPartial[1] +
    +
  1. Chrome は調整された (Tweaked) 状態の要素に {{cssxref("padding")}} プロパティが適用されていると、{{HTMLElement("progress")}} 要素や {{HTMLElement("meter")}} 要素を隠します。
  2. +
+
テキストとフォント
{{cssxref("color")}}N.A.N.A.
{{cssxref("font")}}N.A.N.A.
{{cssxref("letter-spacing")}}N.A.N.A.
{{cssxref("text-align")}}N.A.N.A.
{{cssxref("text-decoration")}}N.A.N.A.
{{cssxref("text-indent")}}N.A.N.A.
{{cssxref("text-overflow")}}N.A.N.A.
{{cssxref("text-shadow")}}N.A.N.A.
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}No[1]No[1] +
    +
  1. 対応されていますが、ブラウザ間で頼りにできるほどの一貫性はありません。
  2. +
+
{{cssxref("border-radius")}}No[1]No[1]
{{cssxref("box-shadow")}}No[1]No[1]
+ +

Range

+ +

{{htmlelement("input/range", "range")}} 入力タイプを見てください。スライダーのつまみのスタイルを変更するための標準的な方法はなく、また Opera ではウィジェットのデフォルトの表示を調整する方法がありません。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}Partial[1]Partial[1] +
    +
  1. Chrome や Opera はウィジェットの周りに余白を追加します。また Windows 7 の Opera では、スライダーのつまみが引き伸ばされます。
  2. +
+
{{cssxref("border")}}NoYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}Partial[1]Yes +
    +
  1. {{cssxref("padding")}} は適用されますが、視覚的な効果はありません。
  2. +
+
テキストとフォント
{{cssxref("color")}}N.A.N.A.
{{cssxref("font")}}N.A.N.A.
{{cssxref("letter-spacing")}}N.A.N.A.
{{cssxref("text-align")}}N.A.N.A.
{{cssxref("text-decoration")}}N.A.N.A.
{{cssxref("text-indent")}}N.A.N.A.
{{cssxref("text-overflow")}}N.A.N.A.
{{cssxref("text-shadow")}}N.A.N.A.
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}No[1]No[1] +
    +
  1. 対応されていますが、ブラウザ間で頼りにできるほどの一貫性はありません。
  2. +
+
{{cssxref("border-radius")}}No[1]No[1]
{{cssxref("box-shadow")}}No[1]No[1]
+ +

画像ボタン

+ +

{{htmlelement("input/image", "image")}} 入力タイプを見てください:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティNT備考
CSS ボックスモデル
{{cssxref("width")}}YesYes
{{cssxref("height")}}YesYes
{{cssxref("border")}}YesYes
{{cssxref("margin")}}YesYes
{{cssxref("padding")}}YesYes
テキストとフォント
{{cssxref("color")}}N.A.N.A.
{{cssxref("font")}}N.A.N.A.
{{cssxref("letter-spacing")}}N.A.N.A.
{{cssxref("text-align")}}N.A.N.A.
{{cssxref("text-decoration")}}N.A.N.A.
{{cssxref("text-indent")}}N.A.N.A.
{{cssxref("text-overflow")}}N.A.N.A.
{{cssxref("text-shadow")}}N.A.N.A.
{{cssxref("text-transform")}}N.A.N.A.
境界と背景
{{cssxref("background")}}YesYes
{{cssxref("border-radius")}}Partial[1]Partial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
{{cssxref("box-shadow")}}Partial[1]Partial[1] +
    +
  1. IE9 はこのプロパティに対応していません。
  2. +
+
+ +

{{PreviousMenu("Learn/HTML/Forms/Advanced_styling_for_HTML_forms", "Learn/HTML/Forms")}}

+ +

このモジュール

+ +

学習コース

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/sending_and_retrieving_form_data/index.html b/files/ja/learn/forms/sending_and_retrieving_form_data/index.html new file mode 100644 index 0000000000..7370945b88 --- /dev/null +++ b/files/ja/learn/forms/sending_and_retrieving_form_data/index.html @@ -0,0 +1,341 @@ +--- +title: フォームデータの送信 +slug: Learn/Forms/Sending_and_retrieving_form_data +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - HTTP + - Web + - セキュリティ + - ファイル + - フォーム +translation_of: Learn/Forms/Sending_and_retrieving_form_data +--- +
{{LearnSidebar}}{{PreviousMenu("Learn/Forms/Form_validation", "Learn/Forms")}}
+ +

フォームがクライアント側で検証されたら、フォームの送信は大丈夫です。前の記事では検証をカバーしたので、送信する準備はできています! この記事では、ユーザーがフォームを送信したときに何が起こるか、つまりデータがどこへ行くのか、そこに来たときにどう扱うのかを見ます。また、フォームデータの送信に関連するセキュリティの考慮事項のいくつかも見てみます。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー, HTML の理解, HTTP およびサーバーサイドプログラミングの基本的な知識。
目標:フォームデータが送信されたら何が起こるかを、データがサーバー上でどのように処理されるかの基本的な考えも含めて理解すること。
+ +

まずは、フォームが送信されたときにデータに何が起こるかを考えてみましょう。

+ +

クライアント/サーバー構成について

+ +

ウェブはごく基本的なクライアント/サーバー構成に基づいており、簡単に言うと次のようになります。クライアント (通常はウェブブラウザー) は HTTP プロトコルを使用して、サーバー (ほとんどの場合 ApacheNginxIISTomcat などのウェブサーバー) にリクエストを送ります。サーバーは同じプロトコルを使用して、リクエストに応答します。

+ +

基本的なクライアント/サーバー構成

+ +

クライアント側において、HTML フォームはサーバーへデータを送信する HTTP リクエストを組み立てるのための、便利でユーザーに使いやすい手段でしかありません。フォームによって、ユーザーが HTTP リクエストで渡す情報を提供することができるようになります。

+ +
+

メモ: どのようにクライアント/サーバー構成が動作するかについてもっと知りたい場合は、サーバーサイド Web サイトプログラミング入門モジュールをお読みください。

+
+ +

クライアント側: データ送信方法の定義

+ +

{{HTMLElement("form")}} 要素で、データを送信する方法を定義します。その属性すべてが、ユーザーが送信ボタンを押すと送信されるリクエストを調整できるように設計されています。もっとも重要な属性は {{htmlattrxref("action","form")}} と {{htmlattrxref("method","form")}} の 2 つです。

+ +

action 属性

+ +

action 属性は、どこにデータを送信するかを定義します。値は妥当な相対/絶対 URL でなければなりません。この属性が与えられなかった場合は、フォームが含まれているページの URL にデータが送信されます。

+ +

この例では、データを絶対 URL の http://example.com に送信します。

+ +
<form action="http://example.com">
+ +

こちらは、相対 URL を使用しています。データは同一オリジン上の別の URL に送信されます。

+ +
<form action="/somewhere_else">
+ +

以下のように属性を指定しない場合は、{{HTMLElement("form")}} 要素はフォームが表示されているページ自身に対してデータを送信します。

+ +
<form>
+ +
+

メモ: HTTPS (secure HTTP) プロトコルを使用して URL を指定することができます。このようにすると、フォーム自体が HTTP でアクセスされる安全ではないページで提供される場合でも、データはリクエストの残りの部分とともに暗号化されます。一方、フォームが安全なページ提供されていても、{{htmlattrxref("action","form")}} 属性で安全ではない HTTP の URL を指定すると、どのブラウザーでもデータを送信する際にユーザーに対してセキュリティの警告を表示します。これは、データが暗号化されないためです。

+
+ +

非ファイル型のフォームコントロールの名前/値は&記号で結合された name=value ペアでサーバーに送られます。action の値は、サーバー側の検証を含め入力データを扱うサーバーのファイルです。サーバーは応答して、一般的にはデータを処理して action 属性で定義された URL を読み込み、新しいページの読み込み (または action が同じページを指している場合は既存ページのリフレッシュ)を引き起こします。

+ +

データがどう送られるかは method 属性に依存します。

+ +

method 属性

+ +

method 属性は、どのようにデータを送信するかを定義します。HTTP プロトコルはリクエストを実行するための方法をいくつか提供しています。HTML フォームのデータは複数の方法で送信することができます。もっとも一般的なものは GET メソッドと POST メソッドです。

+ +

これら2つのメソッドの違いを理解するために、一歩戻って HTTP の動作についてみていきましょう。ウェブ上のリソースにたどり着こうとするたびに、ブラウザーは URL へリクエストを送信します。HTTP リクエストは 2 つの部分で構成されます。ブラウザーの機能に関する包括的なメタデータのセットを持つヘッダーと、指定されたリクエストをサーバーが処理するために必要な情報を持つ本文です。

+ +

GET メソッド

+ +

GET メソッドは、サーバーに対して指定したリソースを返すよう求めるためにブラウザーが使用するメソッドです。"やあサーバー、このリソースをくれよ。" この場合、ブラウザーは空の本文を送信します。本文が空であるため、フォームをこのメソッドで送信する場合はデータを URL の後に付加します。

+ +

以下のフォームについて考えてみましょう。

+ +
<form action="http://foo.com" method="get">
+  <div>
+    <label for="say">What greeting do you want to say?</label>
+    <input name="say" id="say" value="Hi">
+  </div>
+  <div>
+    <label for="to">Who do you want to say it to?</label>
+    <input name="to" id="to" value="Mom">
+  </div>
+  <div>
+    <button>Send my greetings</button>
+  </div>
+</form>
+ +

GET メソッドが使用されているので、フォームを送信するときにブラウザーのアドレスバーに www.foo.com/?say=Hi&to=Mom という URL が見えるでしょう。

+ +

URL に追加されたデータは名前/値の組の連続です。URL の Web アドレスが終了した後、疑問符 (?) に続いて、名前/値の組が、それぞれアンパサンド (&) で区切られて入ります。この場合、2 つのデータの断片がサーバーに渡されます。

+ + + +

HTTP リクエストは次のようになります。

+ +
GET /?say=Hi&to=Mom HTTP/1.1
+Host: foo.com
+ +
+

メモ: この例は GitHub にあります。— get-method.html を参照してください (ライブはこちら).

+
+ +

POST メソッド

+ +

POST メソッドは少し異なります。これは、HTTP リクエストの本文で提供したデータを考慮したレスポンスの要求を、ブラウザーがサーバーに送信するためのメソッドです。"やあサーバー、このデータを見て適切な結果を返してよ。" このメソッドを使用してフォームを送信する場合は、データが HTTP リクエストの本文の後に追加されます。

+ +

例を見てみましょう。— これは前述の GET の節で見たものと同じフォームですが、{{htmlattrxref("method","form")}} 属性が post に設定されています。

+ +
<form action="http://foo.com" method="post">
+  <div>
+    <label for="say">What greeting do you want to say?</label>
+    <input name="say" id="say" value="Hi">
+  </div>
+  <div>
+    <label for="to">Who do you want to say it to?</label>
+    <input name="to" id="to" value="Mom">
+  </div>
+  <div>
+    <button>Send my greetings</button>
+  </div>
+</form>
+ +

フォームをが POST メソッドで送信されると、URL にはデータが追加されず、HTTP リクエストは次のように、リクエスト本文にデータが含まれた形になります。

+ +
POST / HTTP/1.1
+Host: foo.com
+Content-Type: application/x-www-form-urlencoded
+Content-Length: 13
+
+say=Hi&to=Mom
+ +

Content-Length ヘッダーは本文の長さを、また Content-Type ヘッダーはサーバーに送信するリソースの種類を表します。これらのヘッダーについて少し説明しましょう。

+ +
+

メモ: この例は GitHub で見つけることができます。— post-method.html を参照してください (ライブ版も見てください)。

+
+ +

HTTP リクエストの表示

+ +

当然ながら HTTP リクエストはユーザーには表示されません (見たいのであれば、Firefox ネットワークモニターChrome デベロッパー ツールなどのツールが必要です)。例のように、フォームのデータは Chrome の Network タブに以下のように表示されます。フォームの送信後に、以下のように操作してください。

+ +
    +
  1. 開発者ツールを開く
  2. +
  3. "Network" を選択
  4. +
  5. "All" を選択
  6. +
  7. "Name" タブから "foo.com" を選択
  8. +
  9. "Headers" を選択
  10. +
+ +

これで下の画像にあるように、フォームデータを取得することができます。

+ +

+ +

ユーザーに表示されるのは呼び出された URL のみです。前述のように、GET リクエストはユーザーが URL バーの中でデータを見ることができますが、POST リクエストではそうではありません。これは 2 つの理由でとても重要です。

+ +
    +
  1. パスワード (あるいは何らかの機密データ) を送信する必要がある場合は、GET メソッドを使用してはいけません。データが URL バーに表示されるリスクがあり、とても危険です。
  2. +
  3. 大量のデータを送信する必要があるなら、POST が好ましいメソッドです。これは、URL の長さ制限があるブラウザーが存在するためです。加えて、多くのサーバーは受け入れる URL の長さを制限しています。
  4. +
+ +

サーバー側: データの取得

+ +

どちらの HTTP メソッドを選択しても、サーバーが受け取る文字列は、キー/値の組のリストとしてデータを取得するために解析されます。このリストにアクセスする方法は、使用する開発プラットフォームや、使用するであろう特定のフレームワークに依存します。

+ +

PHP の例

+ +

PHP は、データにアクセスするためのグローバルオブジェクトを提供します。POST メソッドを使用したと仮定すると、データを取得してユーザーに表示する例は以下のとおりです。もちろん、データに対して何をするかはあなた次第です。データを表示したり、データベースに保管したり、メールで送信したり、他の手段で処理したりするでしょう。

+ +
<?php
+  // $_POST グローバル変数は、POST メソッドで送信されたデータへ名前でアクセスを可能にする
+  // GET メソッドで送信されたデータにアクセスするには、$_GET が使用できる
+  $say = htmlspecialchars($_POST['say']);
+  $to  = htmlspecialchars($_POST['to']);
+
+  echo  $say, ' ', $to;
+?>
+ +

この例では送信されたデータを含むページを表示します。これはサンプルの php-example.html ファイル、つまり以前 methodPOSTactionphp-example.php の時に見たサンプルフォームを含むファイルアクションの中で見ることができます。送信されると、フォームデータは上記のブロックの PHP コードを含む php-example.php へ送信されます。コードが実行されると、ブラウザーの出力は Hi Mom になります。

+ +

+ +
+

メモ: この例はブラウザーにローカルに読み込んだ時には動作しません。— ブラウザーは PHP コードを解釈できないので、フォームがブラウザーに送信されると、PHP ファイルをダウンロードしようとするでしょう。動作させるためには、この例を何らかの PHP サーバー経由で実行する必要があります。ローカルの PHP のテストには、MAMP (Mac および Windows) や AMPPS (Mac, Windows, Linux) がいいでしょう。

+ +

MAMP を使って MAMP Pro がない (または MAMP Pro デモトライアルの有効期限が切れた)場合、動作させるのにトラブルが起こるかもしれません。再び動作させるには MAMP アプリを閉じて、MAMP > Preferences > PHPメニューから "Standard Version:" を "7.2.x" (x はあなたがどのバージョンをインストールしたかによります)にするといいことがわかっています。

+
+ +

Python の例

+ +

この例は、同じこと (与えられたデータをウェブページに表示する) を Python で行います。これはテンプレートの表示やフォームデータの受付などのために Flask フレームワークを使用しています (python-example.py を参照してください)。

+ +
from flask import Flask, render_template, request
+app = Flask(__name__)
+
+@app.route('/', methods=['GET', 'POST'])
+def form():
+    return render_template('form.html')
+
+@app.route('/hello', methods=['GET', 'POST'])
+def hello():
+    return render_template('greeting.html', say=request.form['say'], to=request.form['to'])
+
+if __name__ == "__main__":
+    app.run()
+ +

次のように、上記のコードでは 2 つのテンプレートが参照されます。(自分の環境で実行する場合、これらは templates というサブディレクトリにあり、python-example.pyファイルと同じディレクトリにある必要があります):

+ + + +
+

メモ: 繰り返しますが、このコードはブラウザーに直接読み込もうとしても動作しません。Python は PHP とは若干異なる動作をします。— ローカルでこのコードを実行するには、Python/PIP をインストールする必要があり、それから pip3 install flask を使用して Flask をインストールしてください。この時点で python3 python-example.py を実行し、ブラウザーで localhost:5000 に移動することで実行することができるでしょう。

+
+ +

その他の言語やフレームワーク

+ +

フォームの操作に使用できるサーバー側の技術は、Perl、Java、.Net、Ruby などたくさんあります。もっとも好きなものを選びましょう。しかしそれらの技術を直接使用することは、扱いにくいため一般的ではないことが特筆に値します。以下のような、フォームをより簡単に扱えるようにする多くの高品質フレームワークのひとつを使用する方がより一般的です:

+ + + +

言うまでもなく、これらのフレームワークを使用したとしても、フォームでの作業が必ずしも簡単になるとは限りません。しかし、すべての機能を自分で 1 から書こうとするよりずっと簡単で、また多くの時間を節約できるでしょう。

+ +
+

メモ: サーバー側言語やフレームワークまで説明することはこの記事の範囲を超えます。上記のリンクが参考になりますので、学習してみてください。

+
+ +

特別な場合: ファイル送信

+ +

ファイルは HTML フォームで特別なケースです。他のデータがすべてテキストデータである中、ファイルはバイナリーデータ (あるいはそのように考えられるデータ) です。HTTP はテキストのプロトコルであるため、バイナリーデータを扱うための特別な要件があります。

+ +

enctype 属性

+ +

この属性で Content-Type HTTP ヘッダーの値を指定できます。このヘッダーはサーバーに対して送信するデータの種類を伝えることから、とても重要です。既定値は application/x-www-form-urlencoded です。人間の言葉では、「これは URL 形式でエンコードされたフォームデータです。」という意味です。

+ +

しかしファイルを送信したい場合は、さらに 2 つのステップを踏む必要があります。

+ + + +

例:

+ +
<form method="post" enctype="multipart/form-data">
+  <div>
+    <label for="file">Choose a file</label>
+    <input type="file" id="file" name="myFile">
+  </div>
+  <div>
+    <button>Send the file</button>
+  </div>
+</form>
+ +
+

警告: 多くのサーバーは悪用を防ぐために、ファイルや HTTP リクエストの長さを制限しています。

+
+ +

一般的なセキュリティへの配慮

+ +

サーバーにデータを送信するたびに、セキュリティについて考える必要があります。HTML フォームはサーバーに対するもっともよくある攻撃の入口 (攻撃が行われる場所) になります。問題が HTML フォーム自身から発生することはありません — サーバーがどのようにデータを扱うかによります。

+ +

server-side の学習トピックの Website security の記事では、一般的な攻撃とその防御を詳細に扱っています。そちらへ行って記事を確認し、何が起こり得るかを理解してください。

+ +

疑い深くあれ: ユーザーを信用してはいけません

+ +

さて、これらの脅威に対してどう対抗するのでしょうか? これは本ガイドの内容を超える話題です。それでも、覚えておくとよいルールがいくつかあります。もっとも重要なルールは、自分自身も含めユーザーを決して信用してはならないことです。信頼されているユーザーでさえハイジャックされるかもしれません。

+ +

サーバーに来るすべてのデータを確認およびサニタイズしなければなりません。いつでもです。例外はありません。

+ + + +

これら 3 つのルールに従うと、多くのあるいはほとんどの問題を避けられるでしょう。ただし、適格の第三者によるセキュリティレビューを受けることもよい考えです。発生し得る問題のすべてを見いだしたとは考えないようにしてください。

+ +

まとめ

+ +

ご覧いただいたように、フォームデータの送信は簡単ですが、アプリケーションを安全にするのは容易ではありません。フロントエンドの開発者はデータのセキュリティモデルを定義すべき者ではないことを忘れないようにしてください。今後見ていくようにクライアント側でのデータ検証も可能ですが、クライアント側で実際に何が起きているかを知ることはできませんので、サーバー側でその検証内容を信用することはできません。

+ +

このチュートリアルを順番に終えた場合、フォームのマークアップとスタイル設定の方法、クライアント側での検証の方法、フォーム送信の理解ができているでしょう。

+ +

関連情報

+ +

ウェブアプリケーションのセキュア化についてさらに学びたいのでしたら、次のリソースをよく読んでください。

+ + + +

{{PreviousMenuNext("Learn/HTML/Forms/The_native_form_widgets", "Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/sending_forms_through_javascript/index.html b/files/ja/learn/forms/sending_forms_through_javascript/index.html new file mode 100644 index 0000000000..3b3ba71ce2 --- /dev/null +++ b/files/ja/learn/forms/sending_forms_through_javascript/index.html @@ -0,0 +1,396 @@ +--- +title: JavaScript によるフォームの送信 +slug: Learn/Forms/Sending_forms_through_JavaScript +tags: + - Advanced + - Example + - Forms + - Forms Guide + - Guide + - HTML + - HTML forms + - JavaScript + - Learn + - Security + - Web + - Web Forms +translation_of: Learn/Forms/Sending_forms_through_JavaScript +--- +
{{LearnSidebar}}
+ +

HTML フォームは HTTP リクエストを宣言的に送信できます。しかし、フォームは 、例えば XMLHttpRequest のように JavaScript 経由で送信する HTTP リクエストを準備することもできます。この記事ではその方法を探ります。

+ +

フォームは必ずしもフォームであるとは限らない

+ +

PWA や SPA やフレームワークベースのアプリが現れたことで、HTML フォームを、応答データを受け取ったときに、新しい文書を読み込むことなくデータ送信するのに使用することが次第に一般的になってきました。最初になぜいろいろなアプローチが必要となるのかを話しましょう。

+ +

グローバルインターフェイスの制御を取得

+ +

次の記事で述べる標準の HTML フォーム送信では、データが送信された URL がロードされます。つまり、ブラウザーウィンドウは全ページロードで移動します。ページ全体の読み込みを回避すると、ちらつきのような視覚上の問題や、ネットワークの遅延を避けて、よりスムーズな操作を提供できます。

+ +

最近の多くの UI は、HTML フォームを使用してユーザーからの入力を収集します。ユーザーがデータを送信しようとすると、アプリケーションはバックグラウンドでデータを非同期的に制御して送信し、変更が必要な UI の部分のみを更新します。

+ +

任意のデータを非同期に送信することは、"Asynchronous JavaScript And XML" を表す頭字語である AJAX として知られています。

+ +

その違いは?

+ +

{{domxref("XMLHttpRequest")}} (XHR) DOM オブジェクトで HTTP リクエストを作成して送信し、結果を取得することができます。歴史的には、{{domxref("XMLHttpRequest")}} は交換フォーマットとして XML を取得して送信するように設計されていました。しかし、JSON は XML に取って代わっています。しかし、XML も JSON もフォームデータリクエストのエンコーディングには適合しません。フォームデータ (application/x-www-form-urlencoded) は、キーと値のペアの URL エンコードされたリストで構成されています。バイナリーデータを送信するために、HTTP リクエストは multipart/form-data に再形成されます

+ +
+

注記: Fetch API は最近 XHR の代わりによく使われます — これは XHR のモダンで更新されたバージョンであり、同様に動作しますが利点もあります。この記事で見る大半の XHR コードは Fetch で置き換えられます。

+
+ +

フロントエンド (ブラウザーで実行されるコード) とバックエンド (サーバーで実行されるコード) を制御すれば、JSON/XML を送信して必要に応じて処理することができます。

+ +

しかし、サードパーティのサービスを利用したい場合、サービスが要求する零式でデータ送信する必要があります。

+ +

ではどのようにしてそのようなデータを送信するのでしょうか?以下に必要となるさまざまなテクニックがあります。

+ +

フォームデータの送信

+ +

フォームデータを送信するには、従来の方法から新しい {{domxref("FormData")}} オブジェクトまで 3 つの方法があります。それらを詳しく見てみましょう。

+ +

手作業での XMLHttpRequest の作成

+ +

{{domxref("XMLHttpRequest")}} は、HTTP リクエストを作成する最も安全で信頼性の高い方法です。{{domxref("XMLHttpRequest")}} を使用してフォームデータを送信するには、URL エンコードしたデータを準備し、フォームデータリクエストの詳細に従ってください。

+ +

例を見てみましょう:

+ +
<button>Click Me!</button>
+ +

JavaScript はこうです:

+ +
const btn = document.querySelector('button');
+
+function sendData( data ) {
+  console.log( 'Sending data' );
+
+  const XHR = new XMLHttpRequest();
+
+  let urlEncodedData = "",
+      urlEncodedDataPairs = [],
+      name;
+
+  // data オブジェクトを、URL エンコードしたキーと値のペアの配列に変換します
+  for( name in data ) {
+    urlEncodedDataPairs.push( encodeURIComponent( name ) + '=' + encodeURIComponent( data[name] ) );
+  }
+
+ // キーと値のペアをひとつの文字列に連結して、Web ブラウザーのフォーム送信方式に
+ // 合うよう、エンコードされた空白をプラス記号に置き換えます。
+  urlEncodedData = urlEncodedDataPairs.join( '&' ).replace( /%20/g, '+' );
+
+  // データが正常に送信された場合に行うことを定義します
+  XHR.addEventListener( 'load', function(event) {
+    alert( 'Yeah! Data sent and response loaded.' );
+  } );
+
+  // エラーが発生した場合に行うことを定義します
+  XHR.addEventListener( 'error', function(event) {
+    alert( 'Oops! Something went wrong.' );
+  } );
+
+  // リクエストをセットアップします
+  XHR.open( 'POST', 'https://example.com/cors.php' );
+
+  // フォームデータの POST リクエストを扱うために必要な HTTP ヘッダを追加します
+  XHR.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+
+  // 最後に、データを送信します
+  XHR.send( urlEncodedData );
+}
+
+btn.addEventListener( 'click', function() {
+  sendData( {test:'ok'} );
+} )
+
+ +

そして、結果は以下のとおりです:

+ +

{{EmbedLiveSample("Building_an_XMLHttpRequest_manually", "100%", 50)}}

+ +
+

注記: この {{domxref("XMLHttpRequest")}} の使用は、第三者の Web サイトにデータを送信したい場合にも、同一生成元ポリシーの対象となります。クロスオリジンリクエストの場合は、CORS と HTTP のアクセス制御が必要です。

+
+ +

XMLHttpRequest と FormData オブジェクトの使用

+ +

HTTP リクエストを手作業で作成するのは大変なことです。幸いなことに、最近の XMLHttpRequest 仕様では {{domxref("FormData")}} オブジェクトを使ってフォームデータリクエストを処理する便利で簡単な方法が提供されています。

+ +

{{domxref("FormData")}} オブジェクトは、送信用のフォームデータを作成したり、送信方法を管理するフォーム要素内のデータを取得するために使用できます。{{domxref("FormData")}} オブジェクトは "書き込み専用" であることに注意してください。つまり、変更することはできますが、内容を取得することはできません。

+ +

このオブジェクトの使い方は FormData オブジェクトの使用で詳述されていますが、2 つの例があります。

+ +

独立した FormData オブジェクトを使用する

+ +
<button type="button" onclick="sendData({test:'ok'})">Click Me!</button>
+ +

HTML のサンプルはおわかりでしょう。JavaScript はこうです。

+ +
const btn = document.querySelector('button');
+
+function sendData(data) {
+  const XHR = new XMLHttpRequest(),
+        FD  = new FormData();
+
+  // データを FormData オブジェクトに投入します
+  for(name in data) {
+    FD.append(name, data[name]);
+  }
+
+  // データが正常に送信された場合に行うことを定義します
+  XHR.addEventListener('load', function(event) {
+    alert('Yeah! Data sent and response loaded.');
+  });
+
+  // エラーが発生した場合に行うことを定義します
+  XHR.addEventListener('error', function(event) {
+    alert('Oups! Something goes wrong.');
+  });
+
+  // リクエストをセットアップします
+  XHR.open('POST', 'http://ucommbieber.unl.edu/CORS/cors.php');
+
+  // FormData オブジェクトを送信するだけです。HTTP ヘッダは自動的に設定されます
+  XHR.send(FD);
+}
+ +

そして、結果は以下のとおりです:

+ +

{{EmbedLiveSample("Using_a_standalone_FormData_object", "100%", 50)}}

+ +

form 要素に紐づけた FormData を使用する

+ +

FormData オブジェクトを {{HTMLElement("form")}} 要素に紐づけることもできます。これにより、フォームに含まれるデータを表す FormData をすばやく得ることができます。

+ +

HTML の部分はかなり典型的です:

+ +
<form id="myForm">
+  <label for="myName">Send me your name:</label>
+  <input id="myName" name="name" value="John">
+  <input type="submit" value="Send Me!">
+</form>
+ +

しかし、JavaScript がフォームを乗っ取ります。

+ +
window.addEventListener("load", function () {
+  function sendData() {
+    const XHR = new XMLHttpRequest();
+
+    // FormData オブジェクトと form 要素を紐づけます
+    const FD  = new FormData(form);
+
+    // データが正常に送信された場合に行うことを定義します
+    XHR.addEventListener("load", function(event) {
+      alert(event.target.responseText);
+    });
+
+    // エラーが発生した場合に行うことを定義します
+    XHR.addEventListener("error", function(event) {
+      alert('Oups! Something goes wrong.');
+    });
+
+    // リクエストをセットアップします
+    XHR.open("POST", "http://ucommbieber.unl.edu/CORS/cors.php");
+
+    // 送信したデータは、ユーザーがフォームで提供したものです
+    XHR.send(FD);
+  }
+
+  // form 要素にアクセスしなければなりません
+  const form = document.getElementById("myForm");
+
+  // フォームの submit イベントを乗っ取ります
+  form.addEventListener("submit", function (event) {
+    event.preventDefault();
+
+    sendData();
+  });
+});
+ +

そして、結果は以下のとおりです:

+ +

{{EmbedLiveSample("Using_FormData_bound_to_a_form_element", "100%", 50)}}

+ +

フォームの {{domxref("HTMLFormElement.elements", "elements")}} プロパティを使用してフォーム内のすべてのデータ要素のリストを取得し、それらを一度に 1 つずつ手動で管理することで、このプロセスにさらに関わることができます。詳細については、{{SectionOnPage("/ja/docs/Web/API/HTMLFormElement.elements", "要素リストの内容にアクセスする")}}の例を参照してください。

+ +

バイナリーデータを扱う

+ +

<input type="file"> ウィジェットを含むフォームで {{domxref("FormData")}} オブジェクトを使用すると、データは自動的に処理されます。しかし、バイナリーデータを手動で送るには、追加でやるべきことがあります。

+ +

現代の Web には、バイナリーデータのソースが多数あります。たとえば、{{domxref("FileReader")}}、{{domxref("HTMLCanvasElement","Canvas")}}、WebRTC などです。残念ながら、一部の従来のブラウザーではバイナリーデータにアクセスできないか、または複雑な回避策が必要です。これらのレガシーケースはこの記事の範囲外です。FileReader API について詳しく知りたい場合は、Web アプリケーションからファイルを扱うを読んでください。

+ +

{{domxref("FormData")}} をサポートするバイナリーデータを送信するのは簡単です。append() メソッドを使用すれば完了です。手動でやらなければならないならば、それはトリッキーです。

+ +

以下の例ではバイナリーデータへのアクセスに {{domxref("FileReader")}} API を使用しており、また手作業でマルチパートのフォームデータを作成しています:

+ +
<form id="myForm">
+  <p>
+    <label for="i1">text data:</label>
+    <input id="i1" name="myText" value="Some text data">
+  </p>
+  <p>
+    <label for="i2">file data:</label>
+    <input id="i2" name="myFile" type="file">
+  </p>
+  <button>Send Me!</button>
+</form>
+ +

ご覧のとおり、HTML は標準の <form> です。不思議なところは何もありません。「魔法」は JavaScript にあります。

+ +
// DOM ノードにアクセスしたいため、
+// ページをロードしたときにスクリプトを初期化します。
+window.addEventListener('load', function () {
+
+  // この変数は、フォームデータを格納するために使用します。
+  const text = document.getElementById("i1");;
+  const file = {
+        dom    : document.getElementById("i2"),
+        binary : null
+      };
+
+  // ファイルコンテンツへのアクセスに FileReader API を使用します。
+  const reader = new FileReader();
+
+  // FileReader API は非同期であるため、ファイルの読み取りが完了したときに
+  // その結果を保存しなければなりません。
+  reader.addEventListener("load", function () {
+    file.binary = reader.result;
+  });
+
+  // ページを読み込んだとき、すでに選択されているファイルがあればそれを読み取ります。
+  if(file.dom.files[0]) {
+    reader.readAsBinaryString(file.dom.files[0]);
+  }
+
+  // 一方、ユーザーがファイルを選択したらそれを読み取ります。
+  file.dom.addEventListener("change", function () {
+    if(reader.readyState === FileReader.LOADING) {
+      reader.abort();
+    }
+
+    reader.readAsBinaryString(file.dom.files[0]);
+  });
+
+  // sendData 関数がメインの関数です。
+  function sendData() {
+    // 始めに、ファイルが選択されている場合はファイルの読み取りを待たなければなりません。
+    // そうでない場合は、関数の実行を遅延させます。
+    if(!file.binary && file.dom.files.length > 0) {
+      setTimeout(sendData, 10);
+      return;
+    }
+
+    // マルチパートのフォームデータリクエストを構築するため、
+    // XMLHttpRequest のインスタンスが必要です。
+    const XHR      = new XMLHttpRequest();
+
+    // リクエストの各パートを定義するためのセパレータが必要です。
+    const boundary = "blob";
+
+    // 文字列としてリクエストのボディを格納します。
+    let data     = "";
+
+    // そして、ユーザーがファイルを選択したときに
+    if (file.dom.files[0]) {
+      // リクエストのボディに新たなパートを作ります
+      data += "--" + boundary + "\r\n";
+
+      // フォームデータであることを示します (他のものになる場合もあります)
+      data += 'content-disposition: form-data; '
+      // フォームデータの名前を定義します
+            + 'name="'         + file.dom.name          + '"; '
+      // 実際のファイル名を与えます
+            + 'filename="'     + file.dom.files[0].name + '"\r\n';
+      // ファイルの MIME タイプを与えます
+      data += 'Content-Type: ' + file.dom.files[0].type + '\r\n';
+
+      // メタデータとデータの間に空行を置きます
+      data += '\r\n';
+
+      // リクエストのボディにバイナリーデータを置きます
+      data += file.binary + '\r\n';
+    }
+
+    // テキストデータの場合はシンプルです。
+    // リクエストのボディに新たなパートを作ります
+    data += "--" + boundary + "\r\n";
+
+    // フォームデータであることと、データの名前を示します。
+    data += 'content-disposition: form-data; name="' + text.name + '"\r\n';
+    // メタデータとデータの間に空行を置きます
+    data += '\r\n';
+
+    // リクエストのボディにテキストデータを置きます。
+    data += text.value + "\r\n";
+
+    // 完了したら、リクエストのボディを "閉じます"。
+    data += "--" + boundary + "--";
+
+    // データが正常に送信された場合に行うことを定義します
+    XHR.addEventListener('load', function(event) {
+      alert('Yeah! Data sent and response loaded.');
+    });
+
+    // エラーが発生した場合に行うことを定義します
+    XHR.addEventListener('error', function(event) {
+      alert('Oups! Something goes wrong.');
+    });
+
+    // リクエストをセットアップします
+    XHR.open('POST', 'http://ucommbieber.unl.edu/CORS/cors.php');
+
+    // マルチパートのフォームデータの POST リクエストを扱うために必要な HTTP ヘッダを追加します。
+    XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary);
+    XHR.setRequestHeader('Content-Length', data.length);
+
+    // 最後に、データを送信します
+    // Firefox のバグ 416178 により、send() の代わりに sendAsBinary() を使用することが必要です。
+    XHR.sendAsBinary(data);
+  }
+
+  // 少なくとも、フォームにアクセスしなければなりません。
+  const form   = document.getElementById("myForm");
+
+  // submit イベントを乗っ取ります。
+  form.addEventListener('submit', function (event) {
+    event.preventDefault();
+    sendData();
+  });
+});
+ +

そして、結果は以下のとおりです:

+ +

{{EmbedLiveSample("Dealing_with_binary_data", "100%", 150)}}

+ +

まとめ

+ +

ブラウザーや扱うデータタイプによっては、JavaScript を介してフォームデータを送信するのが簡単な場合と難しい場合があります。{{domxref("FormData")}} オブジェクトが一般的な答えであり、レガシーブラウザーで polyfill を使用することをためらってはいけません。

+ +

このモジュール

+ +

学習コース

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/styling_html_forms/index.html b/files/ja/learn/forms/styling_html_forms/index.html new file mode 100644 index 0000000000..4634665cef --- /dev/null +++ b/files/ja/learn/forms/styling_html_forms/index.html @@ -0,0 +1,398 @@ +--- +title: HTML フォームへのスタイル設定 +slug: Learn/Forms/Styling_HTML_forms +tags: + - CSS + - Example + - Forms + - Guide + - HTML + - Intermediate + - Web +translation_of: Learn/Forms/Styling_web_forms +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/Forms/Other_form_controls","Learn/Forms/Advanced_form_styling","Learn/Forms")}}

+ +

前の記事ではウェブフォームを構築するのに必要な HTML のすべてを見てきました。この記事ではフォームコントロールにスタイル設定する CSS の使い方に進みます。これは歴史的に難しかったです — フォームコントロールは大きく変わり CSS を使ったフォームのカスタマイズは簡単になりました— しかし古いブラウザーが引退してモダンブラウザーが多くの機能を与えるため、より簡単になりました。

+ + + + + + + + + + + + +
前提条件: +

基本的なコンピューターリテラシーと、HTMLCSS の基本的な理解。

+
目的:フォームのスタイル設定の問題を理解し、役立つスタイル付けのテクニックを学ぶこと。
+ +

なぜ CSS によるフォームウィジェットへのスタイル設定は困難であるか?

+ +

1995年頃に HTML 2 仕様へフォームコントロールが追加されました。CSS は 1996年までリリースされず、その後も少しのブラウザーによって十分サポートされませんでした。ブラウザーはフォームコントロールの管理や表示について下層の OS に頼ることを選択しました。

+ +

CSS が HTML のスタイル設定できるようになってからも、ユーザーは各プラットフォームの視覚的な外見に慣れていましたので、ブラウザーベンダーはフォームコントロールをスタイル付け可能にすることに乗り気ではありませんでした。しかしこれは変わりました。ウェブサイトのオーナーはこれまでよりも、サイト全体に適するスタイルを欲しており、ウェブプラットフォームはこれを実現可能にしました。

+ +

いくつかのフォームウィジェットでは、コントロールをスタイル設定できるように作成し直すのは難しいですが、ユーザービリティを破綻させないよう気をつける必要はあるものの、CSS を使って多くのフォーム機能をスタイル設定できます。

+ +

CSS を伴ってもすべてのウィジェットが同等に作成されるわけではありません

+ +

いまだに、フォームで CSS を使用する際に困ることが存在します。この問題は、3 つのカテゴリーに分けられます。

+ +

良好

+ +

いくつかの要素はプラットフォーム間の問題があるとしても、ほとんど問題なくスタイルを設定できます。これらは以下の構造的な要素が含まれます:

+ +
    +
  1. {{HTMLElement("form")}}
  2. +
  3. {{HTMLElement("fieldset")}} と {{HTMLElement("legend")}}
  4. +
  5. 単一行のテキスト {{HTMLElement("input")}} (例 text, url, email...のタイプ) <input type="search">を除く
  6. +
  7. 複数行の {{HTMLElement("textarea")}}
  8. +
  9. ボタン ({{HTMLElement("input")}} と {{HTMLElement("button")}}の両方)
  10. +
  11. {{HTMLElement("label")}}
  12. +
  13. {{HTMLElement("output")}}
  14. +
+ +

不良

+ +

一部の要素はほとんどスタイル設定ができず、時に CSS3 の高度な知識やトリックが必要になるかもしれません。

+ +
    +
  1. チェックボックスとラジオボタン
  2. +
  3. <input type="search">
  4. +
+ +

これら特殊なケースをどのように扱うかについては、HTML フォームへの高度なスタイル設定の記事で見ていきます。

+ +

劣悪

+ +

一部の要素は、CSS でスタイルを設定できません。たとえば次のもの:

+ + + +

これらの要素をスタイル設定するのに関して何ができるかについては、HTML フォームへの高度なスタイル設定の記事で見ていきます。

+ +

これらすべてのウィジェットの主な問題は、ウィジェットの構造がとても複雑であるという事実と、(コントロールの width や margin の変更といった)基本的なスタイル設定を超えると、現在の CSS では(例えばカレンダー日付ピッカーや、選択肢のリストを表示する<select>のボタンのような)ウィジェットの細かい部分すべてにスタイルを設定できるほどの表現力がないことによります。

+ +

これらのウィジェットを完全にカスタマイズしたい場合は、HTML, CSS, JavaScript を使って独自のものを作成する必要があります。それはこのコアフォームの記事の範囲を超えますが、高度な記事のカスタムウィジェットの作成方法の記事で説明します。

+ +
+

: フォームコントロールの内部コンポーネントにスタイル設定するプロプライエタリな CSS 疑似要素、例えば {{cssxref('::-moz-range-track')}}がありますが、これはブラウザー同士で整合していないので、これに頼るべきではありません。これについては後程でも触れます。

+
+ +

良好

+ +

CSS でのスタイル設定が容易な要素は、振る舞いが他の HTML 要素とほとんど同じであるため、問題に直面することはないでしょう。ただし、ブラウザー間でユーザーエージェントのスタイルシートが若干矛盾するかもしれませんので、より簡単にスタイルを設定できるようにするためのトリックがあります。

+ +

上記で述べた基本的な CSS ツールと同じく、いくつかのセレクターが与えられます — UI 疑似クラス — これにより現在の UI の状態に基づくスタイル設定ができます。これは次の記事である、UI 疑似クラスで扱います。

+ +

この記事の最後で基本的なフォームコントロールのスタイル設定と配置について理解できる実例を詳しく見ていきます。しかしその前に、知っておくと良いフォームスタイル設定の特定の面をいくつか述べておきます。

+ +

フォントとテキスト

+ +

CSS のフォントやテキストの機能は、任意のウィジェットで容易に使用できます (また、フォームウィジェットで {{cssxref("@font-face")}} も使用できます)。ただし、ブラウザーの動作にしばしば矛盾があります。デフォルトで、一部のブラウザーは親から {{cssxref("font-family")}} や {{cssxref("font-size")}} を継承しません。代わりに多くのブラウザーでは、システムのデフォルトの体裁を使用します。フォームの体裁を他のコンテンツと一致させるには、以下のルールをスタイルシートに追加するとよいでしょう:

+ +
button, input, select, textarea {
+  font-family : inherit;
+  font-size   : 100%;
+}
+ +

{{cssxref('inherit')}} のプロパティ値で、プロパティ値は計算された親要素のプロパティ値に一致するようになります。つまり親の値を継承します。

+ +

以下のスクリーンショットで違いを示します。左側は Mac OS X の Chrome における<input type="text">, <input type="date">, {{htmlelement('select')}}, {{htmlelement('textarea')}}, <input type="submit">, <button> 要素の既定のレンダリングで、プラットフォームのデフォルトフォントスタイルを使用しています。右側は同じ要素ですが、フォントを調和させるスタイルルールを適用したものです。

+ +

Form controls with default and inherited font families. 既定では, some types are serif and others are sans serif. Inheriting should change the fonts of all to the parent's font family - in this case a paragraph. Oddly, input of type submit does not inherit from the parent paragraph.

+ +

既定はいろいろと変わります。継承により、フォントは親のフォントファミリーに変更されます — ここでは親コンテナのデフォルトの serif フォントです。ほぼすべてそうですが、例外として Chrome では<input type="submit"> は親段落を継承しません。むしろ、{{cssxref('font-family#Values', 'font-family: system-ui')}}を使います。これは同等な入力タイプの中で <button> 要素を使う理由です!

+ +

フォームはシステムのデフォルトスタイルを使用するか、コンテンツに合うよう設計されたカスタムスタイルを使用するかについては多くの議論があります。これを決めるのは、設計者としてサイトやウェブアプリケーションを作成するあなた次第です。

+ +

ボックスモデル

+ +

すべてのテキストフィールドは、CSS のボックスモデルに関する全プロパティ ({{cssxref("width")}}、{{cssxref("height")}}、{{cssxref("padding")}}、{{cssxref("margin")}}、および {{cssxref("border")}}) を完全にサポートしています。ただし前述のとおり、ブラウザーがウィジェットを表示する際はシステムのデフォルトスタイルに依存します。コンテンツに対してそれらをどのように混ぜ合わせるかを決めるのは、あなた次第です。ウィジェットでネイティブのルックアンドフィールを維持したいのでしたら、ウィジェットのサイズを調和させたい場合に若干の問題に直面するでしょう。

+ +

これは各ウィジェットがボーダー、パディング、マージンについて独自のルールを持っているためです。このためさまざまなウィジェットを同じサイズにしたい場合に、{{cssxref("box-sizing")}} プロパティを使用しなければなりません:

+ +
input, textarea, select, button {
+  width : 150px;
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+}
+ +

下のスクリーンショットで、左の列は<input type="radio">, <input type="checkbox">, <input type="range">, <input type="text">, <input type="date"> input, {{htmlelement('select')}}, {{htmlelement('textarea')}},<input type="submit">, {{htmlelement('button')}} の既定の描画、右の列は同じ要素に上のルールを使用して作成したものです。各種のウィジェットのプラットフォームのデフォルトルールと比較して、すべての要素が同じ領域を占めるようにすることが可能な点に注目してください。

+ +

box model properties effect most input types.

+ +

スクリーンショットで明白でないことはラジオボタンとチェックボックスコントロールが同じであるが、水平位置が {{cssxref('width')}} プロパティで与えられる 150px の中心にあることです。他のブラウザーではウィジェットを中心揃えにしませんが、割り当てられたスペースに付着させます。

+ +

legend 配置

+ +

{{HTMLElement("legend")}} 要素はポジショニングを除いて、スタイル設定の問題はありません。既定では、それは親 {{HTMLElement("fieldset")}} の上ボーダーの前面に、左上の隅の近くに配置されます。これを他の場所、例えば fieldset内のどこかや、左下の隅に配置するには、配置に頼る必要があります。

+ +

下記の例を見てください:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/native-form-widgets/positioned-legend.html", '100%', 400)}}

+ +

この方法で legend を配置するには、次の CSS を使います(簡単のため他の宣言は削除しています):

+ +
fieldset {
+  position: relative;
+}
+
+legend {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+}
+ +

<fieldset> も配置される必要があり、<legend> がそれに合わせて位置が決まるように (そうでなければ <legend><body>に合わせて位置決めされます)

+ +

{{HTMLElement("legend")}} 要素はアクセシビリティのためとても重要です — これはアシスト技術により fieldset 内の各フォーム要素のラベルとして話されます — が、上のようなテクニックの使用は良いです。legend コンテンツは同じ方法で話されます; 単に見た目の位置が変更されます。

+ +
+

: <legend>の位置決めに役立つ{{cssxref("transform")}}プロパティも使用できますが、例えばa transform: translateY();を使って配置するとき、移動はするものの <fieldset> の枠に劣悪なギャップができて、除去が困難です。

+
+ +

特定のスタイル設定の例

+ +

HTML フォームにスタイルを設定する方法の具体例を見ていきましょう。以下のような "はがき" 風の連絡フォームを作成します。完成バージョンはこちら

+ +

この例に従うには、postcard-start.html ファイルをコピーして、次のやり方に従ってください。

+ +

HTML

+ +

HTML は、ガイドの最初の記事で使用したものより少しだけ複雑です。いくつか ID やタイトルを追加しています。

+ +
<form>
+ <h1>to: Mozilla</h1>
+
+  <div id="from">
+    <label for="name">from:</label>
+    <input type="text" id="name" name="user_name">
+  </div>
+
+  <div id="reply">
+    <label for="mail">reply:</label>
+    <input type="email" id="mail" name="user_email">
+  </div>
+
+  <div id="message">
+    <label for="msg">Your message:</label>
+    <textarea id="msg" name="user_message"></textarea>
+  </div>
+
+  <div class="button">
+    <button type="submit">Send your message</button>
+  </div>
+</form>
+ +

上記のコードを HTML の body に追加します。

+ +

Organizing your assets

+ +

ここからがおもしろいところです! コードを書き始める前に、ここでは 3 つの追加要素が必要です:

+ +
    +
  1. はがきの背景 — この画像をダウンロードして作業している HTML ファイルと同じディレクトリーに保存します。
  2. +
  3. タイプライター風フォント: fontsquirrel.com の "Secret Typewriter"  — TTF ファイルを上記と同じディレクトリーにダウンロードします。
  4. +
  5. 手書き風フォント: fontsquirrel.com の "Journal"  — TTF ファイルを上記と同じディレクトリーにダウンロードします。
  6. +
+ +

始める前にフォントの処理が必要です:

+ +
    +
  1. fontsquirrel Webfont Generator に移動します。
  2. +
  3. フォームを使って、両方のフォントファイルをアップロードして webfont キットを生成します。キットをコンピューターにダウンロードします。
  4. +
  5. zip ファイルを展開します。
  6. +
  7. 展開した中身には 2 つの .woff ファイルと 2 つの .woff2 ファイルがあります。このファイルを、前と同じ fonts というディレクトリーにコピーします。各フォントの 2 つのファイルはブラウザー互換性を最大化するのに使います; より詳しい情報は Web fonts の記事を見てください。
  8. +
+ +

CSS

+ +

ここから例の CSS を見ていきましょう。{{htmlelement("style")}} 要素の中にすべてのコードブロックを一つ一つ追加します。

+ +

全体レイアウト

+ +

まず、{{cssxref("@font-face")}} ルールと、すべての{{HTMLElement("body")}} と {{HTMLElement("form")}} 要素に設定するスタイルを定義して準備します。fontsquirrel 出力が上記で述べたものと異なる場合、stylesheet.css ファイル内にダウンロード済みの webfont キットの中から正しい @font-face ブロックを見つけることができます(下記の @font-face ブロックをそれで置換し、パスをフォントファイルのものに更新する必要があります):

+ +
@font-face {
+    font-family: 'handwriting';
+    src: url('fonts/journal-webfont.woff2') format('woff2'),
+         url('fonts/journal-webfont.woff') format('woff');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'typewriter';
+    src: url('fonts/veteran_typewriter-webfont.woff2') format('woff2'),
+         url('fonts/veteran_typewriter-webfont.woff') format('woff');
+    font-weight: normal;
+    font-style: normal;
+}
+
+body {
+  font  : 1.3rem sans-serif;
+  padding : 0.5em;
+  margin  : 0;
+  background : #222;
+}
+
+form {
+  position : relative;
+  width  : 740px;
+  height : 498px;
+  margin : 0 auto;
+  padding: 1em;
+  box-sizing: border-box;
+  background : #FFF url(background.jpg);
+
+  /* we create our grid */
+  display  : grid;
+  grid-gap : 20px;
+  grid-template-columns : repeat(2, 1fr);
+  grid-template-rows    : 10em 1em 1em 1em;
+}
+ +

注意として、フォームをレイアウトするのに CSS GridFlexbox を使っています。これで、タイトルやフォーム要素といった各要素を配置できます:

+ +
h1 {
+  font : 1em "typewriter", monospace;
+  align-self : end;
+}
+
+#message {
+   grid-row: 1 / 5;
+}
+
+#from, #reply {
+   display: flex;
+}
+ +

ラベルとコントロール

+ +

そして、フォーム要素自体に対するスタイル設定を始めます。まずは、{{HTMLElement("label")}} に適切なフォントを割り当てましょう。

+ +
label {
+  font : .8em "typewriter", sans-serif;
+}
+ +

テキストフィールドには、共通のルールがいくつか必要です。{{cssxref("border")}} や {{cssxref("background")}} の削除と {{cssxref("padding")}} や {{cssxref("margin")}} の再定義を行います。

+ +
input, textarea {
+  font    : 1.4em/1.5em "handwriting", cursive, sans-serif;
+  border  : none;
+  padding : 0 10px;
+  margin  : 0;
+  width   : 80%;
+  background : none;
+}
+ +

これらフィールドのひとつがフォーカスを得たときに、ライトグレー色で透過する背景で強調します。一部のブラウザーで付加されるデフォルトのフォーカス強調を取り除くため、{{cssxref("outline")}} プロパティを追加することが重要ですので注意してください。

+ +
input:focus, textarea:focus {
+  background   : rgba(0,0,0,.1);
+  border-radius: 5px;
+}
+ +

テキストフィールドのスタイル設定が完了して、次は単一行および複数行のテキストフィールドの表示が同じになるよう調整しなければなりません。これは、一般的にこれらのデフォルト表示が同じでないためです。

+ +

Tweaking the textareas

+ +

{{HTMLElement("textarea")}} 要素はデフォルトでブロック要素としてレンダリングされるようにします。ここで重要なことは、{{cssxref("resize")}} プロパティと {{cssxref("overflow")}} プロパティの 2 つです。ここでは固定サイズでデザインしているため、ユーザーが複数行のテキストフィールドをリサイズできないように resize プロパティを使用します。{{cssxref("overflow")}} プロパティは、ブラウザー間でのフィールドの一貫性を向上させるために使用します。これのデフォルト値が auto であるブラウザーと scroll であるブラウザーが存在します。この例では、すべてのブラウザーが auto になるようにするのがよいでしょう。

+ +
textarea {
+  display : block;
+
+  padding : 10px;
+  margin  : 10px 0 0 -10px;
+  width   : 100%;
+  height  : 90%;
+
+  border-right: 1px solid;
+
+  /* resize  : none; */
+  overflow: auto;
+}
+ +

送信ボタンにスタイル設定する

+ +

{{HTMLElement("button")}} 要素は、CSS によってより便利になります。疑似要素を含めて、行いたいことが何でもできます!

+ +
button {
+  padding      : 5px;
+  font         : bold .6em sans-serif;
+  border       : 2px solid #333;
+  border-radius: 5px;
+  background   : none;
+  cursor       : pointer;
+  transform    : rotate(-1.5deg);
+}
+
+button:after {
+  content      : " >>>";
+}
+
+button:hover,
+button:focus {
+  outline     : none;
+  background  : #000;
+  co
+ +

最終結果

+ +

これでよし! フォームは次のようになるでしょう:

+ +

+ +
+

: 例が期待どおり動かず、われわれのバージョンを確認したい場合、GitHub にあります — ライブ版を見てください (ソースコードも見てください)。

+
+ +

スキルを試しましょう!​

+ +

この記事の終わりまで到達しました。しかし、肝要な点を思い起こせるでしょうか?次に進む前に、テストによって知識の定着を試すことができます——スキルテスト:スタイリングの基本をご覧ください。

+ +

まとめ

+ +

ご覧いただいたとおり、テキストフィールドとボタンだけでフォームを作成する限りでは、CSS を使用したスタイル設定は容易です。次の記事では、"不良" や "劣悪" カテゴリに入っているウィジェットの扱い方を見ていきます。

+ +

{{PreviousMenuNext("Learn/Forms/Other_form_controls","Learn/Forms/Advanced_form_styling","Learn/Forms")}}

+ +

このモジュール

+ +

E

+ + + +

上級トピック

+ +

セクション

+ + diff --git a/files/ja/learn/forms/the_native_form_widgets/index.html b/files/ja/learn/forms/the_native_form_widgets/index.html new file mode 100644 index 0000000000..f0ddcdc09d --- /dev/null +++ b/files/ja/learn/forms/the_native_form_widgets/index.html @@ -0,0 +1,339 @@ +--- +title: 基本的なネイティブフォームコントロール +slug: Learn/Forms/The_native_form_widgets +tags: + - Example + - Forms + - Guide + - HTML + - Intermediate + - Web +translation_of: Learn/Forms/Basic_native_form_controls +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}
+ +

直前の記事では、機能的なウェブフォームの例をマークアップし、いくつかのフォームコントロールとよくある構造要素を導入し、アクセシビリティのベストプラクティスを見てきました。次にさまざまなフォームコントロールやウィジェットの機能を詳しく見ていきます — 色々な種類のデータを集めるのにどんなオプションが使えるのかを見ていきます。とりわけこの記事では、ウェブの初期からある全てのブラウザーで利用できる、オリジナルのフォームコントロールを見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーと、基本的な HTML の理解
目的:データを収集するためにブラウザーで使用できるネイティブフォームウィジェットの種類と、それらを HTML を使用して実装する方法を理解する。
+ +

{{HTMLelement('form')}}, {{HTMLelement('fieldset')}}, {{HTMLelement('legend')}}, {{HTMLelement('textarea')}}, {{HTMLelement('label')}}, {{HTMLelement('button')}},  {{HTMLelement('input')}}といったフォーム要素については既に見てきました。この記事では次を網羅します:

+ + + +
+

: この記事で説明されている機能のほとんどは、ブラウザー間で幅広くサポートされています。これに対する例外に注意しましょう。より正確な詳細が必要な場合は、HTML フォーム要素のリファレンス、特に広範囲にわたる <input> 型の参照を参照してください。

+
+ +

テキスト入力フィールド

+ +

テキスト {{htmlelement("input", "入力")}} フィールドは最も基本的なフォームウィジェットです。これらはユーザーがあらゆる種類のデータを入力できるとても便利な方法です。

+ +
+

: HTML フォームのテキストフィールドは単純なプレーンテキストの入力コントロールです。つまり、これらを使ってリッチエディット (太字、斜体など) を実行することはできません。見かけるすべてのリッチテキストエディタは、HTML、CSS、および JavaScript で作成されたカスタムウィジェットです。

+
+ +

すべてのテキストフィールドに共通する動作があります:

+ + + +
+

: {{htmlelement("input")}} 要素は、type 属性によってさまざまなフォームとなるため、、HTML要素の中でも特別です。単一行のテキストフィールド、テキスト入力のないコントロール、時間と日付のコントロール、チェックボックス、カラーピッカー、ボタンといったテキスト入力のないコントロールなど、ほとんどのタイプのフォームウィジェットの作成に使用されます。

+
+ +

単一行のテキストフィールド

+ +

単一行のテキストフィールドは、{{htmlattrxref("type","input")}} 属性値が text に設定されている {{HTMLElement("input")}} 要素を使用するか、{{htmlattrxref("type","input")}} 属性を指定しない場合( text がデフォルト値になり)に作成されます。{{htmlattrxref("type","input")}} 属性に指定した値がブラウザーに認識されない場合 (たとえば type="color" を指定してブラウザーがネイティブの色ピッカーをサポートしていない場合)、この属性の値のテキストは代替値になります。

+ +
+

: GitHub の single-line-text-fields.html に、すべての単一行テキストフィールドタイプの例があります (こちらも参照してください)。

+
+ +

これは基本的な単一行のテキストフィールドの例です。

+ +
<input type="text" id="comment" name="comment" value="I'm a text field">
+ +

単一行のテキストフィールドは、ひとつだけ厳密な制約があります: 改行を含むテキストを入力した場合、ブラウザーはデータを送信する前に改行を取り除きます。

+ +

下記のスクリーンショットは macOS での Firefox 71 と Safari と Windows 10 の Chrome 79 と Edge 18 にて、既定の、フォーカスされた、無効にされたテキスト入力を示しています。

+ +

Screenshot of the disabled attribute and default :focus styles on a text input in Firefox, Safari, Chrome and Edge.

+ +
+

HTML5 では {{htmlattrxref("type","input")}} 属性に専用の値を追加することで、基本的な単一行のテキストフィールドを拡張しています。これらの値もやはり {{HTMLElement("input")}} 要素を単一行のテキストフィールドにしますが、フィールドに対して追加の制約や機能を付加します。

+
+ +

パスワードフィールド

+ +

このタイプのフィールドは、{{htmlattrxref("type","input")}} 属性の値 password を使用して設定できます:

+ +
<input type="password" id="pwd" name="pwd">
+ +

password の値は入力したテキストに対する特別な制約は付加しませんが、フィールドの値を隠します(例、ドットやアスタリスク)ので読むことができません。

+ +

これはユーザーインターフェイスの機能でしかないことに注意してください。テキストは JavaScript を使用してあなた自身でエンコードしなければ、平文で送信されてしまい、セキュリティには良くありません — 悪い組織がデータを遮ってパスワードや、クレジットカードデータや、送信したあらゆるものを盗むことがあります。ユーザーからこれを保護するためにはフォームを含むあらゆるページをセキュア通信でホストし (つまり https:// ... アドレスにて) 、データ送信前に暗号化することです。

+ +

最近のブラウザーは、安全でない接続を介してフォームデータを送信することによるセキュリティへの影響を認識しており、ユーザーが安全でないフォームを使用しないように警告を実装しています。Firefox が実装しているものの詳細については、安全でないパスワードをご覧ください。

+ +

隠しコンテンツ

+ +

もう1つのオリジナルなテキストコントロールは hidden 入力タイプです。これは他のフォームデータとともにサーバー送信されるがユーザーからは見えないデータを持つのに使われています — 例えば命令を発行するときにサーバーにタイムスタンプを送りたい場合。これは隠れているので、ユーザーが見ることも、意図せずに値を編集することもなく、フォーカスを得ることもないしスクリーンリーダーが気づくこともありません。

+ +
<input type="hidden" id="timestamp" name="timestamp" value="1286705410">
+
+ +

このような要素を作成する場合は、name 属性と value 属性の設定が必要です。この値は JavaScript にて動的にセットできます。hidden 入力タイプには関連したラベルはありません。

+ +

その他のテキストタイプ、{{HTMLElement("input/search", "search")}}, {{HTMLElement("input/url", "url")}}, と{{HTMLElement("input/tel", "tel")}}, は HTML5 で追加されました。これは次のチュートリアルの「HTML5 入力タイプ」にて網羅されます。

+ +

チェック可能アイテム:チェックボックスとラジオボタン

+ +

チェック可能アイテムは、そのものや、関連したラベルをクリックすることで状態を変更できるコントロールです。チェック可能アイテムは 2 種類あります: チェックボックスとラジオボタンです。どちらもデフォルトでチェックするかを示すために、checked 属性を使用します。

+ +

これらのウィジェットは、他のフォームウィジェットと同じようには動作しない点が特筆されます。ほとんどのフォームウィジェットではフォームを送信すると、name 属性を持つすべてのウィジェットは値がなくても送信します。チェック可能アイテムでは、それらがチェックされている場合にのみ値を送信します。チェックされていない場合は、name も含めて何も送信しません。チェックされているが値がない場合、name が on という値で送信されます。

+ +
+

: このセクションの例は、checkable-items.html として GitHub にあります (こちらも参照してください)。

+
+ +

最大限のユーザービリティ/アクセシビリティを実現するために、関連項目の各リストを {{htmlelement("fieldset")}} で囲み、リストの全体的な説明を示す {{htmlelement("legend")}} で囲むことをお勧めします。{{htmlelement("label")}}/{{htmlelement("input")}} 要素の個々のペアは、それぞれ独自のリスト項目 (または同様のもの) に含める必要があります。関連した {{htmlelement('label')}} はラジオボタンやチェックボックスの直後に、{{htmlelement("legend")}}の中身にラジオボタンやチェックボックスのグループの説明が置かれます。これは上の例に示されています。

+ +

チェックボックス

+ +

チェックボックスは、type 属性を {{HTMLElement("input/checkbox", "checkbox")}} に設定した {{HTMLElement("input")}} 要素で作成します。

+ +
<input type="checkbox" checked id="carrots" name="carrots" value="carrots">
+ +

checked 属性を含んだチェックボックスはページ読み込み時に自動的にチェックされます。チェックボックスまたはその関連ラベルをチェックするとチェックボックスのオン/オフがトグルされます。

+ +

下記のスクリーンショットは macOS での Firefox 71 と Safari と Windows 10 の Chrome 79 と Edge 18 にて、既定の、フォーカスされた、無効にされたチェックボックスを示しています。

+ +

Default, focused and disabled Checkboxes in Firefox 71 and Safari 13 on Mac and Chrome 79 and Edge 18 on Windows 10

+ +
+

: checked 属性のあるあらゆるチェックボックスやラジオボタンには、チェックされていない場合でも、対応する {{cssxref(':default')}} 仮想クラスがあります。現在チェックされているものには{{cssxref(':checked')}} 仮想クラスがあります。

+
+ +

チェックボックスのオンオフ性質により、チェックボックスは、規定のチェックボックスを拡張してトグルスイッチのように見えるボタンを作っている開発者やデザイナーにとって、トグルボタンとして考えられます。ここで動作する例を 見ることができます(ソースコードも見られます)。

+ +

ラジオボタン

+ +

ラジオボタンは、{{htmlattrxref("type","input")}} 属性を radio に設定した {{HTMLElement("input")}} 要素で作成します。

+ +
<input type="radio" checked id="soup" name="meal">
+ +

いくつかのラジオボタンをまとめることができます。{{htmlattrxref("name","input")}} 属性で同じ値を共有すると、それらのラジオボタンは同じボタングループに属するとみなされます。グループ内でボタンは同時に 1 つだけチェックできます。つまり、あるラジオボタンをチェックすると、他のラジオボタンは自動的にチェックが外れます。フォームを送信するときは、チェックしているラジオボタンのみの値を送信します。何もチェックしていない場合はラジオボタンの集まり全体が未知の状態であるとみなし、フォーム送信時は値を送信しません。

+ +
<fieldset>
+  <legend>What is your favorite meal?</legend>
+  <ul>
+    <li>
+      <label for="soup">Soup</label>
+      <input type="radio" checked id="soup" name="meal" value="soup">
+    </li>
+    <li>
+      <label for="curry">Curry</label>
+      <input type="radio" id="curry" name="meal" value="curry">
+    </li>
+    <li>
+      <label for="pizza">Pizza</label>
+      <input type="radio" id="pizza" name="meal" value="pizza">
+    </li>
+  </ul>
+</fieldset>
+ +

下記のスクリーンショットは macOS での Firefox 71 と Safari と Windows 10 の Chrome 79 と Edge 18 にて、チェックなしとチェックされたラジオボタン、フォーカスされた、また無効でチェックなしとチェックされたラジオボタンを示しています。

+ +

Radio buttons on Firefox 71 and Safari 13 on Mac and Chrome 79 and Edge 18 on Windows 10

+ +

ボタン

+ +

ラジオボタンはその名に反して、実際のボタンではありません。実際のボタンを見てみましょう! ボタンを生成するには、3 種類の入力タイプがあります:

+ +
+
{{原語併記("送信", "Submit")}}
+
フォームデータをサーバーに送信します。{{HTMLElement("button")}} 要素の場合、type 属性 (または type の無効な値) を省略すると、送信ボタンが表示されます。
+
{{原語併記("リセット", "Reset")}}
+
すべてのフォームウィジェットをデフォルト値にリセットします。
+
button
+
自動的な効果のないボタンで、JavaScript コードを用いてカスタマイズできるもの。
+
+ +

それから、{{htmlelement("button")}} 要素それ自体もあります。これは値が submitreset または button である type 属性をとり、上記の 3 つの <input> 種別を模倣できます。この 2 つの主な違いは実際の <button> 要素の方が多くのスタイル設定できることです。

+ +
+

: image 入力タイプもボタンとしてレンダリングされます。それはあとで見ます。

+
+ +
+

: このセクションの例は button-examples.html として GitHub にあります (こちらも参照してください)。

+
+ +

ボタンは {{HTMLElement("button")}} 要素か {{HTMLElement("input")}} 要素で作成します。どの種類のボタンを表示するかを指定するのは、{{htmlattrxref("type","input")}} 属性の値です:

+ +

送信

+ +
<button type="submit">
+    This a <br><strong>submit button</strong>
+</button>
+
+<input type="submit" value="This is a submit button">
+ +

リセット

+ +
<button type="reset">
+    This a <br><strong>reset button</strong>
+</button>
+
+<input type="reset" value="This is a reset button">
+ +

無名

+ +
<button type="button">
+    This an <br><strong>anonymous button</strong>
+</button>
+
+<input type="button" value="This is an anonymous button">
+ +

ボタンは {{HTMLElement("button")}} 要素でも {{HTMLElement("input")}} 要素でも、常に同じ動作になります。上記のサンプルでわかるように、{{HTMLElement("button")}} 要素はラベルとして HTML コンテンツを使用できて、これは開始と終了の<button>タグの間に挿入されます。一方で{{HTMLElement("input")}} 要素は空要素です。つまり value 属性の中にラベルが挿入され、このためプレーンテキストのコンテンツのみ使用できます。

+ +

下記の例は macOS での Firefox 71 と Safari と Windows 10 の Chrome 79 と Edge 18 にて、既定の、フォーカスされた、無効なボタンを示しています。

+ +

Default, focused and disabled button input types in Firefox 71 and Safari 13 on Mac and Chrome 79 and Edge 18 on Windows 10

+ +

画像ボタン

+ +

画像ボタンコントロールは {{HTMLElement("img")}} 要素とまったく同じように表示されますが、ユーザーがクリックすると送信ボタン (前述) のように動作します。

+ +

画像ボタンは、{{htmlattrxref("type","input")}} 属性を image に設定した {{HTMLElement("input")}} 要素で作成します。

+ +

この要素は {{HTMLElement("img")}} 要素とまったく同じ属性をサポートして、さらにフォームボタンがサポートする属性もすべてサポートします。

+ +
<input type="image" alt="Click me!" src="my-img.png" width="80" height="30" />
+ +

画像ボタンをフォームの送信に使用する際にこのウィジェットは自身の値を送信しませんが、代わりに画像上でクリックした位置の X 座標と Y 座標を送信します (座標は画像に対して相対的、つまり画像の左上隅が座標 0, 0 になります)。座標は 2 つのキーと値の組として送信されます。

+ + + +

サンプルをご覧ください。フォームの画像上の座標 (123, 456) でクリックすると、 get メソッド経由で送信されて、以下のような値の追加された URL が送信されます:

+ +
http://foo.com?pos.x=123&pos.y=456
+ +

これは "hot map" を作成するためにとても便利な手段です。これらの値がどのように送信あるいは取得されるかについては、フォームデータの送信の記事で詳しく説明します。

+ +

ファイルピッカー

+ +

初期のHTMLであった最後の <input> タイプがあります: ファイル入力タイプです。フォームで、ファイルをサーバーに送信できます。この特定操作については以下の記事で詳しく説明します: フォームデータの送信。ファイルピッカーウィジェットで、ユーザーは送信するファイルを 1 つ以上選択できます。

+ +

ファイルピッカーウィジェットを作成するには、{{htmlattrxref("type","input")}} 属性を file に設定した {{HTMLElement("input")}} 要素を使用します。{{htmlattrxref("accept","input")}} 属性を使用して、受け入れるファイルの種類を制限できます。加えて、ユーザーが複数のファイルを選択できるようにしたい場合は、{{htmlattrxref("multiple","input")}} 属性を付加します。

+ +

+ +

以下の例では、画像ファイルを要求するファイルピッカーを作成しています。ユーザーは複数のファイルを指定できます。

+ +
<input type="file" name="file" id="file" accept="image/*" multiple>
+ +

いくつかのモバイルデバイスでは、ファイルピッカーは、次のようにキャプチャー情報を accept 属性に追加することで、端末のカメラやマイクでキャプチャーされた写真、動画、オーディオにアクセスできます:

+ +
<input type="file" accept="image/*;capture=camera">
+<input type="file" accept="video/*;capture=camcorder">
+<input type="file" accept="audio/*;capture=microphone">
+ +

共通属性

+ +

フォームウィジェットを定義するために使用される要素の多くは、独自の属性をいくつか持っています。ただし、すべてのフォーム要素に共通の一連の属性があり、それによりウィジェットをある程度制御できます。共通属性のリストは以下のとおりです。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性名既定値説明
autofocusfalseこの真偽値属性を使用すると、ユーザーがページをロードするときに、たとえば別のコントロールを入力して上書きしない限り、要素に自動的に入力フォーカスするように指定できます。この属性を指定できるのは、文書内の 1 つのフォーム関連要素だけです。
disabledfalseこの真偽値属性は、ユーザーが要素と対話できないことを示します。この属性が指定されていない場合、要素はそれを含む要素 (例えば {{HTMLElement("fieldset")}}) からその設定を継承します。disabled 属性が設定されている包含要素がない場合は、その要素が有効になります。
formウィジェットが関連付けられている <form> 要素。属性の値は、同じ文書内の {{HTMLElement("form")}} 要素の id 属性でなければなりません。理論的には、フォームウィジェットを {{HTMLElement("form")}} 要素の外側に設定できます。しかし実際には、その機能をサポートするブラウザーはありません。
name要素の名前。これはフォームデータとともに送信されます。
value要素の初期値
+ +

スキルをテストしましょう!

+ +

この記事の最後に到着しましたが、最も大事な情報を覚えていますか? 次に進む前に、この情報を保持しているか検証するテストがあります — Test your skills: Basic controls を見てください。

+ +

まとめ

+ +

上で見たように、利用可能なフォーム要素には多くの異なるタイプがあります。一度にこれらの詳細の全てを覚えておく必要はありません。詳細について調べるために好きなだけこの記事に戻ることができます 。

+ +

この記事では古い入力タイプをカバーしてきました — これは HTML の初期の頃に導入されたオリジナルで、すべてのブラウザーでよくサポートされます。次のセクションでは、HTML 5 で追加された新しい type 属性の値を見ていきます。

+ +

{{PreviousMenuNext("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/ui_pseudo-classes/index.html b/files/ja/learn/forms/ui_pseudo-classes/index.html new file mode 100644 index 0000000000..8ab11cbac6 --- /dev/null +++ b/files/ja/learn/forms/ui_pseudo-classes/index.html @@ -0,0 +1,616 @@ +--- +title: UI 擬似クラス +slug: Learn/Forms/UI_pseudo-classes +tags: + - Beginner + - CSS + - Example + - Forms + - Guide + - HTML + - Pseudo-classes + - Styling + - Web +translation_of: Learn/Forms/UI_pseudo-classes +--- +

{{LearnSidebar}}{{PreviousMenuNext("Learn/Forms/Advanced_form_styling", "Learn/Forms/Form_validation", "Learn/Forms")}}

+ +

In the previous articles we covered the styling of various form controls, in a general manner. This included some usage of pseudo-classes, 例えば、using :checked to target a checkbox only when it is selected. In this article, we will explore in detail the different UI pseudo-classes available to us in modern browsers for styling forms in different states.

+ + + + + + + + + + + + +
前提条件:Basic computer literacy, and a basic understanding of HTML and CSS, including general knowledge of pseudo-classes and pseudo-elements.
目的:To understand what parts of forms are hard to style, and why; to learn what can be done to customize them.
+ +

疑似クラスで何が利用できるか?

+ +

The original pseudo-classes available to us (as of CSS 2.1) that are relevant to forms are:

+ + + +

These basic pseudo-classes should be familiar to you now. More recently, the CSS Selector Level 3 and CSS Basic UI Level 3 added more pseudo-classes related to HTML forms that provide several other useful targetting conditions that you can take advantage of. We'll discuss these in more detail in the sections below, but briefly, the main ones we'll be looking at are:

+ + + +

There are many others too, but the ones listed above are the most obviously useful. Some of the others are aimed at solving very specific niche problems, or simply not very well supported in browsers yet. The ones listed above all have pretty good browser support, but of course you should test your form implementations carefully to make sure they work for your target audience.

+ +
+

: A number of the pseudo-classes discussed here are concerned with styling form controls based on their validation state (is their data valid, or not?) You'll learn much more about setting and controlling validation constraints in our next article — Client-side form validation — but for now we'll keep things simple with regards to form validation, so it doesn't confuse things.

+
+ +

入力が必須か否かでスタイル設定する

+ +

One of the most basic concepts with regards to client-side form validation is whether a form input is required (it has to be filled in before the form can be submitted) or optional.

+ +

{{htmlelement('input')}}, {{htmlelement('select')}}, and {{htmlelement('textarea')}} elements have a required attribute available which, when set, means that you have to fill in that control before the form will successfully submit. 例えば、:

+ +
<form>
+  <fieldset>
+    <legend>Feedback form</legend>
+    <div>
+      <label for="fname">First name: </label>
+      <input id="fname" name="fname" type="text" required>
+    </div>
+    <div>
+      <label for="lname">Last name: </label>
+      <input id="lname" name="lname" type="text" required>
+    </div>
+    <div>
+      <label for="email">Email address (include if you want a response): </label>
+      <input id="email" name="email" type="email">
+    </div>
+    <div><button>Submit</button></div>
+  </fieldset>
+</form>
+ +

Here, the first name and last name are required, but the email address is optional.

+ +

You can match these two states using the {{cssxref(':required')}} and {{cssxref(':optional')}} pseudo-classes. 例えば、if we apply the following CSS to the above HTML:

+ +
input:required {
+  border: 1px solid black;
+}
+
+input:optional {
+  border: 1px solid silver;
+}
+ +

The required controls would have a black border, and the optional control will have a silver border, like so:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/basic-required-optional.html", '100%', 400)}}

+ +

You can also try submitting the form without flling it in, to see the client-side validation error messages browsers give you 既定では.

+ +

The above form isn't bad, but it isn't great either. For a start, we are signalling required versus optional status using color alone, which isn't great for colorblind people. Second, the standard convention on the web for required status is an asterisk (*), or the word "required" being associated with the controls in question.

+ +

In the next section we'll look at a better example of indicating required fields using :required, which also digs into using generated content.

+ +
+

: You'll probably not find yourself using the :optional pseudo-class very often. Form controls are optional 既定では, so you could just do your optional styling 既定では, and add styles on top for required controls.

+
+ +
+

: If one radio button in a same-named group of radio buttons has the required attribute, all the radio buttons will be invalid until one is selected, but only the one with the attribute assigned will actually match {{cssxref(':required')}}.

+
+ +

疑似クラスでコンテンツを生成する

+ +

In previous articles we've seen usage of generated content, but we thought now would be a good time to talk about it in a bit more detail.

+ +

The idea is that we can use the ::before and ::after pseudo-elements along with the content property to make a chunk of content appear before or after the affected element. The chunk of content is not added to the DOM, so is invisible to screenreaders; it is part of the document's styles. Because it is a pseudo element, it can be targetted with styles in the same way that any actual DOM node can.

+ +

This is really useful when you want to add a visual indicator to an element, such as a label or icon, but don't want it to be picked up by assistive technologies. 例えば、in our custom radio buttons example, we use generated content to handle the placement and animation of the inner circle when a radio button is selected:

+ +
input[type="radio"]::before {
+  display: block;
+  content: " ";
+  width: 10px;
+  height: 10px;
+  border-radius: 6px;
+  background-color: red;
+  font-size: 1.2em;
+  transform: translate(3px, 3px) scale(0);
+  transform-origin: center;
+  transition: all 0.3s ease-in;
+}
+
+input[type="radio"]:checked::before {
+  transform: translate(3px, 3px) scale(1);
+  transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
+}
+ +

This is really useful — screenreaders already let their users know when a radio button or checkbox they encounter is checked/selected, so you don't want them to read out another DOM element that indicates selection — that could be confusing. Having a purely visual indicator solves this problem.

+ +
+

: This also shows how you can combine a pseudo-class and pseudo-element if required.

+
+ +

Back to our required/optional example from before, this time we'll not alter the appearance of the input itself — we'll use generated content to add an indicating label (see it live here, and see the source code here).

+ +

First of all, we'll add a paragraph to the top of the form to say what you are looking for:

+ +
<p>Required fields are labelled with "required".</p>
+ +

Screenreader users will get "required" read out as an extra bit of information when they get to each required input, which sighted users will get our label.

+ +

Since form inputs don't directly support having generated content put on them (this is because generated content is placed relative to an element's formatting box, but form inputs work more like replaced elements and therefore don't have one), we will add an empty <span> to hang the generated content on:

+ +
<div>
+  <label for="fname">First name: </label>
+  <input id="fname" name="fname" type="text" required>
+  <span></span>
+</div>
+ +

The immediate problem with this was that the span was dropping onto a new line below the input, because the input and label are both set with width: 100%. To fix this we style the parent <div> to become a flex container, but also tell it to wrap its contents onto new lines if the content becomes too long:

+ +
fieldset > div {
+  margin-bottom: 20px;
+  display: flex;
+  flex-flow: row wrap;
+}
+ +

The effect this has is that the label and input sit on separate lines because they are both width: 100%, but the <span> has a width of 0 so can sit on the same line as the input.

+ +

Now onto the generated content. We create it using this CSS:

+ +
input + span {
+  position: relative;
+}
+
+input:required + span::after {
+  font-size: 0.7rem;
+  position: absolute;
+  content: "required";
+  color: white;
+  background-color: black;
+  padding: 5px 10px;
+  top: -26px;
+  left: -70px;
+}
+ +

We set the <span> to position: relative simply so that we can set the generated content to position: absolute and position it relative to the <span> rather than the <body> (The generated content acts as though it is a child node of the element it is generated on, for the purposes of positioning).

+ +

Then we give the generated content the content "required", which is what we wanted our label to say, and style and position it as we want. The result is seen below.

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/required-optional-generated.html", '100%', 430)}}

+ +

データが妥当が否かでコントロールをスタイル設定する

+ +

The other really important, fundamental concept in form validation is whether a form control's data is valid or not (in the case of numerical data, we can also talk about in-range and out-of-range data). Form controls with constraint limitations can be targeted based on these states.

+ +

:valid と :invalid

+ +

You can target from control using the {{cssxref(":valid")}} and {{cssxref(":invalid")}} pseudo-classes. Some points worth bearing in mind:

+ + + +

Let's go in and look at a simple example of :valid/:invalid (see valid-invalid.html for the live version, and also check out the source code).

+ +

As in the previous example, we've got extra <span>s to generate content on, which we'll use to provide indicators of valid/invalid data:

+ +
<div>
+  <label for="fname">First name *: </label>
+  <input id="fname" name="fname" type="text" required>
+  <span></span>
+</div>
+ +

To provide these indicators, we use the following CSS:

+ +
input + span {
+  position: relative;
+}
+
+input + span::before {
+  position: absolute;
+  right: -20px;
+  top: 5px;
+}
+
+input:invalid {
+  border: 2px solid red;
+}
+
+input:invalid + span::before {
+  content: '✖';
+  color: red;
+}
+
+input:valid + span::before {
+  content: '✓';
+  color: green;
+}
+ +

As before, we set the <span>s to position: relative so that we can position the generated content relative to them. We then absolutely position different generated content depending on whether the form's data is valid or invalid — a green check or a red cross, respectively. To add a bit of extra urgency to the invalid data, we've also given the inputs a thick red border when invalid.

+ +
+

: We've used ::before to add these labels, as we were already using ::after for the "required" labels.

+
+ +

You can try it below:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/valid-invalid.html", '100%', 430)}}

+ +

Notice how the required text inputs are invalid when empty, but valid when they have something filled in. The email input on the other hand is valid when empty, as it is not required, but invalid when it contains something that is not a proper email address.

+ +

範囲内と範囲外のデータ

+ +

As we hinted at above, there are two other related pseudo-classes to consider — {{cssxref(":in-range")}} and {{cssxref(":out-of-range")}}. These match numeric inputs where range limits are specified by the {{htmlattrxref("min", "input")}} and {{htmlattrxref("max","input")}}, when their data is inside or outside the specified range, respectvely.

+ +
+

: Numeric input types are date, month, week, time, datetime-local, number, and range.

+
+ +

It is worth noting that inputs whose data is in-range will also be matched by the :valid pseudo-class, and inputs whose data is out-of-range will also be matched by the :invalid pseudo-class. So why have both? The issue is really one of semantics — out-of-range is a more specific type of invalid communication, so you might want to provide a different message for out-of-range inputs, which will be more helpful to users than just saying "invalid". You might even want to provide both.

+ +

Let's look at an example that does exactly this. Our out-of-range.html demo (see also the source code) builds on top of the previous example to provide out-of-range messages for the numeric inputs, as well as saying whether they are required.

+ +

The numeric input looks like this:

+ +
<div>
+  <label for="age">Age (must be 12+): </label>
+  <input id="age" name="age" type="number" min="12" max="120" required>
+  <span></span>
+</div>
+ +

And the CSS looks like this:

+ +
input + span {
+  position: relative;
+}
+
+input + span::after {
+  font-size: 0.7rem;
+  position: absolute;
+  padding: 5px 10px;
+  top: -26px;
+}
+
+input:required + span::after {
+  color: white;
+  background-color: black;
+  content: "Required";
+  left: -70px;
+}
+
+input:out-of-range + span::after {
+  color: white;
+  background-color: red;
+  width: 155px;
+  content: "Outside allowable value range";
+  left: -182px;
+}
+ +

This is a similar story to what we had before in the :required example, except that here we've split out the declarations that apply to any ::after content into a separate rule, and given the separate ::after content for :required and :out-of-range states their own content and styling. You can try it here:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/out-of-range.html", '100%', 430)}}

+ +

It is possible for the number input to be both required and out-of-range at the same time, so what happens then? Because the :out-of-range rule appears later in the source code than the :required rule, the cascade rules come into play, and the out of range message is shown.

+ +

This works quite nicely — when the page first loads, "Required" is shown, along with a red cross and border. When you've typed in a valid age (i.e. in the range of 12-120), the input turns valid. If however, you then change the age entry to one that is out of range, the "Outside allowable value range" message then pops up in place of "Required".

+ +
+

: To enter an invalid/out-of-range value, you'll have to actually focus the form and type it in using the keyboard. The spinner buttons won't let you increment/decrement the value outside the allowable range.

+
+ +

有効/無効や読み取り専用/読み書き可能の入力をスタイル設定する

+ +

An enabled element is an element that can be activated; it can be selected, clicked on, typed into, etc.  A disabled element on the other hand cannot be interacted with in any way, and its data isn't even sent to the server

+ +

These two states can be targeted using {{cssxref(":enabled")}} and {{cssxref(":disabled")}}. Why are disabled inputs useful? Well, sometimes if some data does not apply to a certain user, you might not even want to submit that data when they submit the form. A classic example is a shipping form — commonly you'll get asked if you want to use the same address for billing and shipping; if so, you can just send a single address to the server, and might as well just disable the billing address fields.

+ +

Let's have a look at an example that does just this. First of all, the HTML is a simple form containing text inputs, plus a checkbox to toggle disabling the billing address on and off. The billing address fields are disabled 既定では.

+ +
<form>
+  <fieldset id="shipping">
+    <legend>Shipping address</legend>
+    <div>
+      <label for="name1">Name: </label>
+      <input id="name1" name="name1" type="text" required>
+    </div>
+    <div>
+      <label for="address1">Address: </label>
+      <input id="address1" name="address1" type="text" required>
+    </div>
+    <div>
+      <label for="pcode1">Zip/postal code: </label>
+      <input id="pcode1" name="pcode1" type="text" required>
+    </div>
+  </fieldset>
+  <fieldset id="billing">
+    <legend>Billing address</legend>
+    <div>
+      <label for="billing-checkbox">Same as shipping address:</label>
+      <input type="checkbox" id="billing-checkbox" checked>
+    </div>
+    <div>
+      <label for="name" class="billing-label disabled-label">Name: </label>
+      <input id="name" name="name" type="text" disabled required>
+    </div>
+    <div>
+      <label for="address2" class="billing-label disabled-label">Address: </label>
+      <input id="address2" name="address2" type="text" disabled required>
+    </div>
+    <div>
+      <label for="pcode2" class="billing-label disabled-label">Zip/postal code: </label>
+      <input id="pcode2" name="pcode2" type="text" disabled required>
+    </div>
+  </fieldset>
+
+  <div><button>Submit</button></div>
+</form>
+ +

Now onto the CSS. The most relevant parts to this example are as follows:

+ +
input[type="text"]:disabled {
+    background: #eee;
+    border: 1px solid #ccc;
+}
+
+.disabled-label {
+  color: #aaa;
+}
+ +

We've directly selected the inputs we want to disable using input[type="text"]:disabled, but we also wanted to gray out the corresponding text labels. These weren't quite as easy to select, so we've used a class to provide them with that styling.

+ +

Now finally, we've used some JavaScript to toggle the disabling of the billing address fields:

+ +
// Wait for the page to finish loading
+document.addEventListener('DOMContentLoaded', function () {
+
+  // Attach `change` event listener to checkbox
+  document.getElementById('billing-checkbox').addEventListener('change', toggleBilling);
+}, false);
+
+function toggleBilling() {
+  // Select the billing text fields
+  let billingItems = document.querySelectorAll('#billing input[type="text"]');
+  // Select the billing text labels
+  let billingLabels = document.querySelectorAll('.billing-label');
+
+  // Toggle the billing text fields and labels
+  for (let i = 0; i < billingItems.length; i++) {
+    billingItems[i].disabled = !billingItems[i].disabled;
+
+    if(billingLabels[i].getAttribute('class') === 'billing-label disabled-label') {
+      billingLabels[i].setAttribute('class', 'billing-label');
+    } else {
+      billingLabels[i].setAttribute('class', 'billing-label disabled-label');
+    }
+  }
+}
+ +

It uses the change event to let the user enable/disable the billing fields, and toggle the styling of the associated labels.

+ +

You can see the example in action below (also see it live here, and see the source code):

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/enabled-disabled-shipping.html", '100%', 600)}}

+ +

Read-only and read-write

+ +

In a similar manner to :disabled and :enabled, the :read-only and :read-write pseudo-classes target two states that form inputs toggle between. Read-only inputs have their values submitted to the server, but the user can't edit them, whereas read-write means they can be edited — their default state.

+ +

An input is set to read-only using the readonly attribute. As an example, imagine a confirmation page where the developer has sent the details filled in on previous pages over to this page, with the aim of getting the user to check them all in one place, add any final data that is needed, and then confirm the order by submitting. At this point, all the final form data can be sent to the server in one go.

+ +

Let's look at what a form might look like (see readonly-confirmation.html for the live example; also see the source code).

+ +

A fragment of the HTML is as follows — note the readonly attribute:

+ +
<div>
+  <label for="name">Name: </label>
+  <input id="name" name="name" type="text"
+         value="Mr Soft" readonly>
+</div>
+ +

If you try the live example, you'll see that the top set of form elements are not focusable, however the values are submitted when the form is submitted. We've also styled the read-only form controls using the :read-only pseudo-class, like so:

+ +
input:-moz-read-only, textarea:-moz-read-only {
+  border: 0;
+  box-shadow: none;
+  resize: none;
+  background-color: white;
+}
+
+input:read-only, textarea:read-only {
+  border: 0;
+  box-shadow: none;
+  resize: none;
+  background-color: white;
+}
+ +

Yes, you've guessed it — Firefox only supports it with a prefix, hence having to double up the ruleset.

+ +
+

: :enabled and read-write are two more pseudo-classes that you'll probably rarely use, given that they describe the default states of input elements.

+
+ +

ラジオとチェックボックスの状態 — チェック済み、既定、中間

+ +

As we've seen in earlier articles in the module, {{HTMLElement("input/radio", "radio buttons")}} and {{HTMLElement("input/checkbox", "checkboxes")}} can be checked or unchecked. But there are a couple of other states to consider too:

+ + + +

:checked

+ +

When checked, they will be matched by the {{cssxref(":checked")}} pseudo-class.

+ +

The most common use of this is to add a different style onto the checkbox/radiobutton when it is checked, in cases where you've removed the system default styling with appearance: none; and want to build the styles back up yourself. We saw examples of this in the previous article, when we talked about Using appearence: none on radios/checkboxes.

+ +

As a recap, the :checked code from our Styled radio buttons example looks like so:

+ +
input[type="radio"]::before {
+  display: block;
+  content: " ";
+  width: 10px;
+  height: 10px;
+  border-radius: 6px;
+  background-color: red;
+  font-size: 1.2em;
+  transform: translate(3px, 3px) scale(0);
+  transform-origin: center;
+  transition: all 0.3s ease-in;
+}
+
+input[type="radio"]:checked::before {
+  transform: translate(3px, 3px) scale(1);
+  transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
+}
+ +

You can try it out here:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/styling-examples/radios-styled.html", '100%', 200)}}

+ +

Basically, we build the styling for the radio button "inner circle" using the ::before pseudo element, but set a scale(0) transform on it. We then use a transition to make it nicely animate into view when the radio is selected/checked. The advantage of using a transform rather than transitioning width/height is that you can use transform-origin to make it grow from the center of the circle, rather than having it appear to grow from the circle's corner.

+ +

:default と :indeterminate

+ +

As mentioned above, the {{cssxref(":default")}} pseudo-class matches radios/checkboxes that are checked 既定では, on page load, even when unchecked. This could be useful for adding an indicator to a list of options to remind the user what the defaults (or starting options) were, in case they want to reset their choices.

+ +

Also mentioned above radios/checkboxes will be matched by the {{cssxref(":indeterminate")}} pseudo-class when they are in a state where they are neither checked nor unchecked. But what does this mean? Elements that are indeterminate include:

+ + + +

This isn't something you'll likely use very often. One use case could be an indicator to tell users that they really need to select a radio button before they move on.

+ +

Let's look at a couple of modified versions of the previous example that remind the user what the default option was, and style the radio buttons when indeterminate. Both of these have the following HTML structure for the inputs:

+ +
<p>
+  <input type="radio" name="fruit" value="cherry" id="cherry">
+  <label for="cherry">Cherry</label>
+  <span></span>
+</p>
+ +

For the :default example, we've added the checked attribute to the middle radio button input, so it will be selected 既定では when loaded. We then style this with the following CSS:

+ +
input ~ span {
+  position: relative;
+}
+
+input:default ~ span::after {
+  font-size: 0.7rem;
+  position: absolute;
+  content: "Default";
+  color: white;
+  background-color: black;
+  padding: 5px 10px;
+  right: -65px;
+  top: -3px;
+}
+ +

This provides a little "Default" label on the one the was originally selected when the page loaded. Note here we are using the general sibling combinator (~) rather than the adjacent sibling combinator (+) — we need to do this because the <span> does not come right after the <input> in the source order.

+ +

See the live result below:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/radios-checked-default.html", '100%', 200)}}

+ +
+

: You can also find the example live on GitHub at radios-checked-default.html (also see the source code.)

+
+ +

For the :indeterminate example, we've got no default selected radio button — this is important — if there was, then there would be no indeterminate state to style. We style the indeterminate radio buttons with the following CSS:

+ +
input[type="radio"]:indeterminate {
+  border: 2px solid red;
+  animation: 0.4s linear infinite alternate border-pulse;
+}
+
+@keyframes border-pulse {
+  from {
+    border: 2px solid red;
+  }
+
+  to {
+    border: 6px solid red;
+  }
+}
+ +

This creates a fun little animated border on the radio buttons, which hopefully indicates that you need to select one of them!

+ +

See the live result below:

+ +

{{EmbedGHLiveSample("learning-area/html/forms/pseudo-classes/radios-checked-indeterminate.html", '100%', 200)}}

+ +
+

: You can also find the example live on GitHub at radios-checked-indeterminate.html (also see the source code.)

+
+ +
+

: You can find an interesting example involving indeterminate states on the <input type="checkbox"> reference page.

+
+ +

その他の疑似クラス

+ +

There are a number of other pseudo-classes of interest, and we don't have space to write about them all in detail here. Let's talk about a few more that you should take the time to investigate.

+ +

The following are fairly well-supported in modern browsers:

+ + + +

The following are also interesting, but as yet not well-supported in browsers:

+ + + +

まとめ

+ +

This completes our look at UI pseudo-classes that relate to form inputs. Keep playing with them, and create some fun form styles! Next up, we'll move on to something different — client-side form validation.

+ +

{{PreviousMenuNext("Learn/Forms/Advanced_form_styling", "Learn/Forms/Form_validation", "Learn/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/forms/your_first_form/example/index.html b/files/ja/learn/forms/your_first_form/example/index.html new file mode 100644 index 0000000000..bddf242144 --- /dev/null +++ b/files/ja/learn/forms/your_first_form/example/index.html @@ -0,0 +1,113 @@ +--- +title: 例 +slug: Learn/Forms/Your_first_form/Example +tags: + - CodingScripting + - HTML + - Web + - ガイド + - フォーム + - 例 + - 初心者 + - 学習 +translation_of: Learn/Forms/Your_first_form/Example +--- +

これは最初の HTML フォームの記事のサンプルコードです。

+ +

簡単なフォーム

+ +

HTML コンテンツ

+ +
<form action="/my-handling-form-page" method="post">
+  <div>
+    <label for="name">Name:</label>
+    <input type="text" id="name" name="user_name">
+  </div>
+
+  <div>
+    <label for="mail">E-mail:</label>
+    <input type="email" id="mail" name="user_email">
+  </div>
+
+  <div>
+    <label for="msg">Message:</label>
+    <textarea id="msg" name="user_message"></textarea>
+  </div>
+
+  <div class="button">
+    <button type="submit">Send your message</button>
+  </div>
+</form>
+ +

CSS コンテンツ

+ +
form {
+  /* Just to center the form on the page */
+  margin: 0 auto;
+  width: 400px;
+
+  /* To see the limits of the form */
+  padding: 1em;
+  border: 1px solid #CCC;
+  border-radius: 1em;
+}
+
+div + div {
+  margin-top: 1em;
+}
+
+label {
+  /* To make sure that all label have the same size and are properly align */
+  display: inline-block;
+  width: 90px;
+  text-align: right;
+}
+
+input, textarea {
+  /* To make sure that all text field have the same font settings
+     By default, textarea are set with a monospace font */
+  font: 1em sans-serif;
+
+  /* To give the same size to all text field */
+  width: 300px;
+
+  -moz-box-sizing: border-box;
+       box-sizing: border-box;
+
+  /* To harmonize the look & feel of text field border */
+  border: 1px solid #999;
+}
+
+input:focus, textarea:focus {
+  /* To give a little highligh on active elements */
+  border-color: #000;
+}
+
+textarea {
+  /* To properly align multiline text field with their label */
+  vertical-align: top;
+
+  /* To give enough room to type some text */
+  height: 5em;
+
+  /* To allow users to resize any textarea vertically
+     It works only on Chrome, Firefox and Safari */
+  resize: vertical;
+}
+
+.button {
+  /* To position the buttons to the same position of the text fields */
+  padding-left: 90px; /* same size as the label elements */
+}
+
+button {
+  /* This extra magin represent the same space as the space between
+     the labels and their text fields */
+  margin-left: .5em;
+}
+ +

結果

+ +

{{ EmbedLiveSample('A_simple_form', '100%', '280') }}

+ +

 

diff --git a/files/ja/learn/forms/your_first_form/index.html b/files/ja/learn/forms/your_first_form/index.html new file mode 100644 index 0000000000..d3e646269f --- /dev/null +++ b/files/ja/learn/forms/your_first_form/index.html @@ -0,0 +1,313 @@ +--- +title: 初めてのフォーム +slug: Learn/Forms/Your_first_form +tags: + - Beginner + - CodingScripting + - Example + - Forms + - Guide + - HTML + - Learn + - Web + - ウェブ + - ガイド + - フォーム + - 初心者向け + - 学習 +translation_of: Learn/Forms/Your_first_form +--- +
+
{{LearnSidebar}}{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}
+
+ +

このシリーズの最初の記事では、簡単なフォームの設計、HTML フォームコントロールとその他の HTML 要素を使用した正しい実装、CSS によるとても簡単なスタイル付け、データをサーバーに送る方法を含めた、ウェブフォームを作成する本当に初歩的な経験をします。サブトピックは、モジュールの後で詳しく展開していきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーと、HTML を理解するを理解していること。
目的:ウェブフォームとは何か、何に使うのか、どうデザインするのか、サンプル事例に必要な基本の HTML 要素について熟知する。
+ +

ウェブフォームとは何か?

+ +

ウェブフォームとは、ユーザーと ウェブサイトやアプリケーションとの対話の要となるもののひとつです。フォームによって、ユーザーは ウェブサイトへデータを送ることができます。それらのデータはたいてい ウェブサーバーに送られて処理、保存されたり (モジュール後半のサーバーにデータを送るを見てください) 、クライアント側ですぐにインターフェイスを更新する(例えば、リストに他の項目を追加したり、UI の機能を表示/非表示にしたり)こともあります。

+ +

ウェブフォームは 1 つ以上のフォームコントロール(ウィジェットともいいます)と、フォーム全体を構成するのに役立つ追加要素 — よく HTML フォームと呼ばれます — とで作られます。それらのコントロールはテキストフィールド (単一行または複数行)、ドロップダウンボックス、ボタン、チェックボックスあるいはラジオボタンがあります。たいていは {{htmlelement("input")}} 要素を使って作成されますが、その他の要素もあります。

+ +

フォームコントロールは、特定フォームの値が入力されるのを強制する(フォーム検証)ためにもプログラミングされ、視力のある・盲目のユーザーいずれにとっても、用途を説明するラベルと対になります。

+ +

フォームを設計する

+ +

コードを書き始める前に、そこから離れてフォームについて考える時間をとるとよいでしょう。簡単なモデルを作ると、あなたがユーザーに入力を依頼したいデータの適切なセットを定義することの助けになります。ユーザー体験 (UX) の観点では、フォームが大規模になるとユーザーが不満を持って離れるリスクが高まると覚えておくことが重要です。簡単に、かつ集中するようにしてください。本当に必要なことだけをたずねてください。

+ +

フォームの設計は、サイトやアプリケーションを構築する際の大事なステップです。フォームのユーザー体験まで扱うと本記事の対象を超えてしまいますが、そこまで踏み込みたい場合は以下の記事をご覧ください。

+ + + +

本記事では、シンプルな連絡フォームを作成します。簡単に図を描いてみましょう。

+ +

The form to build, roughly sketch

+ +

このフォームには、3 つのテキストフィールドと 1 つのボタンがあります。要するに、ユーザーへ名前(Name)、メールアドレス(E-mail)、送信したいメッセージ(Message)をたずねます。ボタンを押すと、データをウェブサーバーに送信します。

+ +

HTML を書きましょう

+ +

これで、HTML に移ってフォームのコードを書く準備ができました。連絡フォームを作るために、以下の HTML 要素を使用します: {{HTMLElement("form")}}、{{HTMLElement("label")}}、{{HTMLElement("input")}}、{{HTMLElement("textarea")}}、{{HTMLElement("button")}} です。

+ +

前に進む前に、簡単な HTML テンプレートをローカルにコピーします — ここにフォームの HTML を入力します。

+ +

{{HTMLElement("form")}} 要素

+ +

すべてのフォームは、以下のように {{HTMLElement("form")}} 要素から始まります:

+ +
<form action="/my-handling-form-page" method="post">
+
+</form>
+ +

これは、フォームを正式に定義します。これは {{HTMLElement("div")}} 要素や {{HTMLElement("p")}} 要素と同様にコンテナ要素ですが、フォームの動作を設定するための固有の属性もサポートします。すべての属性は省略可能ですが、少なくとも action 属性と method属性は常に設定することがベストプラクティスであると考えられます。

+ + + +
+

: これらの属性がどのように働くかについて、詳しくはフォームデータの送信と取得で説明しています。

+
+ +

今は、上の {{htmlelement("form")}} 要素を HTML 本文に追加します。

+ +

{{HTMLElement("label")}}、{{HTMLElement("input")}} および {{HTMLElement("textarea")}} 要素でウィジェットを追加する

+ +

連絡フォームはとてもシンプルで 3 つのテキストフィールドを持っており、それぞれに 対応した {{HTMLelement("label")}} がついています。

+ + + +

HTML コードで、それらは以下のようになります:

+ +
<form action="/my-handling-form-page" method="post">
+ <ul>
+  <li>
+    <label for="name">Name:</label>
+    <input type="text" id="name" name="user_name">
+  </li>
+  <li>
+    <label for="mail">E-mail:</label>
+    <input type="email" id="mail" name="user_email">
+  </li>
+  <li>
+    <label for="msg">Message:</label>
+    <textarea id="msg" name="user_message"></textarea>
+  </li>
+ </ul>
+</form>
+ +

フォームのコードを上に見えるようなものに更新してください。

+ +

{{HTMLelement("li")}} 要素はコードを扱いやすく構造化するとともに、スタイル設定を容易にするため (後述) に置いています。すべての {{HTMLElement("label")}} 要素における、 for 属性の使い方に注目してください。これは、ラベルとフォームウィジェットを関連付けるための正式な方法です。この属性は、対応するウィジェットの id を参照します。

+ +

これには利点があります — フォームコントロールにラベルを関連付けて、ユーザーがマウス、トラックパッド、タッチデバイスでラベルをクリックすると対応するウィジェットがアクティブになり、スクリーンリーダーのユーザーに読み上げられるアクセシブルな名前が提供されます。この属性の利点をさらに知りたいのでしたら、こちらの記事ですべてを詳しく説明しています: HTML フォームの構築方法.

+ +

{{HTMLElement("input")}} 要素でもっとも重要な属性は、type 属性です。この属性は {{HTMLElement("input")}} 要素の見た目や動作を定義するため、とても重要です。これは要素を根本的に変えるものですから、注意してください。詳しく知りたい場合は、ネイティブフォームウィジェットの記事をご覧ください。

+ + + +

大事なことを言い忘れましたが、<input><textarea></textarea> の構文に注意してください。これは HTML の変わったことの 1 つです。<input> タグは空要素です。つまり、終了タグは不要です。一方 {{HTMLElement("textarea")}} は空の要素ではないので、適切な終了タグで閉じる必要があります。これは HTML フォームの特定の機能、つまりデフォルト値の定義方法に影響があります。{{HTMLElement("input")}} 要素のデフォルト値を定義するには、次のように value 属性を使う必要があります。

+ +
<input type="text" value="デフォルトではこの要素にはこの文章が挿入されます" />
+ +

また、{{HTMLElement("textarea")}} のデフォルト値を定義したい場合は、デフォルト値を {{HTMLElement("textarea")}} の開始タグと終了タグの間に書いてください。以下のとおりです:

+ +
<textarea>
+デフォルトではこの要素にはこの文章が挿入されます
+</textarea>
+ +

{{HTMLElement("button")}} を追加する

+ +

フォームはほぼできあがりました。あとは、ユーザーがフォームに記入したらデータを"送信"するためのボタンを追加します。これは、{{HTMLElement("button")}} 要素を使用して簡単にできます: 閉じタグの </ul> の直前に次の行を追加します:

+ +
<li class="button">
+  <button type="submit">メッセージを送信</button>
+</li>
+ +

{{htmlelement("button")}} 要素は type 属性を受け付けます。3 種類の値を受け付けて、これは submitresetbutton です。

+ + + +
+

メモ: {{HTMLElement("input")}} 要素で対応する type を指定して、ボタンを作成することもできます。例えば <input type="submit"> のように。{{HTMLElement("button")}} 要素との大きな違いは、{{HTMLElement("input")}} 要素ではラベルとしてプレーンテキストしか許容しませんが、{{HTMLElement("button")}} 要素ではすべての HTML コンテンツを使用して、もっと複雑でクリエイティブなボタンコンテンツを作成できます。

+
+ +

CSS でフォームを少し見栄えよくしましょう

+ +

フォームのHTMLコードの記述ができました。このフォームをお気に入りのブラウザーで見ると、見栄えがよくないでしょう。

+ +
+

メモ: あなたの HTML コードが正しくないと考える場合、完成例と比較してみてください — first-form.html にあります (ライブ版も見てください)。

+
+ +

フォームを素敵にスタイル付けるのはトリッキーです。それはこの記事でフォームスタイリングについて教える範囲を超えています。なので当面はまずまずの見ばえとなる CSS を追加するだけにしましょう。

+ +

最初に、ページの HTML の head 内に {{htmlelement("style")}} 要素を追加します。次のようになります:

+ +
<style>
+
+</style>
+ +

style タグの中に、次の CSS を追加します:

+ +
form {
+  /* フォームをページの中央に置く */
+  margin: 0 auto;
+  width: 500px;
+  /* フォームの範囲がわかるようにする */
+  padding: 1em;
+  border: 1px solid #CCC;
+  border-radius: 1em;
+}
+
+ul {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+
+form li + li {
+  margin-top: 1em;
+}
+
+label {
+  /* すべてのラベルを同じサイズにして、きちんと揃える */
+  display: inline-block;
+  width: 90px;
+  text-align: right;
+}
+
+input, textarea {
+  /* すべてのテキストフィールドのフォント設定を一致させる
+     デフォルトで、textarea は等幅フォントが設定されている */
+  font: 1em sans-serif;
+
+  /* すべてのテキストフィールドを同じサイズにする */
+  width: 300px;
+  box-sizing: border-box;
+
+  /* テキストフィールドのボーダーの外見を同一にする */
+  border: 1px solid #999;
+}
+
+input:focus,
+textarea:focus {
+  /* アクティブな要素を少し強調する */
+  border-color: #000;
+}
+
+textarea {
+  /* 複数行のテキストフィールドをラベルにきちんと揃える */
+  vertical-align: top;
+
+  /* テキスト入力に十分な領域を与える */
+  height: 5em;
+}
+
+.button {
+  /* ボタンを他のテキストフィールドと同じ場所に置く */
+  padding-left: 90px; /* label 要素と同じサイズ */
+}
+
+button {
+  /* このマージンは、ラベルとテキストフィールドの間のスペースと
+     おおよそ同じスペースを表す */
+  margin-left: .5em;
+}
+ +

保存して再読み込みすると、フォームがよりきれいになりました。

+ +
+

メモ: Github の first-form-styled.html にあります(ライブ版も見てください)。

+
+ +

データをウェブサーバーに送信する

+ +

最後の、またもっともややこしいであろう部分が、サーバー側でのフォームデータの扱いです。{{HTMLElement("form")}} 要素は  action 属性と method 属性により、どこへどのようにデータを送信するかを定義できます。

+ +

フォームコントロールに name をつけます。これらの名前はクライアント側とサーバー側の両側で重要です。ブラウザー側ではそれぞれのデータにどのような名前をつけるかを示すものであり、サーバー側では名前によってそれぞれのデータを扱うことができます。フォームデータは名前/値のペアとしてサーバーに送信されます。

+ +

データに名前をつけるために、各々のデータを集めるフォームウィジェットの name 属性を使用しなければなりません。ここでもフォームのコードで見てみましょう:

+ +
<form action="/my-handling-form-page" method="post">
+ <ul>
+  <li>
+    <label for="name">Name:</label>
+    <input type="text" id="name" name="user_name" />
+  </li>
+  <li>
+    <label for="mail">E-mail:</label>
+    <input type="email" id="mail" name="user_email" />
+  </li>
+  <li>
+    <label for="msg">Message:</label>
+    <textarea id="msg" name="user_message"></textarea>
+  </li>
+
+  ...
+
+ +

この例では、フォームはそれぞれ "user_name"、"user_email"、"user_message" と名付けられた 3 つのデータを送信します。これらのデータは URL "/my-handling-form-page" へ、HTTP POST メソッドで送信します。

+ +

サーバー側では URL "/my-handling-form-page" のスクリプトが、HTTP リクエストに埋め込まれた 3 つのキーおよび値のアイテムリストとしてデータを受け取ります。スクリプトがデータを処理する方法は、あなた次第です。各サーバーサイド言語 (PHP、Python、Ruby、Java、C# など) は、これらのデータを扱う仕組みを持っています。これは本ガイドで踏み込んでいく範囲を超えますが、詳しく知りたい場合はフォームデータの送信と取得の記事にサンプルを載せていますのでご覧ください。

+ +

まとめ

+ +

おめでとうございます! 初めてのウェブフォームが完成しました。こちらが最終結果のデモです。

+ +

{{ EmbedLiveSample('A_simple_form', '100%', '240', '', 'Learn/Forms/Your_first_form/Example') }}

+ +

これはほんの開始点です、しかし — さて、より深く見ていくときが来ました。ウェブフォームはここで見てきたものよりさらに強力であり、ガイドの他の記事で残りの部分を習得できます。

+ +

{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}

+ +

このモジュール

+ + + +

上級トピック

+ + diff --git a/files/ja/learn/front-end_web_developer/index.html b/files/ja/learn/front-end_web_developer/index.html new file mode 100644 index 0000000000..4b0649573a --- /dev/null +++ b/files/ja/learn/front-end_web_developer/index.html @@ -0,0 +1,193 @@ +--- +title: フロントエンド Web 開発者 +slug: Learn/Front-end_web_developer +translation_of: Learn/Front-end_web_developer +--- +

{{learnsidebar}}

+ +

フロントエンドWeb開発パスへようこそ!

+ +

このパスでは、フロントエンドWeb開発者になるために理解すべき全ての事を体系的なコースとして提供しています。 それぞれのセクションに取り組み、どんどん新しいスキルを習得(または、既存のスキルをより磨いて)して下さい。それぞれのセクションには、練習とテストがあり理解を確かめてから次のセクションに進んで下さい。

+ +

扱っているトピック

+ +

扱っているトピックとしては:

+ + + +

それそれのセクションに順番どおり取り組んでも良いですが、 内容が独立しているため、もしHTMLを既に知っているのであれば、一つ飛ばしてCSSのセクションに取り組んでも良いでしょう。

+ +

前提知識

+ +

このコースを始めるにあたり前提知識は必要ありません。必要なのはモダンなブラウザが動作するコンピュータ、インターネット接続 、学びたいという意欲だけです。

+ +

フロントエンドWeb開発が自分に適しているかわからなく、易しい説明が必要な場合はこの時間がかかる完全なコースを始める前に、Webサイト学習の最初のステップを読んでください。

+ +

学習につまずいたら

+ +

私たちは、フロントエンドWeb開発の学習が少しでもやさしくなるよう努力してきました。それでも、何か理解できないことあったり、コードが動かなかったりして、学習につまずくことがあるでしょう。

+ +

落ち着いて下さい。プロの開発者でも初心者でも、誰にだって学習でつまづくことはあります。学習とヘルプ(English) では情報を検索する際のヒントなど一連の有益な情報を提供しています。依然として学習につまずいているなら Discourse forum で気軽に質問して見て下さい。

+ +

さあ、始めましょう。幸運を!

+ +

学習パス

+ +

さあ、始めましょう

+ +

所要時間: 1–2 時間

+ +

前提知識

+ +

基本的なコンピュータリテラシー以外に必要ありあせん。

+ +

学習を進めるための条件

+ +

コースのこの部分には評価はありません。 ただし、スキップしないように注意してください。 コースの後半で演習を行う準備を整えておくことが重要です。

+ +

中心となるモジュール

+ + + +

HTML(意味付けと構造)

+ +

所要時間: 35–50 時間

+ +

前提知識

+ +

基本的なコンピュータリテラシーと基本的なWeb開発環境以外は何もありません。

+ +

学習を進めるための条件

+ +

それぞれのステップに関する知識をテストするように設計されています。 テストを完了すると、次のステップに進む準備ができているということです。

+ +

中心となるモジュール

+ + + +

CSS(スタイルとレイアウト)

+ +

所要時間: 90–120 時間

+ +

前提知識

+ +

CSSの学習を始める前にHTMLの基本的な知識を身につけておくことを推奨します。少なくともHTMLの紹介は読んでおきましょう。

+ +

学習を進めるための条件

+ +

それぞれのステップに関する知識をテストするように設計されています。 テストを完了すると、次のステップに進む準備ができているということです。

+ +

中心となるモジュール

+ + + +

補助教材

+ + + +

JavaScript(インタラクティビティ)

+ +

所要時間: 135–185 時間

+ +

前提知識

+ +

JavaScript を学習し始める前に基本的な HTML の知識を身に付けておくことをお勧めします。少なくとも HTML 入門 は最初に読んでおくべきでしょう。

+ +

学習を進めるための条件

+ +

それぞれのステップに関する知識をテストするように設計されています。 テストを完了すると、次のステップに進む準備ができているということです。

+ +

中心となるモジュール

+ + + +

Web フォーム(ユーザーのデータを扱う)

+ +

所要時間: 40–50 時間

+ +

前提知識

+ +

フォームを作るにはHTML、CSS、JavaScriptの知識が必要です。フォームの操作は複雑であるため、これは専用のトピックです。

+ +

学習を進めるための条件

+ +

それぞれのステップに関する知識をテストするように設計されています。 テストを完了すると、次のステップに進む準備ができているということです。

+ +

中心となるモジュール

+ + + +

すべての人のためにWebを作る

+ +

所要時間: 60–75 時間

+ +

前提知識

+ +

このセクションを実行する前に、HTML、CSS、およびJavaScriptを理解しておくことをお勧めします。 テクニックと最善慣行の多くは、複数のテクノロジーに触れています。

+ +

学習を進めるための条件

+ +

それぞれのステップに関する知識をテストするように設計されています。 テストを完了すると、次のステップに進む準備ができているということです。

+ +

中心となるモジュール

+ + + +

モダンなツール

+ +

所要時間: 55–90 時間

+ +

前提知識

+ +

説明したツールはこれらのテクノロジーの多くと連携して機能するため、このセクションを実行する前にHTML、CSS、およびJavaScriptを理解しておくことをお勧めします。

+ +

学習を進めるための条件

+ +

There are no specific assessment articles in this set of modules. The case study tutorials at the end of the second and third modules prepare you for grasping the essentials of modern tooling.

+ +

中心となるモジュール

+ + + +
+
+
diff --git a/files/ja/learn/getting_started_with_the_web/css_basics/index.html b/files/ja/learn/getting_started_with_the_web/css_basics/index.html new file mode 100644 index 0000000000..86fb5b8ee5 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/css_basics/index.html @@ -0,0 +1,295 @@ +--- +title: CSS の基本 +slug: Learn/Getting_started_with_the_web/CSS_basics +tags: + - CSS + - CodingScripting + - Styling + - Web + - 'l10n:priority' + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/CSS_basics +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web")}}
+ +
+

CSS (Cascading Style Sheets) は、ウェブページのスタイルを設定するコードです。「CSS の基本」では、始めるのに必要なものを紹介します。ここでは、テキストを黒または赤にするにはどうすればいいのか?そのような場所でコンテンツを画面に表示させるにはどうすればいいのか?背景画像と色を使って ウェブページをどのように飾るのか?というような疑問に答えていきます。

+
+ +

それでは CSS とは何でしょうか?

+ +

HTML のように、CSS は本当のプログラミング言語ではありません。またマークアップ言語でもありません。CSS はスタイルシート言語です。CSS は、HTML の要素を選択的にスタイルにするために使うものです。例えば、この CSS は段落のテキストを選択し、色を赤に設定しています。

+ +
p {
+  color: red;
+}
+ +

それでは試してみましょう: これらの 3 行の CSS をテキストエディタの新しいファイルに貼り付け、ファイルを style.css として styles ディレクトリに保存します。

+ +

しかし、まだ CSS を HTML 文書に適用する必要があります。そうしないと CSS のスタイリングはブラウザの HTML 文書の表示方法に影響しません。(私たちのプロジェクトに従っていない場合、ファイルを扱うHTML の基本を読み、まず何をする必要があるのかを見てください)

+ +
    +
  1. index.html ファイルを開き、head ({{HTMLElement("head")}} タグと </head> タグの間) に以下の行を貼り付けます + +
    <link href="styles/style.css" rel="stylesheet" type="text/css">
    +
  2. +
  3. index.html を保存し、ブラウザで読み込みます。このように表示されるでしょう :
  4. +
+ +

A mozilla logo and some paragraphs. The paragraph text has been styled red by our css.段落テキスト(<p></p>で囲んだ文字)が赤色になりましたか?おめでとうございます!今はじめて CSS を書き、成功しました!

+ +

CSS ルールセットの構造

+ +

上記の CSS をもう少し詳しく見てみましょう:

+ +

CSS p declaration color red

+ +

全体の構造はルールセットと呼びます (しかし、しばしば "ルール" として略されます)。個々のパーツの名前にも注意してください :

+ +
+
{{原語併記("セレクタ", "selector")}}
+
ルールセットの先頭にある HTML 要素名。これはスタイルを設定する要素 (この場合は p 要素) を選択します。別の要素をスタイルするには、Selector を変更します。
+
{{原語併記("宣言", "declaration")}}
+
color: red; のような単一のルールで、要素のプロパティのうちどの要素をスタイルするかを指定します。
+
{{原語併記("プロパティ", "property")}}
+
指定された HTML 要素のスタイルを設定する方法 (この場合 color は {{htmlelement("p")}} 要素のプロパティです)。CSS ではルール内でどのプロパティを適用するかを選択します。
+
{{原語併記("プロパティ値", "property value")}}
+
プロパティの右側にはコロンの後にプロパティ値があり、与えられたプロパティの多くの外観から 1 つを選択します (赤以外にも多くの色の値があります)。
+
+ +

構文の他の重要な部分に注意してください:

+ + + +

したがって、一度に複数のプロパティ値を変更するには、セミコロンで区切って次のように記述するだけです:

+ +
p {
+  color: red;
+  width: 500px;
+  border: 1px solid black;
+}
+ +

複数の要素を選択する

+ +

複数の要素の種類を選択することができ、すべての要素に単一のルールセットを適用することもできます。カンマで区切られた複数のセレクタを含めます。例えば:

+ +
p,li,h1 {
+  color: red;
+}
+ +

さまざまな種類のセレクタ

+ +

多くのさまざまな種類のセレクタがあります。上の項目では、特定のHTMLドキュメント内の特定のタイプのすべての要素を選択する要素セレクタだけを取り上げました。しかしそれ以上に細かい選択をすることができます。一般的なタイプのセレクタを次に示します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
セレクタ名何を選択するか
要素セレクタ (時々タグまたは型セレクタと呼ばれます)指定された型のすべての HTML 要素p
+ <p> を選択
ID セレクタページ上の指定された ID を持つ要素。 特定のHTMLページでは、1つのIDにつき1つの要素(そしてもちろん1つの要素につき1つのID)しか許されません。#my-id
+ <p id="my-id"> または <a id="my-id"> を選択
クラスセレクタ指定されたクラスを持つページの要素 (複数のクラスインスタンスがページに表示されます).my-class
+ <p class="my-class"> 及び <a class="my-class"> を選択
属性セレクタ指定された属性を持つページ上の要素img[src]
+ <img src="myimage.png"> を選択するが、<img> は選択しない
擬似クラスセレクタ指定された要素が指定された状態にあるとき。例えば、マウスポインターが上に乗っている (ホバー) 状態。a:hover
+ <a> を選択するが、マウスポインターがリンク上にあるときのみ。
+ +

セレクタの種類は多く、セレクタガイドにより詳しい一覧があります。

+ +

フォントとテキスト

+ +

CSS の基本をいくつか勉強しましたので、style.css ファイルにいくつかのルールと情報を追加して、この例を見栄え良くしましょう。最初に、フォントとテキストの見ばえを少し良くしてみましょう。

+ +
    +
  1. まず最初に、どこかの安全に保存した Google フォントの出力を見つけてください。{{htmlelement("link")}} 要素を index.html の上部 (<head> タグと </head> タグの間) のどこかに追加します。これは次のようになります: + +
    <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
    + +

    このコードは、ウェブページとともにOpen Sansフォントファミリをダウンロードするスタイルシートにページをリンクし、独自のスタイルシートを使用してHTML要素に設定することを可能にします。

    +
  2. +
  3. 次に style.css ファイルにある既存のルールを削除します。良いテストでしたが、赤いテキストは実のところあまりよくありません。
  4. +
  5. 代わりに次の行を追加し、プレースホルダー行を Google フォントから取得した実際の font-family 行に置き換えます。(この font-family は、テキストに使用するフォントを意味します)。このルールは最初にページ全体のグローバルベースフォントとフォントサイズを設定します (<html> はページ全体の親要素です。その中のすべての要素は同じ font-sizefont-family を継承します): +
    html {
    +  font-size: 10px; /* px means 'pixels': the base font size is now 10 pixels high  */
    +  font-family: 'Open Sans', sans-serif; /* this should be the rest of the output you got from Google fonts */
    +}
    + +
    +

    : 「px」の意味を説明するコメントを追加しました。/**/ の間にある CSS ドキュメント内のものは CSS コメントです。ブラウザはコードをレンダリングするときにこれを無視します。これはあなたが実施していることについての役立つメモを書く場所です。

    +
    +
  6. +
  7. HTML ボディ ({{htmlelement("h1")}}、{{htmlelement("li")}}、{{htmlelement("p")}}) 内のテキストを含む要素のフォントサイズを設定します)。また、読みやすくするために見出しのテキストを中央に置き、本文の内容に行の高さと文字の間隔を設定します: +
    h1 {
    +  font-size: 60px;
    +  text-align: center;
    +}
    +
    +p, li {
    +  font-size: 16px;
    +  line-height: 2;
    +  letter-spacing: 1px;
    +}
    +
  8. +
+ +

これらの px 値はあなたが望むようにデザインを得るために好きなものに調整できますが、一般的にデザインは次のようになります:

+ +

a mozilla logo and some paragraphs. a sans-serif font has been set, the font sizes, line height and letter spacing are adjusted, and the main page heading has been centered

+ +

ボックス、ボックス、ボックスについてのすべてのこと

+ +

CSS を書いていて気づくことの 1 つは、ボックスのサイズ・色・位置などを設定することです。ページの HTML 要素のほとんどはお互いの上にあるボックスと考えることができます。

+ +

a big stack of boxes or crates sat on top of one another

+ +

当然のことながら、CSS レイアウトは主にボックスモデルに基づいています。ページ上のスペースを占める各ブロックは、次のようなプロパティを持ちます:

+ + + +

three boxes sat inside one another. From outside to in they are labelled margin, border and padding

+ +

このセクションでは次のものを使用します :

+ + + +

では、ページに CSS を追加しましょう!これらの新しいルールをページの最後に追加しておき、値の変更を試すのを恐れることなく、どのように変化するかを確認してください。

+ +

ページの色を変更する

+ +
html {
+  background-color: #00539F;
+}
+ +

このルールはページ全体の背景色に設定を行います。上記のカラーコードを、サイトを計画する際に選択した色に変更します。

+ +

ボディのスタイリング

+ +
body {
+  width: 600px;
+  margin: 0 auto;
+  background-color: #FF9500;
+  padding: 0 20px 20px 20px;
+  border: 5px solid black;
+}
+ +

次は {{htmlelement("body")}}  要素です。ここにはいくつかの宣言がありますので、それらをひとつひとつ見て行きましょう:

+ + + +

メインページタイトルの配置とスタイリング

+ +
h1 {
+  margin: 0;
+  padding: 20px 0;
+  color: #00539F;
+  text-shadow: 3px 3px 1px black;
+}
+ +

body の上部にひどい隙間があることに気づいたかもしれません。これは CSS をまったく適用していなくても、ブラウザが {{htmlelement("h1")}} 要素 (他の中でも) にデフォルトのスタイルを適用するためです。それは悪い考えのように聞こえるかもしれませんが、私たちは未構築のウェブページでも基本的な読みやすさを求めています。ギャップをなくすには、margin: 0; を設定してデフォルトのスタイルを上書きします。

+ +

次に見出しの上下のパディングを 20 ピクセルに設定し、見出しテキストを html の背景色と同じ色にしました。

+ +

私たちがここで使ってきた興味深いプロパティの 1 つは、要素のテキストコンテンツにテキストシャドウを適用する text-shadow です。その 4 つの値は次のとおりです。

+ + + +

繰り返しますが、さまざまな値を試してみてください。

+ +

画像のセンタリング

+ +
img {
+  display: block;
+  margin: 0 auto;
+}
+ +

最後に画像をよりよく見えるように中央に配置します。以前は body のために実施したことと同じようにもう一度 margin: 0 auto トリックを使うことができましたが、何か別のことをする必要もあります。body 要素はブロックレベルです。つまり、ページ上のスペースを占有し、マージンや他のスペーシング値を適用することができます。一方、イメージはインライン要素でありできないことを意味します。画像にマージンを適用するには、display: block; を使用して画像のブロックレベルの動作を指定する必要があります。

+ +
+

: 上記の手順では、本体に設定されている幅 (600ピクセル) よりも小さい画像を使用していることを前提としています。画像が大きい場合、それは本文をオーバーフローし、ページの残りの部分にはみ出します。これを修正するには、1) グラフィックスエディタを使用してイメージの幅を縮小するか、2) <img> 要素の {{cssxref("width")}} プロパティを小さな値、例えば 400 px; に設定することで、 CSS を使用してイメージのサイズを変更します。

+
+ +
+

: あなたがまだ display: block; とブロックレベル/インラインの区別を理解していなくても、心配しないでください。CSS をもっと深く勉強することが出来ます。使用可能なさまざまな表示値の詳細については、display のリファレンスページを参照してください。

+
+ +

まとめ

+ +

この記事のすべての手順に従っている場合は、次のようなページが表示されます (このリンクから我々が作成したバージョンを見ることもできます)。

+ +

a mozilla logo, centered, and a header and paragraphs. It now looks nicely styled, with a blue background for the whole page and orange background for the centered main content strip.

+ +

もしわからなくなった場合、Github の完成したサンプルコードと作業内容を常に比較することができます。

+ +

ここでは、CSS の表面に少し触れただけです。詳細については、CSS の学習トピックをご覧ください。

+ +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/dealing_with_files/index.html b/files/ja/learn/getting_started_with_the_web/dealing_with_files/index.html new file mode 100644 index 0000000000..cdc3e3a336 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/dealing_with_files/index.html @@ -0,0 +1,117 @@ +--- +title: ファイルの扱い +slug: Learn/Getting_started_with_the_web/Dealing_with_files +tags: + - Beginner + - CodingScripting + - Files + - HTML + - 'l10n:priority' + - theory + - website + - ガイド +translation_of: Learn/Getting_started_with_the_web/Dealing_with_files +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web")}}
+ +
+

Web サイトは、テキストコンテンツ、コード、スタイルシート、メディアコンテンツなど、多くのファイルで構成されています。Web サイトを構築するときは、これらのファイルをローカルコンピュータ上の合理的な構造に組み立て、互いに呼び出すことができるようにして、最終的にサーバにアップロードする前に、すべてのコンテンツを正しいものにする必要があります。ファイルの扱いでは、Web サイトに合理的なファイル構造を設定できるように、注意すべきいくつかの問題について説明します。

+
+ +

コンピュータ上で Web サイトがあるべき場所

+ +

自分のコンピュータ上の Web サイトでローカルに作業している時、関連するすべてのファイルを、サーバ上に公開された Web サイトのファイル構造のミラーである単一のフォルダに保持する必要があります。このフォルダは好きな場所に置くことができますが、簡単に見つけることができる場所、たとえばデスクトップ上、ホームフォルダの中、またはハードディスクのルートなどに置いてください。

+ +
    +
  1. Web サイトプロジェクトを保存する場所を選択してください。ここでは web-projects (またはそれに類するもの) という新しいフォルダを作成します。これは Web サイトのプロジェクト全てを保持するところです。
  2. +
  3. この最初のフォルダの中に、最初の Web サイトを格納する別のフォルダを作成します。それを test-site (またはもっと想像力のあるもの) と呼びましょう。
  4. +
+ +

大文字と空白の除外

+ +

この記事を通して、フォルダやファイルに空白のない全て小文字で名前を付けるよう求めていることに気が付くでしょう。その理由は次の通りです。

+ +
    +
  1. 多くのコンピュータ、特に Web サーバでは、大文字と小文字が区別されます。例えば、あなたの Web サイトの test-site/MyImage.jpg に画像を置いて、別のファイルから画像を test-site/myimage.jpg として呼び出せば、それは動作しないかもしれません。
  2. +
  3. ブラウザ、Web サーバ、プログラミング言語は、空白の扱いが一貫していません。例えば、ファイル名に空白を使用すると、システムによってはそのファイル名を 2 つのファイル名として扱うことがあります。サーバによっては、ファイル名の空白を "%20" (URI の空白の文字コード) に置き換えるので、リンクが壊れてしまう結果になります。my_file.html のように単語をアンダースコアで区切るよりは、my-file.html のようにハイフンで区切る方がよいでしょう。
  4. +
+ +

簡単に言えば、ファイル名にはハイフンを使うべきです。Google の検索エンジンはハイフンを単語の区切りとして扱いますが、アンダースコアはそうしません。このような理由から、少なくとも自分で判断できるようになるまでは、フォルダやファイルの名前を空白のない小文字にして、ダッシュで区切った方がいいでしょう。そうすれば、転んで道路に倒れることが少なくなるでしょう。

+ +

Web サイトはどのような構成にするべきか

+ +

次に、テストサイトがどのような構造を持つべきかを見てみましょう。私たちが作成する Web サイトプロジェクトで最も一般的なのは、index の HTML ファイルと、画像、スタイルシート、スクリプトファイルを入れるフォルダです。作成してみましょう。

+ +
    +
  1. index.html: このファイルには、一般的にあなたのホームページの内容、つまりあなたが最初にあなたのサイトに行ったときに見るテキストと画像が含まれています。テキストエディターを使用して、index.html という名前の新しいファイルを作成し、test-site フォルダ内に保存します。
  2. +
  3. images フォルダ: このフォルダにはサイトで使用するすべての画像を入れます。test-site フォルダの中に images という名前のフォルダを作成します。
  4. +
  5. styles フォルダ: このフォルダには、コンテンツのスタイルを設定するための CSS コード(例えばテキストと背景色の設定など)を入れます。test-site のフォルダの中に styles というフォルダを作成します。
  6. +
  7. scripts フォルダ : このフォルダには、サイトにインタラクティブ機能を追加するために使用されるすべての JavaScript コード(クリックされたときにデータを読み込むボタンなど)が含まれます。test-site のフォルダの中に scripts というフォルダを作成します。
  8. +
+ +
+

: Windows では、既定で有効になっている既知のファイルの種類の拡張子を表示しないというオプションがあるため、ファイル名の表示に問題が発生することがあります。一般に、Windows エクスプローラーで [フォルダオプション...] オプションを選択し、[登録されている拡張子は表示しない] チェックボックスをオフにし、[OK] をクリックすることで、これをオフにすることができます。お使いの Windows のバージョンに関する詳細な情報については、Web で検索してください。

+
+ +

ファイルパス

+ +

ファイルをお互いに呼び出すためには、ファイルパスを提供する必要があります。基本的には、あるファイルが別のファイルの場所を知っています。これを実証するために、index.html ファイルに短い HTML を挿入し、Web サイトをどのような外見にするかの記事で選択した画像を表示させます。あるいは、コンピュータ上またはウェブ上の既存の画像を自由に選択して、以下の手順で使用することができます。

+ +
    +
  1. 以前に選択した画像を images フォルダにコピーします。
  2. +
  3. index.html ファイルを開き、次のコードをファイルに挿入します。それが今のところ何を意味するのか気にしないでください。シリーズの後半で構造を詳しく見ていきます。 +
    <!DOCTYPE html>
    +<html>
    +  <head>
    +    <meta charset="utf-8">
    +    <title>My test page</title>
    +  </head>
    +  <body>
    +    <img src="" alt="My test image">
    +  </body>
    +</html> 
    +
  4. +
  5. <img src="" alt="My test image"> という行は、ページに画像を挿入する HTML コードです。画像がどこにあるのかを HTML に伝える必要があります。画像は images ディレクトリ内にあり、index.html と同じディレクトリにあります。ファイル構造の中で index.html からその画像に移動するのに必要なファイルパスは images/your-image-filename です。例えば、私たちの画像は firefox-icon.png と呼ばれ、ファイルパスは images/firefox-icon.png です。
  6. +
  7. src="" コードの二重引用符の間の HTML コードにファイルパスを挿入します。
  8. +
  9. HTML ファイルを保存し、Web ブラウザに読み込みます (ファイルをダブルクリックします)。新しい Web ページに画像が表示されます。
  10. +
+ +

地球の周りに燃える狐を表した firefox のロゴのみを表示した基本的なウェブサイトのスクリーンショット。

+ +

ファイルパスの一般的なルールは次の通りです。

+ + + +

今のところ、これが知る必要があるすべてです。

+ +
+

: Windows のファイルシステムでは、スラッシュ (/) ではなくバックスラッシュまたは¥記号を使用します。(例 : C:\windows)。これは HTML では使用できません。Windows で Web サイトを開発している場合でも、コード内ではスラッシュを使用する必要があります。

+
+ +

他にするべきこと

+ +

今のところは以上です。フォルダ構造は次のようになります。

+ +

macOS X の finder におけるファイル構造。images フォルダーに画像が入っており、scripts と styles フォルダーは空で、あと index.html がある

+ +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/how_the_web_works/index.html b/files/ja/learn/getting_started_with_the_web/how_the_web_works/index.html new file mode 100644 index 0000000000..8aaecfed16 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/how_the_web_works/index.html @@ -0,0 +1,110 @@ +--- +title: Web のしくみ +slug: Learn/Getting_started_with_the_web/How_the_Web_works +tags: + - DNS + - HTTP + - IP + - Infrastructure + - TCP + - 'l10n:priority' + - クライアント + - サーバー + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/How_the_Web_works +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}
+ +
+

Web のしくみでは、あなたがコンピュータや携帯電話の Web ブラウザで Web ページを見るときに起こることを簡単に説明します。

+
+ +

この理論は、Web のコードを書く上ですぐにでも必要というわけではありませんが、背景で何が起きているのかを理解しておくと、いずれ役に立つでしょう。

+ +

クライアントとサーバ

+ +

Web に接続されたコンピュータは{{原語併記("クライアント", "client")}}{{原語併記("サーバ", "server")}}と呼ばれます。これらがどのように相互作用するかを概略図で表すと次のようになります。

+ +

Two circles representing client and server. An arrow labelled request is going from client to server, and an arrow labelled responses is going from server to client

+ + + +

道具箱の他の部分

+ +

もちろん上で説明したクライアントとサーバだけでなく、これら二つ以外にも、他に多くのものが関わっています。以下では、それについて説明します。

+ +

いま、Web が道路であると想像してみましょう。道路の片端にクライアントがあり、そこは例えれば、あなたの自宅のようなものです。反対の端はサーバで、そこは例えれば、あなたが何かを買うお店のようなものです。

+ +

+ +

クライアントとサーバに加えて、以下のものにも触れなければなりません。

+ + + +

ならば何が起こるのか

+ +

ブラウザに Web アドレスを打ち込んだ時に何が起こっているかというと (お店に歩いていく例えでは),

+ +
    +
  1. ブラウザは DNS サーバにアクセスし、Web サイトのあるサーバの実際のアドレスを探します (お店の住所を見つけます)
  2. +
  3. ブラウザはサーバに HTTP リクエストメッセージを送信して、Web サイトのコピーをクライアントに送るよう求めます (お店に行ってものを注文します)。このメッセージ、およびクライアントとサーバ間でやりとりされるその他すべてのデータは、TCP/IP を使用してインターネット経由で送信されます
  4. +
  5. サーバがクライアントのリクエストを承認すると、サーバはクライアントに 「200 OK」 というメッセージを送ります。これは「もちろんその Web サイトを見ることができます。どうぞ!」という意味です。そして Web サイトのファイルを、データパケットと呼ばれる一連の小さな{{原語併記("塊", "chunk")}}としてブラウザに送信し始めます (お店は商品を渡し、あなたは自宅に持って帰ります)
  6. +
  7. ブラウザは小さな塊を完全な Web サイトに組み立て、表示します (玄関にものが到着しました — 新しいピカピカのものです、すばらしい!)
  8. +
+ +

DNS の説明

+ +

実際の Web アドレスは、お気に入りの Web サイトを見つけるためにアドレスバーに入力するような、すばらしい、覚えやすい文字列ではありません。実際の Web アドレスは 63.245.217.105 のような特殊な数字です。

+ +

これは、{{Glossary("IP Address", "IP アドレス")}} と呼ばれ、Web 上の一意の場所を表します。しかし、覚えにくいと思いませんか?だから、ドメインネームサーバが発明されたのです。これらは特別なサーバで、ブラウザに入力した Web アドレス ("mozilla.org" など) と Web サイトの実際の (IP) アドレスを対応させます。

+ +

Web サイトには、IP アドレスを使用して直接アクセスできます。IP Checker のようなツールにドメインを打ち込むことで、Web サイトの IP アドレスを見つけることができます。

+ +

パケットの説明

+ +

先ほど、データがサーバからクライアントに送信される形式を説明するために、「パケット」という用語を使用しました。ここではどういう意味なのでしょうか。基本的に、Web 上でデータが送信されると、何千もの小さな塊として送信されるため、たくさんの異なるユーザーが同じ Web サイトを同時にダウンロードできます。Web サイトが単一の大きな塊として送信されるとすると、一度に1人のユーザーしかダウンロードできなくなるため、Web がとても非効率的になり、使うのが楽しくなくなるでしょう。

+ +

関連情報

+ + + +

クレジット表示

+ +

道路の写真: Street composing, by Kevin D.

+ +

{{PreviousMenu("Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/html_basics/index.html b/files/ja/learn/getting_started_with_the_web/html_basics/index.html new file mode 100644 index 0000000000..aeaba9696e --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/html_basics/index.html @@ -0,0 +1,239 @@ +--- +title: HTML の基本 +slug: Learn/Getting_started_with_the_web/HTML_basics +tags: + - CodingScripting + - HTML + - Web + - 'l10n:priority' + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/HTML_basics +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web/CSS_basics", "Learn/Getting_started_with_the_web")}}
+ +
+

HTML (Hypertext Markup Language、ハイパーテキスト・マークアップ・ランゲージ)は、 Web サイトのコンテンツに構造を指定するために使うコードです。具体的に言うと、構造というのは、段落や箇条書きのリスト、画像、テーブルなどのようなものです。タイトルが示すように、この記事では、HTML とその機能の基本的な理解ができるように説明します。

+
+ +

そもそも HTML とは

+ +

HTML はプログラミング言語ではありません。マークアップ言語と言って、コンテンツの構造を決めるものです。 HTML は {{Glossary("element", "要素")}} の集まりでできています。要素とは様々なコンテンツがどのように見えるか、またどのように動くかを表現するためにタグで囲まれたまとまりです。{{Glossary("tag", "タグ")}} は言葉や画像を表示したり、他のページに移動するハイパーリンクを作ったり、文字を斜体にしたり、大きくしたり小さくしたり、色々なことが出来ます。例えば、次の文を見てください。

+ +
My cat is very grumpy
+ +

上の文を単体で表示したいなら、段落タグ ({{htmlelement("p")}}) で文を囲うことでこれが段落であると指定することができます。

+ +
<p>My cat is very grumpy</p>
+ +

HTML 要素の中身

+ +

この段落要素についてもうちょっと詳しく見ていきましょう。

+ +

+ +

要素は主に以下のようなもので構成されています:

+ +
    +
  1. {{原語併記("開始タグ", "opening tag")}}: これは、要素の名前(今回は p)を山括弧で囲ったものです。どこから要素が始まっているのかやどこで効果が始まるのかを表しています。今回の場合どこから段落が始まるかを表しています。
  2. +
  3. {{原語併記("終了タグ", "closing tag")}}: これは、要素名の前にスラッシュが入っていることを除いて開始タグと同じです。どこで要素が終わっているかを表しています。今回の場合どこで段落が終わるかを表しています。終了タグの書き忘れは、初心者のよくある間違いで、正しく表示されません。
  4. +
  5. {{原語併記("コンテンツ", "content")}}: 要素の内容です。今回の場合はただの文字です。
  6. +
  7. {{原語併記("要素", "element")}}: 開始タグ、終了タグ、コンテンツで要素を構成します。
  8. +
+ +

要素は{{原語併記("属性", "Attribute")}}を持つことが出来ます。このような感じです:

+ +

+ +

属性とは要素に対し実際には表示されない追加情報を含んだものです。ここでは class が属性の名前editor-note が属性のです。 class 属性を使って要素に識別するための名前を与えていて、後でこの要素を指定してスタイルをつけたり様々なことができるようになります。

+ +

属性は次のような形式です。

+ +
    +
  1. 要素名 (すでにいくつか属性がある場合はひとつ前の属性) との間の空白
  2. +
  3. 属性名とそれに続く等号
  4. +
  5. 引用符で囲まれた属性の値
  6. +
+ +
+

メモ: ASCII の空白 (または " ' ` = < > 文字) を含まない単純な属性値は引用符を付けないままにすることができますが、コードの一貫性と理解を容易にするため、すべての属性値を引用することをお勧めします。

+
+ +

要素のネスト

+ +

要素の中に他の要素を入れることも出来ます。これをネスト(または入れ子)と言います。もしあなたの猫が「とっても」機嫌が悪いことを表したいとしたら、「とっても」という単語を {{htmlelement("strong")}} 要素に入れて単語の強調を表すことが出来ます。

+ +
<p>私のネコは<strong>とっても</strong>機嫌が悪い。</p>
+ +

しかしながら要素のネストは正しく行われなければなりません。上記の例ではまず始めに {{htmlelement("p")}} 要素が開始され、その次に {{htmlelement("strong")}} 要素が開始されています。そうしたならば、必ず {{htmlelement("strong")}} 要素、 {{htmlelement("p")}} 要素の順で終了しなければなりません。次の例は間違いです。

+ +
<p>私の猫は<strong>とっても機嫌が悪い。</p></strong>
+ +

要素は確実に他の要素の中もしくは外で開始し、終了する必要があります。上記の例のように要素が重複してしまうと、 Web ブラウザはあなたがしようとしていたことを推測してもっともよいと思われる解釈をするため、予期せぬ結果になることがあります。そうならないよう気を付けましょう!

+ +

空要素

+ +

コンテンツを持たない要素もあります。そのような要素を{{原語併記("空要素", "empty elements")}} と呼びます。 {{htmlelement("img")}} 要素を例に見ていきましょう。

+ +
<img src="images/firefox-icon.png" alt="My test image">
+ +

この要素は 2 つの属性を持っていますが終了タグ </img> はありませんし、内部にコンテンツもありません。これは image 要素はその機能を果たすためにコンテンツを囲うものではないからです。 image 要素の目的は画像を HTML ページの表示させたいところに埋め込むことです。

+ +

HTML 文書の構造

+ +

ここまでは HTML 要素についてみてきました。しかし要素単体ではあまり役には立ちません。ここからはどのようにしてそれぞれの要素を組み合わせ、 HTML ページ全体を作っていくのかを勉強していきましょう。ファイルを扱うで出てきた index.html に書いてあるコードをもう一度見てみましょう。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My test page</title>
+  </head>
+  <body>
+    <img src="images/firefox-icon.png" alt="My test image">
+  </body>
+</html>
+ +

この中にあるものは以下の通りです。

+ + + +

画像

+ +

もう一度 {{htmlelement("img")}} 要素について見ていくことにしましょう。

+ +
<img src="images/firefox-icon.png" alt="My test image">
+ +

前に説明したように、これは書いたところに画像を埋め込みます。画像ファイルのパスを値に持つ src (source) 属性を指定する事によってその画像を表示できます。

+ +

また、 alt (alternative; 代替) 属性も指定しています。これは以下の様な理由で画像を見られない人に向けて文字で説明をするものです。

+ +
    +
  1. 目が不自由な人。著しく目の不自由な人はよくスクリーンリーダーと呼ばれるツールを使っていて、それは画像の alt 属性の内容を読み上げます。
  2. +
  3. 何らかの理由で画像の表示に失敗した場合。例えば、 src 属性に指定したパスが間違っていたときなどです。ページを保存したり再読み込みしたりするとこのような本来画像があるべき場所に下記のような何かが表示されるでしょう。
  4. +
+ +

+ +

alt 属性の内容は「説明する文」であるということが重要です。代替文は画像が伝えたいことをうまく言い表しているべきです。上の「My test image」はあまり良い例ではありません。 Firefox のロゴの代替文字列として適切なのは、「地球を囲む燃えるような狐の Firefox ロゴ」というようなものです。

+ +

あなたが用意した画像に良い代替文字列を付けてみましょう。

+ +
+

注記: アクセシビリティについて詳しくは MDN のアクセシビリティのページを参照してください。

+
+ +

テキストのマークアップ

+ +

この章では、文字列をマークアップするために使用する基本的な HTML 要素をいくつか見ていきます。

+ +

見出し

+ +

見出し要素は文書中の見出し、小見出しを指定することができるものです。通常の書籍でも主題、章題、副題があります。 HTML でも同じことが出来ます。 HTML では {{htmlelement("h1")}} から {{htmlelement("h6")}} の 6段階の見出しが用意されていますが、よく使うのはせいぜい 3 つから 4 つほどでしょう。

+ +
<h1>My main title</h1>
+<h2>My top level heading</h2>
+<h3>My subheading</h3>
+<h4>My sub-subheading</h4>
+ +

それでは、あなたの HTML の {{htmlelement("img")}} 要素の上に適切なタイトルを付けてみましょう。

+ +
+

メモ: 見出しレベル1には暗黙のスタイルがあることがわかります。テキストを大きくしたり太字にしたりするために見出し要素を使用しないでください。これらはアクセシビリティSEO などのその他の理由で使用されます。レベルをスキップせずに、ページ上に意味のある一連の見出しを作成してください。

+
+ +

段落

+ +

先に説明したように、 {{htmlelement("p")}} 要素は段落を示しています。通常の文章を書く時にはこの要素を頻繁に使うことになるでしょう。

+ +
<p>This is a single paragraph</p>
+ +

試しに {{htmlelement("img")}} 要素のすぐ下にいくつか段落を作り、文章を書いてみましょう。(文章は Web サイトはどんな見た目にしたいですか?から持ってきても良いです。)

+ +

リスト

+ +

多くの Web のコンテンツはリストで出来ており、 HTML にはリストを表すための特別な要素が用意されています。リストは最低 2 つの要素を組み合わせて生成します。主要なリスト形式として番号付きリストと番号なしリストがあります。

+ +
    +
  1. 番号なしリストは、お買い物リストのようにアイテムの順番が特に関係ない時に使います。番号なしリストは {{htmlelement("ul")}} 要素で囲みます。
  2. +
  3. 番号付きリストは料理のレシピのようにアイテムの順番が関係ある時に使います。番号付きリストは {{htmlelement("ol")}} 要素で囲みます。
  4. +
+ +

リストの中に入るそれぞれのアイテムは {{htmlelement("li")}} (list item) 要素の中に書きます。

+ +

例えば、次の段落の一部をリストにしたい場合、

+ +
<p>At Mozilla, we’re a global community of technologists, thinkers, and builders working together ... </p>
+ +

以下のようにマークアップします。

+ +
<p>At Mozilla, we’re a global community of</p>
+
+<ul>
+  <li>technologists</li>
+  <li>thinkers</li>
+  <li>builders</li>
+</ul>
+
+<p>working together ... </p>
+ +

あなたのページに番号付きリストと番号なしリストを追加してみましょう。

+ + + +

リンクはとても重要です ―― これが Web をひとつの Web にします。リンクを追加するには、シンプルな要素 {{htmlelement("a")}} を使えばよいです。 a は "anchor" を省略したものです。段落中の文字をリンクにするには次の手順で行います。

+ +
    +
  1. リンクにしたい文字を選びます。今回は "Mozila Manifesto" を選びました。
  2. +
  3. 選んだ文字を {{htmlelement("a")}} 要素で囲みます。 +
    <a>Mozilla Manifesto</a>
    +
  4. +
  5. このように {{htmlelement("a")}} 要素に href 属性を追加します。 +
    <a href="">Mozilla Manifesto</a>
    +
  6. +
  7. このリンクがリンクしたい Web アドレスをこの属性の値に書き込みます。 +
    <a href="https://www.mozilla.org/en-US/about/manifesto/">Mozilla Manifesto</a>
    +
  8. +
+ +

アドレスの先頭にある https://http:// の部分 (プロトコルと言います) を書き忘れると、予期せぬ結果となってしまうかもしれません。リンクを作ったら、ちゃんとそれが遷移したいところに行ってくれるかを確かめましょう。

+ +
+

href は属性名として変に思うかもしれません。覚えにくかったら、 hrefhypertext reference を表しているということを覚えておきましょう。

+
+ +

もしまだやってないのなら、ページにリンクを追加してみましょう。

+ +

まとめ

+ +

ここまでの説明に沿ってやってきたのなら、下のようなページが出来上がっているはずです (ここでも見られます)。
+
+ A web page screenshot showing a firefox logo, a heading saying mozilla is cool, and two paragraphs of filler text

+ +

もし途中で行き詰まってしまったなら、 GitHub にある完成版のコード例と見比べてみてください。

+ +

この記事では HTML の表面的な部分だけを勉強しました。もっと知りたい場合は HTML を学ぶを読んでみてくだい。

+ +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web/CSS_basics", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/index.html b/files/ja/learn/getting_started_with_the_web/index.html new file mode 100644 index 0000000000..6471ecabd2 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/index.html @@ -0,0 +1,65 @@ +--- +title: Web 入門 +slug: Learn/Getting_started_with_the_web +tags: + - Beginner + - CSS + - HTML + - Index + - 'l10n:priority' + - publishing + - ガイド + - デザイン + - 学習 + - 理論 +translation_of: Learn/Getting_started_with_the_web +--- +
{{LearnSidebar}}
+ +
+

Web 入門は、実用的な Web 開発の入門シリーズです。まずはじめに、簡単な Web ページを作るのに必要なツールをセットアップします。そして、簡単なコードを書いたら、実際に Web に公開します。

+
+ +

初めての Web サイトの旅

+ +

プロが作るような Web サイトを作るのはとても大変な作業です。Web 開発の初心者は、まずは小さなものから作り始めるとよいでしょう。今すぐ Facebook のようなサイトを作ることはできませんが、簡単な Web サイトなら作るのはそれほど難しくありません。私たちはここから始めることにしましょう。

+ +

以下の記事を順番に読んでいけば、Web サイトを作ったことがない全くの初心者でも、自身の Web サイトを作って、Web に公開できるようになります。さあ、はじめましょう!

+ +

基本的なソフトウェアのインストール

+ +

Web サイトを作るためのツールはたくさんあります。Web 開発を始めたばかりの頃は、テキストエディタやフレームワーク、テストツールといったいろいろなソフトウェアが山のようにあって、混乱してしまうかもしれません。そこで、基本的なソフトウェアのインストールでは、基本的な Web 開発を始めるあなたのために私たちが選んだツールを紹介して、ツールのインストールの手順をひとつずつ順番に説明しています。

+ +

Web サイトをどんな外見にするか

+ +

Web サイトのコードを書き始める前に、まずは計画を立てることが大切です。あなたの Web サイトにはどんな情報を載せますか?フォントや色はどうしたいですか? Web サイトをどんな外見にするかでは、コンテンツやデザインを計画するのに役に立つ簡単な方法を紹介します。

+ +

ファイルの扱い

+ +

Web サイトを作るにはたくさんのファイルが必要です。テキストコンテンツのファイル、コードのファイル、スタイルシートのファイル、画像などのメディアコンテンツのファイルなどがあります。Web サイトを作るときは、これらのファイルをうまく配置して、ファイル同士がお互いにアクセスできることを確認する必要があります。ファイルの扱いでは、Web サイトのファイルを適切に配置する方法と、気をつけるべきことについて説明します。

+ +

HTML の基本

+ +

Hypertext Markup Language (HTML、ハイパーテキスト・マークアップ・ランゲージ) は、Web サイトのコンテンツに構造を指定して、それぞれの部分がどういう意味や目的を持っているのかを指定するために使うコードです。具体的に言うと、構造というのは、段落や箇条書きのリスト、画像、テーブルなどのようなものです。HTML の基本では、分からなくならないように、HTML に親しめるように丁寧に説明します。

+ +

CSS の基本

+ +

Cascading Stylesheets (CSS: カスケーディング・スタイルシート) は、Web サイトの見た目を決めるために使うコードです。CSS を書くと、テキストの色を黒や赤にしたり、コンテンツを画面のどこに表示するかを決めたり、ページの背景に好きな色をつけたり画像を表示したりして、Web サイトを好きなように飾り付けることができます。CSS の基本では、こうした飾り付けの方法について説明します。

+ +

JavaScript の基本

+ +

JavaScript は、Web サイトにインタラクティブな機能を追加するために使うプログラミング言語です。例えば、ゲーム、ボタンが押された時やフォームにデータが入力された時に起こること、動的なスタイルの効果、アニメーション、などなどです。JavaScript の基本では、この楽しいプログラミング言語を使ってどんなことができるのか、そしてどうやって使い始めれば良いのかを紹介します。

+ +

Web サイトの公開

+ +

Web サイトのコードを書き終えて、Web サイトに必要なファイルが用意できたら、作ったファイルをすべてオンラインにして、インターネット上の他の人からも見られるようにする必要があります。Web サイトの公開では、あなたが書いた簡単なコードをオンラインにして世界中に公開するための簡単な方法を説明します。

+ +

Web のしくみ

+ +

あなたがお気に入りの Web サイトにアクセスする時、実は目に見えない所ではとても複雑なことが行われています。Web のしくみでは、あなたがパソコンで Web ページを開いた時に裏側でどんなことが行われているのか、その大まかなしくみを説明します。

+ +

関連情報

+ +

Web Demystified: 完全な初心者を対象とした、Web 開発までの Web の基本を説明した動画の素晴らしいシリーズ。Jérémie Patonnier 作。

+ +

The web and web standards: この記事では、Web の役立つ背景 — どうやってできたのか、Web 標準技術とはなにか、どう連携させるか、" Web 開発者" がなぜ素晴らしいキャリアであるか、この過程を通じてどんなベストプラクティスが学習できるか — を提供します。

diff --git a/files/ja/learn/getting_started_with_the_web/installing_basic_software/index.html b/files/ja/learn/getting_started_with_the_web/installing_basic_software/index.html new file mode 100644 index 0000000000..f8432d7d97 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/installing_basic_software/index.html @@ -0,0 +1,80 @@ +--- +title: 基本的なソフトウェアのインストール +slug: Learn/Getting_started_with_the_web/Installing_basic_software +tags: + - WebMechanics + - 'l10n:priority' + - セットアップ + - ツール + - テキストエディタ + - ブラウザ + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/Installing_basic_software +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web")}}
+ +
+

「基本的なソフトウェアのインストール」では、あなたが簡単な Web 開発をするのに必要なツールを紹介して、それらのツールを適切にインストールする方法について説明します。

+
+ +

プロフェッショナルはどんなツールを使っている?

+ + + +

今の私にはどんなツールが必要?

+ +

上のリストにはたくさんのツールが書かれていて、ちょっと恐ろしかったかもしれませんね。でも大丈夫です。Web 開発を始めるのには、まだ上のツールをほとんど知らなくても問題ありません。これから私たちが、Web 開発に必要最小限のツールのセットアップの仕方を説明しておきます。必要なものは、テキストエディタと最新の Web ブラウザーだけで十分です。

+ +

テキストエディタのインストール

+ +

あなたのコンピューターには、おそらく初めから基本的なテキストエディタがインストールされているはずです。Windows にはメモ帳が、MacOS にはテキストエディットが、Linux の場合はディストリビューションによっていろいろですが、Ubuntu には gedit が初めからインストールされているはずです。

+ +

ただ、Web 開発をする時には、メモ帳やテキストエディットのようなソフトウェアよりも、もっと高機能なプログラムを使うべきです。私たちのおすすめのソフトウェアは、 Visual Studio Code です。これは無料で利用することができ、ライブプレビューやコードヒントを提供します。

+ +

最新の Web ブラウザーのインストール

+ +

次に、これから私たちが書くコードをテストするためのブラウザーをいくつかインストールしましょう。あなたが使っているオペレーティングシステムを選び、リンクから好きなブラウザーをインストールしてみてください。

+ + + +

次に進む前に、テストに使えるように最低でも 2 つのブラウザーをインストールするようにしてください。

+ +
+

メモ: Internet Explorer は最新の Web 機能と互換性がなく、プロジェクトを実行できない場合があります。現在は Internet Explorer を使用している人はほとんどいないので、通常はあなたの Web プロジェクトとそれの互換性について心配する必要はありません — 間違いなく学習中はあまり心配する必要はありません。

+
+ +

ローカルの Web サーバーのインストール

+ +

いくつかの例では、動作を成功させるのに Web サーバーでの実行が必要です。ローカルテストサーバーのインストール方法にて、その方法が見つかります。

+ +

{{NextMenu("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/javascript_basics/index.html b/files/ja/learn/getting_started_with_the_web/javascript_basics/index.html new file mode 100644 index 0000000000..61095df0eb --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/javascript_basics/index.html @@ -0,0 +1,437 @@ +--- +title: JavaScript の基本 +slug: Learn/Getting_started_with_the_web/JavaScript_basics +tags: + - JavaScript + - Learn + - Web + - codescripting + - 'l10n:priority' + - 初心者 +translation_of: Learn/Getting_started_with_the_web/JavaScript_basics +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/CSS_basics", "Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}
+ +
+

JavaScript は Web サイトにインタラクティブ機能 (ゲーム、ボタンが押されたときやデータがフォームに入力されたときの反応、動的なスタイルの変更、アニメーションなど) を追加するプログラミング言語です。この記事は、このエキサイティングな言語を始めるのに役立ち、可能性についてのアイディアを提供します。

+
+ +

そもそも JavaScript とは何か

+ +

{{Glossary("JavaScript")}} (略して "JS") は成熟した{{Glossary("Dynamic_programming_language", "動的プログラミング言語")}}であり、{{Glossary("HTML")}} 文書に適用すると、 Web サイトに動的な対話操作を提供できます。Mozilla プロジェクト、Mozilla Foundation、Mozilla Corporation の共同設立者である Brendan Eich によって考案されました。

+ +

JavaScript の用途は多彩です。小さいものでは、カルーセル、画像ギャラリー、レイアウトの変更、ボタンのクリックに対するレスポンスなどから始めることができます。もっと経験を積むと、ゲーム、2D および 3D のアニメーショングラフィック、包括的なデータベース駆動型アプリケーションなどを作成することができます。

+ +

JavaScript はとてもコンパクトですが、一方でとても柔軟性があります。開発者は JavaScript 言語のコアをベースに多種多様なツールを作成し、最小限の労力で膨大な様々な機能を利用できるようにしました。例えば以下のようなものがあります。

+ + + +

この記事は JavaScript の簡単な紹介に留めるべきだと思いますので、現段階では、JavaScript 言語のコアと上記の様々なツールの違いを詳しく話して混乱させることは避けるようにします。それらは、この後に続く詳細、JavaScript 学習エリア、およびMDN の他の部分で詳しく学ぶことができます。

+ +

以下では、コア言語のいくつかの側面について紹介します。またブラウザの API 機能についてもいくつか説明します。楽しみましょう!

+ +

"Hello world" の例

+ +

上記の章は実にエキサイティングに聞こえるかもしれませんが、それもそのはずです — JavaScript は最も活気のある Web 技術の 1 つで、使い始めれば、 Web サイトは力と創造性の新しい次元に入るでしょう。

+ +

しかし、JavaScript を使いこなせるようになるのは HTML や CSS よりも少し難しいです。小さなものから始め、小さく確実な手順で作業を続ける必要があるかもしれません。始めるにあたって、"hello world!" を表示する例 (基本的なプログラミング例の標準) を作りながら、基本的な JavaScript をページに追加する方法を紹介しましょう。

+ +
+

重要: これまでこのコースに沿って進めてきていない場合は、このサンプルコードをダウンロードして作業を進めてください。

+
+ +
    +
  1. 最初に、あなたのテストサイトに行って、「scripts」という名前(かぎ括弧は除く)の新しいフォルダを作成してください。それから、作成した scripts フォルダの中で main.js という新しいファイルを作成してください。それを scripts フォルダに保存してください。
  2. +
  3. 次に、 index.html ファイルの </body> 閉じタグの前に新しい行を追加し、以下の新しい要素を追加してください。 +
    <script src="scripts/main.js"></script>
    +
  4. +
  5. これは CSS の {{htmlelement("link")}} 要素の時の作業と基本的に同じです。これは JavaScript をページに適用するので、(CSS の時と同じく、ページ上の何に対しても) HTML に影響を与えることができます。
  6. +
  7. main.js ファイルに次のコードを追加してください。 +
    const myHeading = document.querySelector('h1');
    +myHeading.textContent = 'Hello world!';
    +
  8. +
  9. 最後に、 HTML と JavaScript を書いたファイルを保存したことを確認し、ブラウザで index.html を読み込んでください。
  10. +
+ +
+

: {{htmlelement("script")}} 要素を HTML ファイルの末尾付近に置いたのは、ブラウザが HTML をファイルに現れる順番で読み込むからです。もし JavaScript が最初に読み込まれ、その下の HTML に影響を与えると見られる場合、 HTML の準備ができる前に JavaScript が読み込まれ、正しく動作できない場合があります。したがって、 HTML ページの末尾付近に JavaScript を配置することは多くの場合、最良の方法です。

+
+ +

何が起きたか

+ +

JavaScript を使用して、見出しの文字列が "Hello world!" に変更されました。最初に {{domxref("Document.querySelector", "querySelector()")}} と呼ばれる関数を使用して見出しの参照を取得し、 myHeading と呼ばれる変数に格納しています。これは CSS のセレクターを使用するのととてもよく似ています。要素に対して何かをしたくなったら、まずその要素を選択する必要があります。

+ +

その後、myHeading 変数の {{domxref("Node.textContent", "textContent")}} プロパティ(見出しの内容を表す)の値を "Hello world!" に設定します。

+ +
+

: 上の例で使用した機能はどちらもドキュメントオブジェクトモデル (DOM) API の一部であり、これを使って文書を操作することができます。

+
+ +

言語の短期集中コース

+ +

どのように動作するかをよりよく理解できるように、 JavaScript 言語の基本機能のいくつかを説明しましょう。これらの機能はすべてのプログラミング言語に共通しているので、これらの基本をマスターすれば、ほとんど何でもプログラムできるようになります!

+ +
+

重要: この記事では、 JavaScript コンソールにサンプルコードを入力して、何が起こるのかを確認してみます。 JavaScript コンソールの詳細については、 ブラウザ開発ツールを探るを参照してください。

+
+ +

変数

+ +

{{Glossary("Variable", "変数")}} は、値を格納できる入れ物です。まず、 var (説明はややこしいですが、推奨しません) まはた let というキーワードと、その後に任意の名前を指定することで、変数を宣言します。

+ +
let myVariable;
+ +
+

: 行末のセミコロンは文が終わる場所を示します。単一の行で複数の文を区切る場合には絶対に必要です。しかし、個々の文の末尾に置くことが良い習慣だと信じている人もいます。使用する場面と使用しない場合については他のルールもあります。詳しくは Your Guide to Semicolons in JavaScript を参照してください。

+
+ +
+

: 変数にはほとんど何でも名前を付けることができますが、いくらかの制約があります(変数の命名規則についてはこの記事を参照してください)。自信がない場合は、有効かどうか変数名を調べることができます。

+
+ +
+

: JavaScript は大文字と小文字を区別します。myVariablemyvariable とは異なる変数です。コードで問題が発生している場合は、大文字・小文字をチェックしてください。

+
+ +
+

: varlet のより詳しい違いは、var と let の違いを見てください。

+
+ +

変数を宣言したら、以下のように値を割り当てることができます。

+ +
myVariable = 'Bob';
+ +

好みに応じて、両方の操作を同一の行で行うことができます。

+ +
let myVariable = 'Bob';
+ +

変数の値は、名前で呼び出すだけで取得することができます。

+ +
myVariable;
+ +

変数に値を代入した後で、変更することもできます。

+ +
let myVariable = 'Bob';
+myVariable = 'Steve';
+ +

なお、変数は様々なデータ型の値を保持することもできます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
データ型説明
{{Glossary("String")}}文字列と呼ばれる一連のテキスト。値が文字列であることを示すには、引用符で囲む必要があります。let myVariable = 'Bob';
{{Glossary("Number")}}数。数字には引用符がありません。let myVariable = 10;
{{Glossary("Boolean")}}真偽値。 truefalse は JS では特別なキーワードであり、引用符は必要ない。let myVariable = true;
{{Glossary("Array")}}単一の参照で複数の値を格納できる構造です。let myVariable = [1,'Bob','Steve',10];
+ 配列の各メンバーはこのように参照してください。
+ myVariable[0], myVariable[1], など。
{{Glossary("Object")}}基本的には何でも格納できます。 JavaScript のすべてがオブジェクトであり、変数に格納することができます。学ぶ際にはこれを覚えておいてください。let myVariable = document.querySelector('h1');
+ 上記の例も同様です。
+ +

ではなぜ変数が必要なのでしょうか。何か面白いプログラミングをするには変数が必要です。値が変更できなければ、挨拶のメッセージをパーソナライズしたり、画像ギャラリーに表示されている画像を変更するなどの動的な操作ができないのです。

+ +

コメント

+ +

コメントは、ブラウザーから無視される、コードの間に入れられた短いテキストスニペットです。CSS と同じように、JavaScript のコードではコメントを付けることができます。

+ +
/*
+挟まれているすべてがコメントです。
+*/
+ +

コメントに改行が含まれていない場合、次のように 2 つのスラッシュの後ろに記載する方が簡単です :

+ +
// これはコメントです
+
+ +

演算子

+ +

{{Glossary("operator", "演算子")}}は、2 つの値 (または変数) に基づいて結果を生成する数学的な記号です。次の表では、JavaScript コンソールで試してみるいくつかの例とともに、最も単純な演算子をいくつか見ることができます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子説明シンボル
追加/連結2 つの数字を加えるか、2 つの文字列を結合します。+6 + 9;
+ 'Hello ' + 'world!';
減算、乗算、除算基本的な数学の計算を実施します。-, *, /9 - 3;
+ 8 * 2; // JavaScript で乗算はアスタリスク
+ 9 / 3;
代入すでに出てきました。変数に値を割り当てます。=let myVariable = 'Bob';
等価2 つの値と型が互いに等しいかどうかを調べ、true / false (真偽値)の結果を返します。===let myVariable = 3;
+ myVariable === 4;
否定、非等価その後にあるものと論理的に反対の値を返します。たとえば truefalse に換えます。等価演算子と一緒に使用されると、否定演算子は 2 つの値が等しくないかどうかをテストします。!, !== +

"Not" の場合、基本式は true ですが、それを否定しているので比較結果は false になります。

+ +

let myVariable = 3;
+ !(myVariable === 3);

+ +

「等しくない」は、基本的に同じ結果を異なる構文で与えます。ここでは「myVariable が 3 とは等しくない」ことをテストします。 myVariable は 3 と等しいので、false を返します。

+ +

let myVariable = 3;
+ myVariable !== 3;

+
+ +

他にも演算子はもっとたくさんありますが、今のところはこれで十分です。全体の一覧については、式と演算子を参照してください。

+ +
+

: データ型を混在させると、計算を実行するときに奇妙な結果になる可能性があるため、変数を正しく参照し、期待通りの結果を得るように注意してください。例えばコンソールに '35' + '25' と入力してみてください。期待通りの結果にならないのはなぜでしょうか。引用符は数字を文字列に変換するので、数字を加算するのではなく、文字列を連結する結果になったのです。 35 + 25 を入力すれば、正しい結果が得られます。

+
+ +

条件文

+ +

条件文は、ある式が true を返すかどうかをテストし、その結果次第でそれぞれのコードを実行するコード構造です。条件文のよくある形は if ... else 文です。例えば以下の通りです。

+ +
let iceCream = 'チョコレート';
+if(iceCream === 'チョコレート') {
+  alert('やった、チョコレートアイス大好き!');
+} else {
+  alert('あれれ、でもチョコレートは私のお気に入り......');
+}
+ +

if( ... ) の中の式が条件です — ここでは等価演算子を使用して、変数 iceCreamチョコレートという文字列とをを比較し、2 つが等しいかどうかを調べています。この比較が true を返した場合、コードの最初のブロックが実行されます。比較が真でない場合、最初のブロックはスキップされ、else 文の後にある 2番目のコードブロックが代わりに実行されます。

+ +

関数

+ +

{{Glossary("Function", "関数")}} は、再利用したい機能をパッケージ化する方法です。プロシージャが必要なときは、毎回コード全体を書くのではなく関数名を使って関数を呼び出すことができます。すでにいくつかの関数の仕様を見てきました。例えば以下のようなものです。

+ +
    +
  1. +
    let myVariable = document.querySelector('h1');
    +
  2. +
  3. +
    alert('hello!');
    +
  4. +
+ +

これらの関数、document.querySelectoralert は、必要なときにいつでも使えるようブラウザに組み込まれています。

+ +

もし変数名に見えるものがあったとしても、その後に括弧 () が付いていれば、おそらくそれは関数です。関数は普通、仕事をするのに必要な小さなデータである{{Glossary("Argument", "引数")}}を取ります。引数は括弧の中に入れ、複数の引数がある場合はカンマで区切ります。

+ +

例えば、alert() 関数はブラウザのウィンドウにポップアップボックスを表示しますが、ポップアップボックスに何を書き込むかを関数に指示するために、文字列を引数として渡す必要があります。

+ +

嬉しいことに、自分で関数を定義することができます。次の例では、引数として 2 つの数値をとり、それらを乗算するという単純な関数を記載します。

+ +
function multiply(num1,num2) {
+  let result = num1 * num2;
+  return result;
+}
+ +

上記の関数をコンソールで実行し、いくつかの引数を指定してテストしてみてください。例えば次のようなものです :

+ +
multiply(4,7);
+multiply(20,20);
+multiply(0.5,3);
+ +
+

: return 文は result の値を関数内から関数の外に戻すことをブラウザに指示し、それを利用できるようにします。これが必要な理由は、関数内で定義された変数が、その関数内でしか利用できないためです。これは変数の{{Glossary("Scope", "スコープ")}}と呼ばれています(変数のスコープのより詳しい説明をお読みください)。

+
+ +

イベント

+ +

Web サイトを実際にインタラクティブにするには、イベントが必要です。イベントは、ブラウザの中で起きていることを検出し、その応答としてコードを実行するコード構造です。最も分かりやすい例は click イベントで、マウスで何かをクリックするとブラウザによって発火されるものです。これを実行するには、コンソールに以下のように入力してから、現在の Web ページ上をクリックしてください。

+ +
document.querySelector('html').onclick = function() {
+    alert('痛っ! つつくのはやめて!');
+}
+ +

要素にイベントを割り当てる方法はたくさんあります。ここでは {{htmlelement("html")}} 要素を選択し、onclick ハンドラのプロパティに、クリックイベントで実行したいコードを含む匿名 (つまり名前がない) 関数を代入します。

+ +

なお、

+ +
document.querySelector('html').onclick = function() {};
+ +

は以下のものと同等です。

+ +
let myHTML = document.querySelector('html');
+myHTML.onclick = function() {};
+ +

短くしただけです。

+ +

Web サイトの例を膨らませる

+ +

ここまで JavaScript の基本を少し見てきましたが、何ができるのかを見るために、例のサイトにいくつかクールな機能を追加してみましょう。

+ +

画像の切り替えの追加

+ +

このセクションでは、 DOM API 機能をもっと使用して、サイトに画像を追加しましょう。画像をクリックすると JavaScript を使用して 2 つの画像を切り替えることができます。

+ +
    +
  1. まずサイトに掲載したいと思う別な画像を見つけてください。最初の画像と同じサイズか、できるだけ近いものを使用してください。
  2. +
  3. この画像を images フォルダに保存してください。
  4. +
  5. この画像の名前を 'firefox2.png' (引用符なし) に変更してください。
  6. +
  7. main.js ファイルに移動し、次の JavaScript を入力します。(もし "hello world" の JavaScript がまだ残っている場合は、削除してください。) +
    let myImage = document.querySelector('img');
    +
    +myImage.onclick = function() {
    +    let mySrc = myImage.getAttribute('src');
    +    if(mySrc === 'images/firefox-icon.png') {
    +      myImage.setAttribute ('src','images/firefox2.png');
    +    } else {
    +      myImage.setAttribute ('src','images/firefox-icon.png');
    +    }
    +}
    +
  8. +
  9. index.html をブラウザに読み込みます。画像をクリックすると、もう一方の画像に変わります。
  10. +
+ +

{{htmlelement("img")}} 要素への参照を変数 myImage に格納します。次にこの変数の onclick イベントハンドラプロパティに、名前のない関数(無名関数)を代入します。そうすれば、この要素がクリックされるたびに以下の動きをします。

+ +
    +
  1. 画像の src 属性の値を取得します。
  2. +
  3. 条件文を使って、src の値が元の画像のパスと等しいかどうかをチェックします。 +
      +
    1. そうであれば、src の値を 2番目の画像へのパスに変更し、もう一方の画像が強制的に {{htmlelement("img")}} 要素の中に読み込まれるようにします。
    2. +
    3. そうでない(すでに変更されている)場合、src の値を元の画像のパスに戻して、元の状態に戻ります。
    4. +
    +
  4. +
+ +

パーソナライズされた挨拶メッセージの追加

+ +

次に、もう 1 つの小さなコードを追加し、ユーザがサイトにアクセスしたときに、ページの表題をパーソナライズされた挨拶メッセージに変更してみましょう。この挨拶メッセージは、ユーザがサイトを離れて後で戻った時にも保存されるようにします。Web Storage API を使用して保存しましょう。したがって、必要な時にいつでもユーザと挨拶メッセージを変更できるオプションも用意しましょう。

+ +
    +
  1. index.html では、 {{htmlelement("script")}} 要素の直前に次の行を追加します : + +
    <button>ユーザを変更</button>
    +
  2. +
  3. main.js では、次のコードを下記のとおりにファイルの最後に配置します。これは新しいボタンと見出しへの参照を変数に格納します。 +
    let myButton = document.querySelector('button');
    +let myHeading = document.querySelector('h1');
    +
  4. +
  5. パーソナライズされた挨拶を設定する以下の関数を追加しましょう。まだ何も起こりませんが、すぐに修正します。 +
    function setUserName() {
    +  let myName = prompt('あなたの名前を入力してください。');
    +  localStorage.setItem('name', myName);
    +  myHeading.textContent = 'Mozilla はすばらしいよ、' + myName;
    +}
    + この関数では prompt() 関数を使用して、alert() のようにダイアログボックスを表示しています。しかし、prompt() はユーザにデータを入力するよう求め、ユーザが OK を押した後に変数にそのデータを格納します。この場合、ユーザに名前を入力するよう求めます。次に、localStorage と呼ばれる API を呼び出すことで、ブラウザにデータを格納して後で受け取ることができます。localStorage の setItem() 関数を使って、'name' と呼ばれるデータを作成し、myName に入っているユーザから入力されたデータを格納します。最後に、見出しの textContent に文字列と新しく格納されたユーザの名前を設定します。
  6. +
  7. 次に、この if ... else ブロックを追加します。これは初期化コードと呼ぶことができ、最初の読み込みでアプリを構成します。 +
    if(!localStorage.getItem('name')) {
    +  setUserName();
    +} else {
    +  let storedName = localStorage.getItem('name');
    +  myHeading.textContent = 'Mozilla はすばらしいよ、' + storedName;
    +}
    + このブロックでは、最初に name のデータが存在しているかどうかをチェックするために否定演算子(! で表される論理否定)を使用しています。存在しない場合は、作成するために setUserName() 関数が実行されます。存在する場合は(つまり、以前の訪問時にユーザが設定した場合)、 getItem() を使用して格納された名前を受け取り、 setUserName() の中で行ったのと同様に、見出しの textContent に文字列とユーザの名前を設定します。
  8. +
  9. 最後に、以下の onclick イベントハンドラをボタンに設定します。クリックすると、setUserName() 関数が実行されます。これでユーザがボタンを押すことで、好きな時に新しい名前を設定できるようになります。 +
    myButton.onclick = function() {
    +  setUserName();
    +}
    +
    +
  10. +
+ +

サイトにアクセスしてみると、ページがユーザ名を尋ね、パーソナライズされたメッセージを表示します。好きなときにボタンを押すと名前を変えることができます。おまけに、名前は localStorage 内に格納されているため、サイトを閉じた後も名前が保持され、次にサイトを開いたときにパーソナライズされたメッセージが保持されます。

+ +

A user name of null?

+ +

この例を実行してユーザー名を入力するダイアログボックスが出たとき、キャンセルボタンを押してみてください。結果として"Mozilla is cool, null"というタイトルが表示されるでしょう。これはプロンプトをキャンセルしたときに、値が null、つまり値がないことに言及する JavaScript の特殊な値にセットされているためです。

+ +

また何も入れずに OK を押してみてください — 結果として"Mozilla is cool,"というタイトルが表示され、これは理由が明白です。

+ +

この問題を避けるには、ユーザーが null や空白の名前を入力していないかチェックするよう、setUserName() 関数を書き換えます:

+ +
function setUserName() {
+  let myName = prompt('Please enter your name.');
+  if(!myName || myName === null) {
+    setUserName();
+  } else {
+    localStorage.setItem('name', myName);
+    myHeading.innerHTML = 'Mozilla is cool, ' + myName;
+  }
+}
+ +

人間の言語では — myName に値がない場合や、nullの場合、 最初から setUserName() を実行します。値がない場合 (上記の式が真でない場合)には、localStorage に値をセットして、見出しのテキストにもセットします。

+ +

まとめ

+ +

最後までこの記事の手順に従った場合は、最終的に次のようなページが表示されているでしょう (こちらで作成した版を表示することもできます)。

+ +

+ +

行き詰まったら、自分の作業を Github 上の完成したサンプルコードと比べてみてください。

+ +

私たちは JavaScript に少し触れただけです。楽しく遊んだり、もっと上達したい場合は、JavaScript の学習トピックに進んでください。

+ +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/CSS_basics", "Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html b/files/ja/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html new file mode 100644 index 0000000000..88eb4cf626 --- /dev/null +++ b/files/ja/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html @@ -0,0 +1,110 @@ +--- +title: Web サイトをどんな外見にするか +slug: Learn/Getting_started_with_the_web/What_will_your_website_look_like +tags: + - Assets + - Composing + - Deprecated + - Plan + - 'l10n:priority' + - コンテンツ + - デザイン + - フォント + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/What_will_your_website_look_like +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/Installing_basic_software", "Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web")}}
+ +
+

Web サイトをどのような外見にするか」では、「どんな情報を Web サイトで提供するか」、「どのフォントと色を使うのか」、「私の Web サイトは何をするのか」といった、コードを書き始める前にあなたの Web サイトについて計画したりデザインするべき事柄について説明します。

+
+ +

まず最初に: 計画を立てる

+ +

始める前に、いくつか考えておかなければいけないことがあります。あなたの Web サイトは実際に何をすべきでしょうか?普通 Web サイトは様々なことができます。しかし、はじめは単純なことにとどめておくべきでしょう。まずは、一つの見出し、一つの画像、そして少しの文章をもつシンプルな Web ページを作ることから始めましょう。

+ +

まずはじめに、次の質問に答える必要があります。

+ +
    +
  1. 何について書かれた Web サイトですか? 犬、ニューヨーク、それともパックマン?
  2. +
  3. テーマについてどんなことを書きますか? タイトルと少しの文章、それからページに表示させたい画像を考えます。
  4. +
  5. Web サイトをどんな見た目にしますか? シンプルで高いレベルから考えます。背景の色は何色にする?サイトにピッタリのフォントの種類はどんなもの?フォーマルなフォント?漫画みたいなフォント?くっきりとした太字?それとも、繊細な細字のフォントでしょうか?
  6. +
+ +
+

注記: 複雑なプロジェクトでは、カラー、フォント、ページのアイテム間のスペース、適切な文章のスタイルなど、詳細なガイドラインが必要です。これは、デザインガイドやデザインシステムやブランドブックと呼ばれます。一例として、 Firefox Photon Design Systemがあります。

+
+ +

デザインを大まかに描き出す

+ +

次に、ペンと紙を取って、あなたのサイトの見た目をどういう風にしたいのか、大まかに描き出します。はじめてのシンプルな Web ページでは、描き出すものもあまりないですが、Web サイトを作るうえでの習慣として身につけるべきです。ヴァン・ゴッホのようになる必要はありませんので!

+ +

+ +
+

注記: 現実の複雑な Web サイトの場合でも、デザインチームは普通、ラフスケッチを描くことから始めます。その後、グラフィックエディタや Web の技術を使って、デジタルのモックアップを作るのです。

+ +

多くの場合、Web の開発チームには、グラフィックデザイナーと{{Glossary("UX", "ユーザーエクスペリエンス")}} (UX) デザイナーがいます。グラフィックデザイナーは、名前の通り Web サイト上の目に見えるイメージなどを作り上げます。 UX デザイナーは、もう少し抽象的な役割を持っていて、サイトを訪れるユーザーが Web サイトでどういう経験をし、どのようにインタラクションするかということを考えます。

+
+ +

アセットを選ぶ

+ +

この時点で、あなたの Web ページについて、将来どう表現したいかをまとめ始めるとよいでしょう。

+ +

文章・テキスト

+ +

あなたが先ほど考えたちょっとした文章やタイトルは、まだそのまま残しておきます。手近なところに置いておきましょう。

+ +

テーマカラー

+ +

色を選ぶときは、色選択ツール (カラーピッカー: Firefox のアドオンやアプリもあります) のサイトへ行き、自分の好みの色を見つけましょう。色をクリックすると、 #660066 のような6文字の奇妙なコードが出てきます。これはヘキサコード (16進法コード) と呼ばれ、あなたの選んだ色を表しています。今はどこか安全なところにコピーしておきましょう。

+ +

+ +

画像・イメージ

+ +

画像を探すには、Google 画像検索にアクセスし、ぴったりなものを探しましょう。

+ +
    +
  1. 欲しい画像が見つかったら、クリックして拡大表示にします。
  2. +
  3. 画像を右クリック (Mac では Ctrl +クリック) し、[名前を付けて画像を保存...] を選択して、画像を安全に保存する場所を選択します。または、後で使用するためにブラウザーのアドレスバーから画像の Web アドレスをコピーします。
  4. +
+ +

+ +

なお、Web 上のほとんどの画像には、 Google 画像検索にあるものも含め、著作権があります。あなたが著作権を侵害してしまう可能性を減らすために、 Google のライセンスフィルターを使うと良いでしょう。 ツールボタンをクリックすると、ライセンスオプションが下に表示されます。再使用が許可された画像などの選択肢を選択してください。

+ +

+ +

フォント

+ +

次のような手順でフォントを選びます。

+ +
    +
  1. Google Fonts に行き、ページをスクロールして気に入ったフォントを見つけます。右側のコントロールを使って、結果をフィルタすることもできます。
  2. +
  3. 使いたいフォントの上にあるプラス (追加) アイコンをクリックします。
  4. +
  5. ページ下部のパネルにある "* Family Selected" と書かれたボタンをクリックします ("*" は選択したフォントの数によって変わります)。
  6. +
  7. ポップアップボックスに、Google が用意してくれた数行のコードが表示されるので、あとでテキストエディタに入力する時のためにコピーしておきます。
  8. +
+ +

+ +

+ +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/Installing_basic_software", "Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール内の文書

+ + diff --git "a/files/ja/learn/getting_started_with_the_web/\343\202\246\343\202\247\343\203\226\343\202\265\343\202\244\343\203\210\343\202\222\345\205\254\351\226\213\343\201\231\343\202\213/index.html" "b/files/ja/learn/getting_started_with_the_web/\343\202\246\343\202\247\343\203\226\343\202\265\343\202\244\343\203\210\343\202\222\345\205\254\351\226\213\343\201\231\343\202\213/index.html" new file mode 100644 index 0000000000..df7bdd555e --- /dev/null +++ "b/files/ja/learn/getting_started_with_the_web/\343\202\246\343\202\247\343\203\226\343\202\265\343\202\244\343\203\210\343\202\222\345\205\254\351\226\213\343\201\231\343\202\213/index.html" @@ -0,0 +1,133 @@ +--- +title: Web サイトの公開 +slug: Learn/Getting_started_with_the_web/ウェブサイトを公開する +tags: + - FTP + - GitHub + - Google App Engine + - Learn + - Web + - 'l10n:priority' + - publishing + - web server + - コードスクリプティング + - 初心者 + - 学習 +translation_of: Learn/Getting_started_with_the_web/Publishing_your_website +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web/How_the_Web_works", "Learn/Getting_started_with_the_web")}}
+ +
+

サイトのコードやファイルの準備ができたら、そのサイトをほかの人が見つけられるように、ファイルやコードをすべてオンラインに置く必要があります。この記事では、シンプルなサンプルコードを少しの手間でネット上に公開する方法を説明します。

+
+ +

どんな選択肢があるのか?

+ +

Web サイトを公開するというのは簡単に語れることではありません。なぜなら、 Web サイトの公開の仕方には、さまざまな方法があるからです。この記事での私たちの目標は、そのすべての方法を記述することではありません。むしろ、我々は初心者の視点から、大まかに 3 つの手法の長所と短所をお話しし、その次に、今のところはこれでうまくいくという方法で一通りやってみます。

+ +

ホストとドメイン名を手に入れる

+ +

もし、あなたが公開した Web サイトのすべてをコントロールしたいと思うなら、次の 2 つに関してお金を払う必要があるでしょう。

+ + + +

多くのプロの手による Web サイトはこんな風にして、公開されているわけです。

+ +

加えて、あなたは、実際に Web サイトに関するファイルをサーバーに送るために、{{Glossary("FTP", "File Transfer Protocol (FTP)")}} プログラムが必要です (詳しくは、どれくらいお金がかかるか: ソフトウェアのページにて)。FTP プログラムは、プログラムごとに様々ですが、一般的に Web サーバーのホスティング会社が提供する詳細情報 (例えば、ユーザーネーム、パスワード、ホスト名) を使用してログインする必要があります。ログインすると、FTP プログラムは、あなたの pc のローカルファイルと、サーバー上のファイルを二つのウィンドウで表示します。その画面において、あなたはファイルを送ったり戻したりできます。

+ +

+ +

ホスティングとドメインを見つけるための TIPS(ヒント)

+ + + +

GitHub や Google App Engine のようなオンラインツールを利用する

+ +

特定のツールを使って、あなたの Web サイトをオンラインに公開することもできます。

+ + + +

これらのツールは、多くのホスティングと違って、利用するのは無料です。しかし、使える機能はやはり限られています。

+ +

CodePen のような、 Web ベースの IDE を用いる方法。

+ +

Web 開発環境を真似た Web アプリはたくさんあります。それらで HTML や CSS、JavaScript を入力し、それらのコードを Web ページとしてレンダリングした結果を表示できます — すべてが 1 つのブラウザータブの中で。一般的に言って、これらのツールはとても簡単で、とても勉強になり、コードの共有に向いていて(例えば、テクニックを共有したり、別のオフィスの同僚にデバッグの助けを求める)、(基本的な機能は) 無料です。

+ +

生成したページを固有のアドレスでホストします。しかしながら、基本的な機能はかなり限られたものであり、そのアプリは大抵において、アセット (画像など) のためのホスティングスペースを提供していません。

+ +

これらを試してみて、一番あなたに合ったものを見つけてみましょう。

+ + + +

+ +

GitHub 経由での公開

+ +

では、GitHub Pages 経由でどれくらい簡単にサイトを公開できるかを実際にやってみましょう。

+ +
    +
  1. まず、 GitHub にサインアップして、あなたのメールアドレスを確認しましょう。
  2. +
  3. 次に ファイルを入れるためのリポジトリを作りましょう。
  4. +
  5. このページ上の、Repository name ボックスに username.github.io の形で、ユーザー名を入力しましょう。username のところに、あなたの名前が入ります。
    + 例えば、私たちの友人である bob smith ならば、
    + bobsmith.github.io と入力することになります。
    + さらに、{{原語併記("README つきでこのリポジトリを初期化", "Initialize this repository with a README")}}をチェックして、{{原語併記("リポジトリの作成", "Create repository")}}をクリックします。
  6. +
  7. Web サイトのフォルダをリポジトリの中にドラッグアンドドロップしたら、Commit changes をクリックしましょう。
    + +
    +

    : フォルダの中に index.html の名前のファイルがあるかを確認しましょう。

    +
    +
  8. +
  9. +

    では、あなたの Web サイトをオンライン上で見るために、ブラウザーから username.github.io に移動しましょう。例えば、ユーザーネームが chrisdavidmills なら、chrisdavidmills.github.io に移動しましょう。

    + +
    +

    : あなたの Web サイトに行けるようになるには少し時間がかかるかもしれません。すぐに行ってもダメなようなら、少し待ってからもう一度試してみましょう。

    +
    +
  10. +
+ +

もっと詳しく知りたい人は GitHub Pages Help を見てください。

+ +

参考文献

+ + + +

{{PreviousMenuNext("Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web/How_the_Web_works", "Learn/Getting_started_with_the_web")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/how_to_contribute/index.html b/files/ja/learn/how_to_contribute/index.html new file mode 100644 index 0000000000..bd269dd210 --- /dev/null +++ b/files/ja/learn/how_to_contribute/index.html @@ -0,0 +1,86 @@ +--- +title: MDN の学習エリアに貢献するには +slug: Learn/How_to_contribute +tags: + - Beginner + - Contribute + - Documentation + - Guide + - Learn + - MDN Meta + - 'l10n:priority' +translation_of: Learn/How_to_contribute +--- +
{{LearnSidebar}}
+ +

あなたがこのページに初めて、あるいはたくさん検索した末に辿り着いたのなら、それはきっとあなたが MDN の学習エリアへの貢献に興味を持って下さったからでしょう。素晴らしいことです!

+ +

このページでは、 MDN の学習コンテンツの改良に協力し始めるのに必要となる全てが見つかるでしょう。できることはたくさんあって、それはあなたがどれくらい時間を使えるか、初心者ウェブ開発者教師かによって決まります。

+ +
+

メモ: 学習エリアの記事を書くためのガイドは、ウェブを学習する人に役立つ記事の書き方にあります。

+
+ +

特定のタスクを探す

+ +

学習エリアに貢献する共通の方法は、記事を読み、誤字を直し、改良を提案することです。GitHub repoへのサンプル追加も、何が必要か聞きたいと思って連絡頂くのも歓迎です。

+ +

新しいことを学習するときに、貢献することは楽しめる良い方法です。道に迷った気になったり、質問があった場合は、Learning Area Discourse threadIRC channel いずれも英語ベース (詳しくはページ最下部を見てください)。Chris Mills が Learning Area (学習エリア) のトピックドライバーです — 彼に直接 ping してもいいでしょう。

+ +

下記の節では一般的なアイデアとして、やることの種類を挙げています。

+ +

初心者の方なら

+ +

すばらしい!初心者は学習エリアの中身にフィードバックを作るのに重要かつ貴重です。あなたにはこの記事のターゲット読者の一員で、われわれのチームの貴重なメンバーになりうるという独特の視点があります。実際に、記事を何かの学習に使ってつまったり、誤解を招く記事を見かけた場合、自分で修正するか、または我々が確実に修正できるように問題点を連絡することができます。

+ +

次のように、貢献できるいくつかの方法があります:

+ +
+
記事にタグを追加する (5分)
+
MDN のコンテンツをタグ付けするのは、 MDN に協力する最も簡単な方法です。タグによって状況にあわせた機能を提供できるようになるため、タグ付けはとても意味ある貢献です。タグ付けを始める前に、用語集の記事学習記事の一覧をご覧ください。
+
用語集の記事を読んでレビューする (5分)
+
コンテンツを初心者の目線で見てもらう必要があります。用語集の記事に分かりにくい箇所があれば改善が必要なため、気軽に変更してください。自分には必要なスキルが無いと感じたら、私たちのメーリングリストに連絡してください。
+
用語集の記事を書く (20分)
+
これは新しいことを学ぶ最良の方法です。理解したい概念を選び、それについて学んだら、用語集の記事を書きましょう。何かを他人に説明することは、頭の中で知識を「定着」させ、物事を自分自身で良く理解できるようになり、さらに他人のために役立ちます。みんなが得をします!
+
学習記事を読んでレビューする (2時間)
+
これは用語集の記事のレビューとよく似ています(上記参照)。こういった記事は通常かなり長いため、より時間を要するだけです。
+
+ +

ウェブ開発者なら

+ +

素敵です!あなたの技術スキルは、初心者向けの技術的に正確なコンテンツを提供するために、まさに我々が必要としているものです。ここは MDN の特定の箇所としてウェブの学習専用であり、説明はできるだけ簡潔であり、簡潔すぎて役立たないのは避けないといけません。過度に正確であることよりも、理解できることがもっと重要です。

+ +
+
用語集の記事を読んでレビューする (5分)
+
ウェブ開発者であるあなたには、私たちのコンテンツが複雑になりすぎずに技術的に正確であるかを確認していただく必要があります。必要に応じて気軽に変更を加えてください。編集の前に内容を議論したい場合は、私たちのメーリングリストまたは IRC channelでコンタクトしてください。
+
用語集の記事を書く (20分)
+
技術的な専門用語を明確にすることは、学習するのと、技術的に正確かつシンプルであるためのとても良い方法です。初心者からは感謝されるでしょう。注目すべき未定義の用語がたくさんあります。都合が良いものを選んでください。
+
学習記事を読んでレビューする (2時間)
+
これは用語集の記事のレビュー(上記)と同じことです。この記事は少し長い時間がかかるだけです。
+
新しい学習記事を書く (4時間以上)
+
MDN には、ウェブ技術(HTML, CSS, JavaScriptなど)についてのシンプルで直言的な記事が欠けています。また MDN にはレビューや作り直しをするべき古いコンテンツもあります。あなたのスキルの限界までふりしぼって、ウェブ技術が初心者でも使えるようにしてください。
+
練習、コードサンプル、インタラクティブな学習ツールの作成 (?時間)
+
全ての学習記事は「アクティブラーニング」と呼ぶ記事を必要としています。その理由は人は自分で何かやってみるのが学ぶのに最良だからです。この素材は、ユーザーが記事に述べられる概念を適用・操作するのを助ける、練習やインタラクティブコンテンツです。アクティブラーニングのコンテンツを作るには多数の方法があり、 JSFiddle や同等品でコードサンプルを作ることから、Thimble で完全にハック可能なインタラクティブコンテンツを作ることまであります。創造性を解き放って!
+
+ +

教師なら

+ +

MDN は技術的な卓越性において長い歴史がありますが、新人に概念を教える最良の方法についての理解は十分ではありません。ここは教師・教育者であるあなたを必要とするところです。私たちの教材が読者にとって優れた、実践的な学びの道筋を提供できるよう手助けできます。

+ +
+
用語集の記事を読んでレビューする (15分)
+
用語集の記事を確認して、必要に応じて気軽に変更を加えてください。編集の前に内容を議論したい場合は私たちのメーリングリストまたは IRC channelでコンタクトしてください
+
用語集の記事を書く (1時間)
+
用語集にて、明確でシンプルな言葉の定義と、概念の基本的な説明は、初心者の要求を満たすのに重要です。教育者としての経験がすばらしい用語集の記事の作成に役立ちます。注目すべき未定義の用語がたくさんあります。都合が良いものを選んでください。
+
記事のイラストや図を描く (1時間)
+
ご存知のように、イラストはあらゆる学習コンテンツの中で有益な部分です。これは MDN でよく不足しているもので、あなたのスキルがそのエリアを違ったものにします。図示コンテンツが不足している記事を確認して、絵を作りたいものを選びます。
+
学習記事を読んでレビューする (2時間)
+
これは用語集の記事(上記)のレビューと同じことです。この記事は少し長い時間がかかるだけです。
+
新しい学習記事を書く (4時間)
+
ウェブのエコシステムとその周りの機能的なトピックについてのシンプルで直言的な記事が必要です。学習記事では知るべきことを全て網羅するよりも、教育的である必要があるため、何をどのように網羅すべきかを知っているあなたの経験は良い資産になるでしょう。
+
練習、クイズ、インタラクティブな学習ツールの作成 (?時間)
+
全ての学習記事は「アクティブラーニング」と呼ぶ記事を必要としています。その理由は人は自分で何かやってみるのが学ぶのに最良だからです。この素材は、ユーザーが記事に述べられる概念を適用・操作するのを助ける、練習やインタラクティブコンテンツです。アクティブラーニングのコンテンツを作るには多数の方法があり、クイズを作ることから、Thimble で完全にハック可能なインタラクティブコンテンツを作ることまであります。創造性を解き放って!
+
+
学習の進路を作る (?時間)
+
進歩的で理解できるチュートリアルを提供するため、コンテンツを学習進路に形付ける必要があります。既存のコンテンツを集めて、学習記事を作成するのに何がたりないか理解するのに良い方法です。
+
diff --git a/files/ja/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html b/files/ja/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html new file mode 100644 index 0000000000..b53798c7d6 --- /dev/null +++ b/files/ja/learn/html/howto/add_a_hit_map_on_top_of_an_image/index.html @@ -0,0 +1,126 @@ +--- +title: 画像にヒットマップを追加する +slug: Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image +tags: + - Graphics + - Guide + - HTML + - Intermediate + - Navigation +translation_of: Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image +--- +
+

ここでは、イメージマップを設定する方法と、最初に検討すべきいくつかの欠点を説明します。

+
+ + + + + + + + + + + + +
前提条件:基本的な HTML 文書の作成方法と、アクセス可能な画像をウェブページに追加する方法について、理解している必要があります。
目的:1つの画像の異なる領域を異なるページにリンクする方法を学びます。
+ +
+

この記事では、クライアント側のイメージマップについてのみ説明します。 ユーザーにマウスが必要なサーバー側のイメージマップは使用しないでください。

+
+ +

イメージマップとその欠点

+ +

{{htmlelement('a')}} 内に画像をネストすると、画像全体が1つのウェブページにリンクします。 一方、イメージマップは、それぞれが異なるリソースにリンクするいくつかのアクティブな領域(「ホットスポット」と呼ばれます)を含みます。

+ +

以前は、イメージマップは一般的なナビゲーションデバイスでしたが、そのパフォーマンスとアクセシビリティの影響を徹底的に検討することが重要です。

+ +

いくつかの理由からテキストリンク(CSS でスタイル付けされたもの)がイメージマップよりも好ましい。 テキストリンクは軽量でメンテナンス可能で、多くの場合 SEO に優しく、アクセシビリティのニーズをサポートしています(スクリーンリーダー、テキストのみのブラウザ、翻訳サービスなど)。

+ +

イメージマップを正しく挿入する方法

+ +

ステップ 1: 画像

+ +

どんな画像でも受け入れられるわけではありません。

+ + + +

{{htmlelement("img")}} 要素と {{htmlattrxref("alt",'img')}} テキストを使用して、常に同じ方法で画像を挿入します。 画像がナビゲーションデバイスとしてのみ存在する場合、後で {{htmlelement('area')}} 要素に適切な {{htmlattrxref("alt",'area')}} テキストを指定すると alt="" と書くことができます。

+ +

特殊な {{htmlattrxref("usemap","img")}} 属性が必要です。 イメージマップには、スペースを含まない一意の名前を考えてください。 次に、usemap 属性の値としてその名前(# が先行する)を割り当てます。

+ +
<img
+  src="image-map.png"
+  alt=""
+  usemap="#example-map-1" />
+ +

ステップ 2: ホットスポットを有効にする

+ +

このステップでは、すべてのコードを {{htmlelement('map')}} 要素内に配置します。 <map> には、上の usemap 属性で使用したのと同じマップ名の {{htmlattrxref("name","map")}} 属性だけが必要です。

+ +
<map name="example-map-1">
+
+</map>
+ +

<map> 要素の中に {{htmlelement('area')}} 要素が必要です。 <area> 要素はそれぞれが1つのホットスポットに対応します。 キーボードでのナビゲーションを直観的に保つには、<area> 要素のソースでの順序がホットスポットの視覚的順序に対応していることを確認してください。

+ +

<area> 要素は空要素ですが、次の4つの属性が必要です。

+ +
+
{{htmlattrxref('shape','area')}}
+
{{htmlattrxref('coords','area')}}
+
+

shape は、circle(円)、rect(四角形)、poly(ポリゴン)、default(デフォルト)の4つの値のいずれかをとります。 (default<area> は画像全体から、あなたが定義した他のホットスポットを除いたものです。) 選択した shape によって、coords で指定する必要がある座標情報が決まります。

+ +
    +
  • 円の場合は、中心の x 座標と y 座標を指定し、その後に半径の長さを指定します。
  • +
  • 四角形の場合は、左上角と右下角の x/y 座標を指定します。
  • +
  • ポリゴンの場合は、各角の x/y 座標を指定します(したがって、少なくとも6つの値)。
  • +
+ +

座標は CSS ピクセルで与えます。

+ +

重なり合っている場合、ソースでの順序で選ばれます。

+
+
{{htmlattrxref('href','area')}}
+
リンク先のリソースの URL。 現在の領域をどこにもリンクさせたくない場合は、この属性を空白のままにしておくことができます(空白の円を描いている場合など)。
+
{{htmlattrxref('alt','area')}}
+
+

リンクがどこにあるのか、それが何をするのかを人に伝える必須の属性。 alt テキストは、画像が利用できない場合にのみ表示されます。 アクセス可能なリンクテキストを書くためのガイドラインを参照してください。

+ +

href 属性が空白で、画像全体に既に alt 属性がある場合、alt="" と書くことができます。

+
+
+ +
<map name="example-map-1">
+  <area shape="circle" coords="200,250,25"
+    href="page-2.html" alt="circle example" />
+
+
+  <area shape="rect" coords="10, 5, 20, 15"
+    href="page-3.html" alt="rectangle example" />
+
+</map>
+ +

ステップ 3: 誰にとっても効果があることを確認する

+ +

多くのブラウザやデバイスでイメージマップを厳密にテストするまで、あなたは完了していません。 キーボードだけでリンクをたどってみてください。 画像をオフにしてみてください。

+ +

イメージマップが約 240 px より広い場合は、ウェブサイトをレスポンシブにするためにさらに調整する必要があります。 座標が同じままでは、もはや画像と一致しないので、小さな画面の場合は画像のサイズを変更するだけでは不十分です。

+ +

イメージマップを使用する必要がある場合は、Matt Stow の jQuery プラグイン(英語)を調べることができます。 また、Dudley Storey は、イメージマップエフェクトとして SVG を使用する方法(英語)と、その後にビットマップ画像用に SVG とラスターを組み合わせる方法(英語)を示しています。

+ +

より詳しく知る

+ + diff --git a/files/ja/learn/html/howto/define_terms_with_html/index.html b/files/ja/learn/html/howto/define_terms_with_html/index.html new file mode 100644 index 0000000000..4c2f87f8a2 --- /dev/null +++ b/files/ja/learn/html/howto/define_terms_with_html/index.html @@ -0,0 +1,151 @@ +--- +title: HTML で用語を定義する +slug: Learn/HTML/Howto/Define_terms_with_HTML +tags: + - Beginner + - Guide + - HTML + - Learn +translation_of: Learn/HTML/Howto/Define_terms_with_HTML +--- +
+

HTML は、インラインであろうと構造化された用語集であろうと、記述の意味を伝達するいくつかの方法を提供します。 この記事では、キーワードを定義する際に適切にマークアップする方法について説明します。

+
+ + + + + + + + + + + + +
前提条件:基本的な HTML 文書の作成方法に精通している必要があります。
目的:新しいキーワードを導入する方法と説明リストを作成する方法を学びます。
+ +

用語の意味が必要なときは、おそらくまっすぐに辞書や用語集に行くでしょう。 辞書や用語集は、キーワードを1つ以上の説明と正式に関連付けます。 この場合は次のようになります。

+ +
+
+
Blue (Adjective)
+
Of a color like the sky in a sunny day.
+ The clear blue sky
+
Of a subtle sadness, melancholy.
+ I'm feeling blue
+
+
+ +

しかし、私たちは常に次のように非公式にキーワードを定義しています。

+ +
+

Firefox は、Mozilla Foundation によって作成されたウェブブラウザです。

+
+ +

これらのユースケースに対処するために、{{Glossary("HTML")}} には説明と説明された単語をマークするための{{Glossary("tag","タグ")}}が用意されているので、読者に意味が適切に伝わるようになります。

+ +

非公式の説明をマークする方法

+ +

教科書では、キーワードが初めて出てきたときに、キーワードを太字にしてすぐに定義するのが一般的です。

+ +

私たちは HTML でもそうしていますが、HTML は視覚的なメディアではないので太字を使いません。 {{htmlelement("dfn")}} は、初めて出現するキーワードをマークするための特別な要素です。 <dfn> タグは、定義ではなく定義される単語の周りにあり、定義は段落全体で構成されています。

+ +
<p><dfn>Firefox</dfn> は、Mozilla Foundation によって作成されたウェブブラウザです。</p>
+
+ +
+

太字のもう1つの用途はコンテンツを強調することです。 太字自体は HTML の概念ではありませんが、強調を示すタグがあります。

+
+ +

特別な場合: 略語

+ +

{{htmlelement("abbr")}} で略語を特別にマークすることが最適です。 これにより、スクリーンリーダーが適切に読むことができ、すべての略語を統一的に操作できるようになります。 新しいキーワードの場合と同様に、初めて出現したときに略語を定義する必要があります。

+ +
<p>
+  <dfn><abbr>HTML</abbr> (hypertext markup language、ハイパーテキストマークアップ言語)</dfn>
+   は、ウェブ上のドキュメントを構造化するために使用される記述言語です。
+</p>
+ +
+

HTML 仕様は実際には略語を拡張するために title 属性を用意しています(英語)。 ただし、これはインライン展開を提供するための許容可能な代替方法ではありません。 title の内容は、マウスを使用していない限り、ユーザーには完全に隠されています。 この仕様も同様にこれを認めています(英語)。

+
+ +

アクセシビリティの向上

+ +

{{HTMLElement('dfn')}} は定義されたキーワードをマークし、現在の段落がキーワードを定義していることを示します。 言い換えれば、<dfn> 要素とそのコンテナの間に暗黙の関係があります。 より正式な関係を望む場合、または定義が段落全体ではなく1つの文で構成されている場合は、aria-describedby 属性を使用して、より正式に定義に関連付けることができます。

+ +
<p>
+  <span id="ff">
+    <dfn aria-describedby="ff">Firefox</dfn>
+    は、Mozilla Foundation によって作成されたウェブブラウザです。
+  </span>
+  <a href="http://www.mozilla.org">mozilla.org</a> からダウンロードできます。
+</p>
+ +

支援技術は、この属性を使用して、指定された用語の代替テキストを見つけることができます。 <dfn> 要素だけでなく、キーワードを囲む任意のタグで aria-describedby を使用して定義できます。 aria-describedby は、説明を含む要素の {{htmlattrxref('id')}} を参照します。

+ +

説明リストを作成する方法

+ +

説明リストは、用語とそれに対応する説明のリスト(例: 定義リスト、辞書エントリ、よくある質問、およびキーと値のペア)です。

+ +
+

説明リストは、対話が話し手を直接記述しないため、対話をマークアップするのには適していません(英語)。 ここには、対話をマークアップするための推奨事項(英語)があります。

+
+ +

説明された用語は、{{htmlelement("dt")}} 要素内にあります。 対応する説明は直ちに続き、1つ以上の {{htmlelement("dd")}} 要素に含まれています。 説明リスト全体を {{htmlelement("dl")}} 要素で囲みます。

+ +

簡単な例

+ +

ここでは簡単な例として、食べ物と飲み物の種類を説明します。

+ +
<dl>
+  <dt>jambalaya</dt>
+    <dd>
+      rice-based entree typically containing chicken,
+      sausage, seafood, and spices
+    </dd>
+
+  <dt>sukiyaki</dt>
+    <dd>
+      Japanese specialty consisting of thinly sliced meat,
+      vegetables, and noodles, cooked in sake and soy sauce
+    </dd>
+
+  <dt>chianti</dt>
+    <dd>
+      dry Italian red wine originating in Tuscany
+    </dd>
+</dl>
+
+ +
+

ご覧のとおり、基本パターンは <dt> の用語を <dd> の説明で置き換えることです。 行内に2つ以上の用語が存在する場合は、以下の説明はそれらのすべてに適用されます。 行内に2つ以上の説明が存在する場合、それらはすべて最後に指定された用語に適用されます。

+
+ +

視覚的な出力を改善する

+ +

グラフィカルブラウザに前述のリストが表示される方法は次のとおりです。

+ +

{{EmbedLiveSample("A_simple_example", 600, 180)}}

+ +

キーワードをより際立たせたい場合は、それらを強調することができます。 HTML は視覚的な媒体ではないことを忘れないでください。 すべての視覚効果に対して {{glossary("CSS")}} が必要です。 CSS の {{cssxref("font-weight")}} プロパティは、ここで必要なものです。

+ +
dt {
+  font-weight: bold;
+}
+
+ +

これにより、以下のわずかに読みやすい結果が生成されます。

+ +

{{EmbedLiveSample("How_to_build_a_description_list", 600, 180)}}

+ +

より詳しく知る

+ + diff --git a/files/ja/learn/html/howto/index.html b/files/ja/learn/html/howto/index.html new file mode 100644 index 0000000000..a7e7f54478 --- /dev/null +++ b/files/ja/learn/html/howto/index.html @@ -0,0 +1,141 @@ +--- +title: 一般的な問題解決に HTML を使う +slug: Learn/HTML/Howto +tags: + - CodingScripting + - HTML +translation_of: Learn/HTML/Howto +--- +
{{LearnSidebar}}
+ +

下記のリンクは、日常の解決すべき問題を HTML を使って解決する解決法を指しています。

+ +
+
+

基本構造

+ +

HTML の最も基本的な適用は文書の構造化です。HTML に慣れていないならここから始めるべきです。

+ + + +

基本的なテキストレベルのセマンティクス

+ +

HTML は文書の意味的な情報を提供することに特化しているので、HTML 文書内でメッセージをうまく伝える方法についてあなたが抱えるかもしれない多くの質問に答えます。

+ + +
+ +
+ + +

HTML のための主な理由は {{Glossary("hyperlink", "ハイパーリンク")}}, を使ってナビゲーションを簡単にすることで、それは色々な方法で使われます:

+ + + +

画像とマルチメディア

+ + + +

スクリプトとスタイリング

+ +

HTML は文書の構造だけを解決します。表現の問題は {{glossary("CSS")}} を使うか、ページをインタラクティブにしたいならスクリプトを使います。

+ + + +

埋め込みコンテンツ

+ + +
+
+ +

あまりない、または上級の問題

+ +

基本を超えると、HTML はとてもリッチで複雑な問題を解決する高度な機能を提供します。この記事は直面するかもしれないあまりないユースケースに取り組むのに役立ちます。

+ +
+
+

フォーム

+ +

フォームは、Web ページから Web サーバにデータを送信するために作成された複雑な HTML 構造です。完全な専用ガイドに目を通すことをお勧めします。ここから始めましょう。

+ + + +

表の情報

+ +

表形式データという情報は、行と列のある表で整理する必要があります。これは最も複雑な HTML 構造の1つで、習得するのは簡単ではありません。

+ + + +

データ表現

+ + +
+ +
+

上級テキストセマンティクス

+ + + +

上級の画像やマルチメディア

+ + + +

国際化

+ +

HTML は単一言語ではありません。一般的な国際化の問題を処理するためのツールを提供します。

+ + + +

パフォーマンス

+ + +
+
+ +

  

diff --git a/files/ja/learn/html/howto/use_data_attributes/index.html b/files/ja/learn/html/howto/use_data_attributes/index.html new file mode 100644 index 0000000000..fdcaf2ade1 --- /dev/null +++ b/files/ja/learn/html/howto/use_data_attributes/index.html @@ -0,0 +1,82 @@ +--- +title: データ属性の使用 +slug: Learn/HTML/Howto/Use_data_attributes +tags: + - HTML + - HTML5 + - ウェブ + - ガイド + - 例 + - 独自データ属性 +translation_of: Learn/HTML/Howto/Use_data_attributes +--- +
{{LearnSidebar}}
+ +

HTML5 は、特定の要素に関連付ける必要があるが、定義済みの意味を持つ必要のないデータに対する拡張性を念頭に置いて設計されています。 data-* 属性により、標準外の属性、 DOM の追加プロパティ、 {{domxref("Node.setUserData()")}} のような特殊な方法に頼らずに、標準的な意味のある HTML 要素に追加情報を格納することができます。

+ +

HTML の構文

+ +

構文は単純です。あらゆる要素上で、名前が data- で始まるあらゆる属性がデータ属性です。例えば、記事 (article) があり、視覚表現を行わない追加情報を格納したいとします。 data 属性を使用するとこれだけです。

+ +
<article
+  id="electric-cars"
+  data-columns="3"
+  data-index-number="12314"
+  data-parent="cars">
+...
+</article>
+ +

JavaScript からのアクセス

+ +

JavaScript でこれらの属性の値を読み出すことも、とても簡単です。 {{domxref("Element.getAttribute", "getAttribute()")}} で完全な HTML での名前を使用して読むこともできますが、もっと簡単な方法が標準で定義されています。 {{domxref("HTMLElement.dataset", "dataset")}} プロパティを通して {{domxref("DOMStringMap")}} で読み出すことができます。

+ +

dataset オブジェクトを通して data 属性を取得するには、属性名の data- より後の部分を使用して取得します (なお、ダッシュは camelCase に変換されます)。

+ +
const article = document.getElementById('electric-cars');
+
+article.dataset.columns // "3"
+article.dataset.indexNumber // "12314"
+article.dataset.parent // "cars"
+ +

それぞれのプロパティは文字列であり、読み書きができます。上記の場合、 article.dataset.columns = 5 を設定すると、その属性が "5" に変わります。

+ +

CSS からのアクセス

+ +

データ属性はプレーンな HTML 属性であるため、CSS からもアクセスできることに注意してください。 例えば、記事の親データを表示するには、次のように {{cssxref("attr")}} 関数を使用して CSS で生成したコンテンツを使用できます。

+ +
article::before {
+  content: attr(data-parent);
+}
+ +

CSS の属性セレクタを使用して、次のようにデータに応じてスタイルを変更することもできます。

+ +
article[data-columns='3'] {
+  width: 400px;
+}
+article[data-columns='4'] {
+  width: 600px;
+}
+ +

この JSBin の例では、これらすべてが一緒に機能していることがわかります。

+ +

データ属性を保存して、ゲームのスコアなど、絶えず変化する情報を含めることもできます。 ここで CSS セレクタと JavaScript アクセスを使用すると、独自の表示ルーチンを作成することなく、気の利いたエフェクトを作成できます。 生成したコンテンツと CSS トランジション(transition、遷移)を使用した例については、このスクリーンキャストを参照してください(JSBin の例)。

+ +

データ値は文字列です。 スタイリングを有効にするには、セレクタで数値を引用符で囲む必要があります。

+ +

問題

+ +

支援技術がアクセスできない可能性があるため、データ属性に表示およびアクセス可能なコンテンツを保存しないでください。 さらに、検索クローラーはデータ属性の値にインデックスを付けない場合があります。

+ +

考慮すべき主な問題は、Internet Explorer のサポートとパフォーマンスです。 Internet Explorer 11 以降は標準のサポートを提供しますが、以前のバージョンはすべて dataset をサポートしていません(英語)。 IE 10 以下をサポートするには、代わりに {{domxref("Element.getAttribute", "getAttribute()")}} を使用してデータ属性にアクセスする必要があります。 また、通常の JS オブジェクトにこのデータを保存する場合と比較して、データ属性の読み取りパフォーマンス(英語)が低下します。

+ +

ただし、カスタム要素に関連付けられたメタデータの場合、それらは優れたソリューションです。

+ +

Firefox 49.0.2(およびおそらくそれに前後したバージョン)では、1022 文字を超えるデータ属性は Javascript(EcmaScript 4)によって読み取られません。

+ +

関連情報

+ + diff --git a/files/ja/learn/html/howto/use_javascript_within_a_webpage/index.html b/files/ja/learn/html/howto/use_javascript_within_a_webpage/index.html new file mode 100644 index 0000000000..598818ab3d --- /dev/null +++ b/files/ja/learn/html/howto/use_javascript_within_a_webpage/index.html @@ -0,0 +1,107 @@ +--- +title: ウェブページで JavaScript を使う方法 +slug: Learn/HTML/Howto/Use_JavaScript_within_a_webpage +tags: + - Beginner + - HTML + - JavaScript + - OpenPractices +translation_of: Learn/HTML/Howto/Use_JavaScript_within_a_webpage +--- +
+

Take your webpages to the next level by harnessing JavaScript. Learn in this article how to trigger JavaScript right from your HTML documents.

+
+ + + + + + + + + + + + +
前提条件:基本的な HTML 文書の作成方法を習熟している必要があります。
目的:HTMLファイルからJavaScript を起動する方法と、JavaScript にアクセスできるようにする最も良い習慣を学ぶ。
+ +

JavaScript について

+ +

{{Glossary("JavaScript")}} はウェブページをインタラクティブにするための、主にクライアントサイドで使われるプログラミング言語です。 JavaScript を使わなくてもすばらしいウェブページを作ることができますが、JavaScript は全く新しいレベルの可能性を開きます。

+ +
+

In this article we're going over the HTML code you need to make JavaScript take effect. If you want to learn JavaScript itself, you can start with our JavaScript basics article. If you already know something about JavaScript or if you have a background with other プログラミング言語s, we suggest you jump directly into our JavaScript Guide.

+
+ +

HTML から JavaScript を起動する方法

+ +

Within a browser, JavaScript doesn't do anything by itself. You run JavaScript from inside your HTML webpages. To call JavaScript code from within HTML, you need the {{htmlelement("script")}} element. There are two ways to use script, depending on whether you're linking to an external script or embedding a script right in your webpage.

+ +

Linking an external script

+ +

Usually, you'll be writing scripts in their own .js files. If you want to execute a .js script from your webpage, just use {{HTMLElement ('script')}} with an src attribute pointing to the script file, using its URL:

+ +
<script src="path/to/my/script.js"></script>
+ +
+

Pro tip: In many cases it's a good idea to put your {{HTMLElement('script')}} elements at the end of your HTML document (right before the </body> closing {{Glossary("tag")}}).

+ +

Loading and running scripts is blocking and immediate. That means, every time the browser comes across a <script> element, the browser stops reading the HTML and instead loads and runs the script. The browser continues reading and rendering the HTML code after running the script.

+ +

When you put {{htmlelement("script")}} elements at the end, you don't run the risk of manipulating {{Glossary("DOM")}} nodes that are not yet initialized. In addition, your webpages will finish displaying faster.

+
+ +

Writing JavaScript within HTML

+ +

You may also add JavaScript code between <script> tags rather than providing an src attribute.

+ +
<script>
+window.addEventListener('load', function () {
+  console.log('This function is executed once the page is fully loaded');
+});
+</script>
+ +

That's convenient when you just need a small bit of JavaScript, but if you keep JavaScript in separate files you'll find it easier to

+ + + +

Use scripting accessibly

+ +

Accessibility is a major issue in any software development. JavaScript can make your website more accessible if you use it wisely, or it can become a disaster if you use scripting without care. To make JavaScript work in your favor, it's worth knowing about certain best practices for adding JavaScript:

+ + + +

Learn more

+ + diff --git a/files/ja/learn/html/index.html b/files/ja/learn/html/index.html new file mode 100644 index 0000000000..fa11f9e2b9 --- /dev/null +++ b/files/ja/learn/html/index.html @@ -0,0 +1,61 @@ +--- +title: 'HTML の学習: ガイドとチュートリアル' +slug: Learn/HTML +tags: + - Beginner + - Guide + - HTML + - Intro + - Learn + - Topic + - ガイド + - トピック + - 初心者 + - 学習 + - 導入 +translation_of: Learn/HTML +--- +
{{LearnSidebar}}
+ +

ウェブサイトを構築するためには、ウェブページの構造を定義するための基本的な技術である {{Glossary('HTML')}} 言語を知っておくべきでしょう。 HTML はウェブコンテンツをどのよう解釈するべきかを特定するために使用します。段落、リスト、見出し、リンク、画像、マルチメディアプレーヤー、フォーム、又は他の数多くの要素の一つ、又はユーザーが定義した新しい要素などです。

+ +

学習経路

+ +

HTML 学習を学びの旅の起点にすることが理想的です。HTML 概論を読んでみましょう。さらに学びたいと思ったなら、次は以下のような内容に移ることになるでしょう。

+ + + +

このトピックを開始する前に、最低限コンピュータを利用することに慣れておくべきでしょう。また、ウェブを受け手の側から、利用すること(つまり、ただ見たり、コンテンツを消費したりすること)にも慣れておくべきでしょう。また基本的な作業環境のセットアップもしておくべきでしょう。細かい話は、 基本的なソフトウェアをインストールするや、 ファイルを扱うに書かれています。今あげた二つの内容は、Web 入門という初心者向けの章に含まれています。

+ +

今回のトピックに入る前に、 ウェブ入門を一読しておくことをお薦めします。けれども、絶対にそうしておく必要があるというわけではありません。 HTML の基礎の記事でカバーされている大体の内容は、 HTML 概論の記事でもカバーされています。ただこちらのほうが、より詳細な記事になっています。

+ +

モジュール

+ +

このトピックは、以下の内容を含んでいます。そして、それらは、学んでいくのに好ましい順番で並んでいます。上から順番に学んでいくのが望ましいでしょう。

+ +
+
HTML 概論
+
この章では、土台作りをします。ここで、あなたはHTMLの重要な概念や構文に慣れたり、HTML を文章に適用していくのを見たり、どうやってハイパーリンクができるのか、HTML がウェブページを作るためにどのように利用されるのかを学ぶことになります。
+
マルチメディアと埋め込み
+
この章では、 HTML を使ってどうやったら、あなたのウェブページにマルチメディアを導入できるかを学びます。画像を取り込むためのいくつかのやり方、ビデオや音声、さらに、ウェブページそのものを埋め込む方法もここで学びます。
+
HTML 表
+
ウェブページ上の表形式のデータを理解しやすく{{glossary("Accessibility", "アクセスしやすい")}}方法で表現することは難しいことです。このモジュールでは、基本的な表のマークアップと、キャプションやサマリーの実装などのより複雑な機能をカバーしています。
+
HTML フォーム
+
フォームはウェブのとても重要な部分です。これらはウェブサイトとのやりとりに必要な多くの機能を提供します。登録とログイン、フィードバックの送信、商品の購入などが含まれます。このモジュールでは、フォームのクライアント側部分の作成を始めます。
+
+ +

よくある HTML の問題の解決

+ +

共通の問題解決に HTML を使う 「基本的な問題を解決するために HTML を使う」では、ウェブページを作った時に出てくる一般的な問題をどうやって解決するかを説明するためのコンテンツのセクションへのリンクを提示します。タイトルの扱い方や、画像やビデオを加えたり、コンテンツを強調したり、基本的なフォームを作ったりします。

+ +

関連情報

+ +
+
+
MDN 上の HTML (HyperText Markup Language) .
+
MDN における HTML に関する文書の入口で、詳細な要素と属性のリファレンスがあります。例えば、要素がが持っている属性は何か、属性の持つ値は何かなどを知りたかったら、これは最適な場所です。
+
+
diff --git a/files/ja/learn/html/introduction_to_html/advanced_text_formatting/index.html b/files/ja/learn/html/introduction_to_html/advanced_text_formatting/index.html new file mode 100644 index 0000000000..0ceb370e9e --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/advanced_text_formatting/index.html @@ -0,0 +1,674 @@ +--- +title: 高度なテキスト処理 +slug: Learn/HTML/Introduction_to_HTML/Advanced_text_formatting +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - Learn + - Text + - abbreviation + - description list + - quote + - semantic +translation_of: Learn/HTML/Introduction_to_HTML/Advanced_text_formatting +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML")}}
+ +

テキストの書式設定のための HTML には他にも多くの要素がありますが、これは HTML テキストの基礎 には書かれていません。この記事で説明されている要素はあまり知られていませんが、知っていると役に立ちます。(これはまだいかなる意味でも完全なリストではありません)。ここでは、注釈、説明リスト、コンピューターコードとその他の関連テキスト、下付き文字と上付き文字、連絡先情報などのマーキングについて学習します。

+ + + + + + + + + + + + +
前提条件:HTML入門に載っている、基本的なHTMLに精通していること。HTML テキストの基礎に載っている、HTMLテキストフォーマット。
目的:高度な意味付け機能をマークアップするための、あまり知られていないHTML要素を学ぶ。
+ +

説明リスト

+ +

HTML テキストの基礎では、HTMLで 基本的なリストをマークアップする方法を見てきました、しかしたまに出てくる第3のリスト — 説明リスト — については触れていませんでした。このリストの目的は、項目とそれに関連する説明を一緒にマークアップすることで、用語の定義や、質問と回答などに使います。用語の定義の例を見てみましょう:

+ +
soliloquy
+In drama, where a character speaks to themselves, representing their inner thoughts or feelings and in the process relaying them to the audience (but not to other characters.)
+monologue
+In drama, where a character speaks their thoughts out loud to share them with the audience and any other characters present.
+aside
+In drama, where a character shares a comment only with the audience for humorous or dramatic effect. This is usually a feeling, thought or piece of additional background information
+ +

説明リストは他の種類のリストと違うラッパーを使います — {{htmlelement("dl")}} です; それぞれの用語が {{htmlelement("dt")}} (description term; 説明用語) 要素で囲まれて、それぞれの説明は {{htmlelement("dd")}} (description definition; 説明定義) 要素で囲まれます。例のマークアップを完了しましょう:

+ +
<dl>
+  <dt>独白( soliloquy )</dt>
+  <dd>ドラマでは、登場人物が自分自身にしゃべりかけ、内なる考えや感情や、そうなった過程を(他の登場人物ではなく)観客に対して表現します。</dd>
+  <dt>独白( monologue)</dt>
+  <dd>ドラマで、登場人物が自分の考えを観客や他の登場人物に伝わるように喋ります。</dd>
+  <dt>ひそひそ話</dt>
+  <dd>ドラマで、登場人物が観客のみに対し、ユーモアやドラマチックな効果を狙ってコメントをします。これは通常は感情や、考えや、追加の背景情報です。</dd>
+</dl>
+ +

ブラウザーデフォルトのスタイルでは、説明を用語からいくらかインデントします。MDN のスタイルはこの慣習にほぼ従いますが、用語を太字にします。

+ +
+
独白 (soliloquy)
+
ドラマでは、登場人物が自分自身にしゃべりかけ、内なる考えや感情や、そうなった過程を(他の登場人物ではなく)観客に対して表現します。
+
独白 (monologue)
+
ドラマで、登場人物が自分の考えを観客や他の登場人物に伝わるように喋ります。
+
ひそひそ話
+
ドラマで、登場人物が観客のみに対し、ユーモアやドラマチックな効果を狙ってコメントをします。これは通常は感情や、考えや、追加の背景情報です。
+
+ +

注意として、単独の用語に複数の説明をつけるのも許されます、例えば:

+ +
+
余談
+
ドラマで、登場人物が観客のみに対し、ユーモアやドラマチックな効果を狙ってコメントをします。これは通常は感情や、考えや、追加の背景情報です。
+
文章では、現在のトピックに関連するが、主な流れには直接くっつけずに脇に置かれるコンテンツの節 (しばしば脇の囲みの中に置かれる)。
+
+ +

アクティブ学習: 定義をマークアップする

+ +

では実際に説明リストを使ってみましょう。ここでは以下の入力フィールドの生テキストをマークアップし、説明リストとして表示されるようにします。あなたがお好きな用語と説明を使って試してみることもできます。

+ +

もし何かミスをしても、リセットボタンでいつでも元に戻すことができます。詰まってしまったら「Show solution」ボタンを押して解答を見ましょう。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 350, "", "", "hide-codepen-jsfiddle") }}

+ +

引用

+ +

HTML には引用をマークアップするための機能もあります。どちらの要素を使用するかは、ブロックとインラインのどちらの引用をマークアップするかによって異なります。

+ +

ブロッククォート

+ +

ブロックレベルのコンテンツのセクション (段落、複数段落、リストなど) が他の場所から引用されている場合は、それを表すために {{htmlelement("blockquote")}} 要素で囲む必要があります。{{htmlattrxref("cite","blockquote")}} 属性内に引用のソースを指す URL を含めます。たとえば、次のマークアップは MDN の <blockquote> 要素ページから取得されます。

+ +
<p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block
+Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
+ +

これをブロッククォートにするには、次のようにします。

+ +
<blockquote cite="https://developer.mozilla.org/ja/docs/Web/HTML/Element/blockquote">
+  <p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block
+  Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
+</blockquote>
+ +

ブラウザのデフォルトのスタイル設定では、これがインデントされた段落として、それが引用であることを示すインジケータとして表示されます。MDN はこれを行いますが、さらにいくつかのスタイルを追加します。

+ +
+

HTML <blockquote> 要素 (または HTML Block Quotation 要素) は、囲まれたテキストが拡張引用符であることを示します。

+
+ +

インラインクォート

+ +

インラインの引用は、{{htmlelement("q")}} 要素を使用することを除いて、まったく同じ方法で機能します。例えば、以下のマークアップには MDN の <q> ページからの引用が含まれています。

+ +
<p>The quote element — <code>&lt;q&gt;</code> — is <q cite="https://developer.mozilla.org/ja/docs/Web/HTML/Element/q">intended
+for short quotations that don't require paragraph breaks.</q></p>
+ +
ブラウザーのデフォルトのスタイル設定では、これは引用符で囲まれた通常のテキストとしてレンダリングされ、次のようになります。
+ +
+ +

quote 要素 — <q> — は "段落区切りを必要としない短い引用のためのもの" です。

+ +

引用元

+ +

{{htmlattrxref("cite","blockquote")}} 属性の内容は役に立ちそうに見えますが、残念ながらブラウザ、スクリーンリーダーなどはこれについてあまり機能しません。 JavaScript または CSS を使用して独自のソリューションを作成しない限り、ブラウザに引用元の内容を表示させる方法はありません。引用元のソースをページ上で利用可能にしたい場合は、それをマークアップするためのより良い方法は、{{htmlelement("cite")}} 要素を quote 要素の隣 (または内側) に置くことです。これはまさに引用したリソースのタイトル — 例えば本の名前 — を含むことを意味しますが、とにかく、 <cite> 内のテキストを何らかの方法で引用ソースにリンクできない理由はありません。

+ +
<p>According to the <a href="https://developer.mozilla.org/ja/docs/Web/HTML/Element/blockquote">
+<cite>MDN blockquote page</cite></a>:
+</p>
+
+<blockquote cite="https://developer.mozilla.org/ja/docs/Web/HTML/Element/blockquote">
+  <p>The <strong>HTML <code>&lt;blockquote&gt;</code> Element</strong> (or <em>HTML Block
+  Quotation Element</em>) indicates that the enclosed text is an extended quotation.</p>
+</blockquote>
+
+<p>The quote element — <code>&lt;q&gt;</code> — is <q cite="https://developer.mozilla.org/ja/docs/Web/HTML/Element/q">intended
+for short quotations that don't require paragraph breaks.</q> -- <a href="https://developer.mozilla.org/ja/docs/Web/HTML/Element/q">
+<cite>MDN q page</cite></a>.</p>
+ +

引用は、デフォルトではイタリック体で表示されています。あなたは quotations.html の例で動作しているこのコードを見ることができます。

+ +

アクティブラーニング: 誰がそう言ったの?

+ +

もう一つのアクティブラーニングの時間です! この例では、あなたにお願いします。

+ +
    +
  1. 中央の段落を cite 属性を含むブロッククォートにします。
  2. +
  3. 3番目の段落の一部を、cite 属性を含むインライン引用に変換します。
  4. +
  5. 各リンクに <cite> 要素を含めます。
  6. +
+ +

必要な引用元は以下のとおりです。

+ + + +

間違えた場合は、リセットボタンを使用していつでもリセットできます。本当に動けなくなったら、Show solution ボタンを押して答えを見てください。

+ + + +

{{ EmbedLiveSample('Playable_code_2', 700, 450, "", "", "hide-codepen-jsfiddle") }}

+ +

略語

+ +

Web を見回すときに見かけるもう1つのかなり一般的な要素は {{htmlelement("abbr")}} です — これは略語や頭字語を囲み、その用語の完全な展開 (これは{{htmlattrxref("title")}} 属性内に含まれる) を提供するために使用されます。例をいくつか見てみましょう。

+ +
<p>We use <abbr title="Hypertext Markup Language">HTML</abbr> to structure our web documents.</p>
+
+<p>I think <abbr title="Reverend">Rev.</abbr> Green did it in the kitchen with the chainsaw.</p>
+ +

これらは次のようなものに見えます (用語が上に置かれると展開はツールチップに表示されます)。

+ +

We use HTML to structure our web documents.

+ +

I think Rev. Green did it in the kitchen with the chainsaw.

+ +
+

: 別の要素だと、{{htmlelement("acronym")}} があります。これは基本的に <abbr> と同じことを行い、特に省略語ではなく頭字語を対象としていました。しかしこれは廃止され、ブラウザでは <abbr> ほどにはサポートされていませんでしたし、同じような機能を備えているため、両方を使用するのは無意味です。 代わりに <abbr> を使用してください。

+
+ +

アクティブラーニング: 略語をマークアップする

+ +

このシンプルなアクティブラーニング課題では、単に略語をマークアップしてください。以下のサンプルを使用するか、またはあなた自身のものと交換することができます。

+ + + +

{{ EmbedLiveSample('Playable_code_3', 700, 300, "", "", "hide-codepen-jsfiddle") }}

+ +

詳細な連絡先をマークアップする

+ +

HTML には連絡先の詳細をマークアップするための要素 — {{htmlelement("address")}} があります。これは単に連絡先の詳細を囲むだけです。例えば:

+ +
<address>
+  <p>Chris Mills, Manchester, The Grim North, UK</p>
+</address>
+ +

ただし {{htmlelement("address")}} 要素は、HTML 文書を作成した人の連絡先の詳細をマークアップするためのものであり、住所ではありません。マークアップが書かれている文書を書いたのがクリスならば、上記は大丈夫でしょう。このようなものでも大丈夫でしょう:

+ +
<address>
+  <p>Page written by <a href="../authors/chris-mills/">Chris Mills</a>.</p>
+</address>
+ +

上付きと下付き

+ +

日付、化学式、数式などの項目をマークアップするときには、上付き文字と下付き文字を使用する必要がある場合があります。{{htmlelement("sup")}} と {{htmlelement("sub")}} 要素がこの仕事を処理します。例えば:

+ +
<p>My birthday is on the 25<sup>th</sup> of May 2001.</p>
+<p>Caffeine's chemical formula is C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>.</p>
+<p>If x<sup>2</sup> is 9, x must equal 3 or -3.</p>
+ +

このコードの出力は次のようになります。

+ +

My birthday is on the 25th of May 2001.

+ +

Caffeine's chemical formula is C8H10N4O2.

+ +

If x2 is 9, x must equal 3 or -3.

+ +

コンピューターコードを表現する

+ +

HTML を使用してコンピュータコードをマークアップするために利用可能な要素がいくつかあります。

+ + + +

いくつか例を見てみましょう。これら (other-semantics.html サンプルファイルのコピーを入手してください) を試してみるべきです:

+ +
<pre><code>var para = document.querySelector('p');
+
+para.onclick = function() {
+  alert('Owww, stop poking me!');
+}</code></pre>
+
+<p>You shouldn't use presentational elements like <code>&lt;font&gt;</code> and <code>&lt;center&gt;</code>.</p>
+
+<p>In the above JavaScript example, <var>para</var> represents a paragraph element.</p>
+
+
+<p>Select all the text with <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd>.</p>
+
+<pre>$ <kbd>ping mozilla.org</kbd>
+<samp>PING mozilla.org (63.245.215.20): 56 data bytes
+64 bytes from 63.245.215.20: icmp_seq=0 ttl=40 time=158.233 ms</samp></pre>
+ +

上記のコードは次のようになります。

+ +

{{EmbedLiveSample('Representing_computer_code','100%',300, "", "", "hide-codepen-jsfiddle") }}

+ +

日付と時刻をマークアップする

+ +

HTML には、時間と日付を機械可読形式でマークアップするための {{htmlelement("time")}} 要素もあります。例えば:

+ +
<time datetime="2016-01-20">20 January 2016</time>
+ +

これはなぜ便利でしょうか? 人間が日付を書き留める方法はたくさんあります。上記の日付は次のように書くことができます。

+ + + +

しかしこれらの異なる形式はコンピュータでは容易には認識できません。ページ内のすべてのイベントの日付を自動的に取得してカレンダーに挿入する場合はどうなりますか。{{htmlelement("time")}} 要素を使用すると、この目的のために、明確で機械可読な日時を付けることができます。

+ +

上記の基本的な例は単純な機械可読な日付を提供するだけですが、可能な他の多くのオプションがあります。例えば:

+ +
<!-- Standard simple date -->
+<time datetime="2016-01-20">20 January 2016</time>
+<!-- Just year and month -->
+<time datetime="2016-01">January 2016</time>
+<!-- Just month and day -->
+<time datetime="01-20">20 January</time>
+<!-- Just time, hours and minutes -->
+<time datetime="19:30">19:30</time>
+<!-- You can do seconds and milliseconds too! -->
+<time datetime="19:30:01.856">19:30:01.856</time>
+<!-- Date and time -->
+<time datetime="2016-01-20T19:30">7.30pm, 20 January 2016</time>
+<!-- Date and time with timezone offset-->
+<time datetime="2016-01-20T19:30+01:00">7.30pm, 20 January 2016 is 8.30pm in France</time>
+<!-- Calling out a specific week number-->
+<time datetime="2016-W04">The fourth week of 2016</time>
+ +

まとめ

+ +

これで HTML テキストのセマンティクスに関する学習が終わりました。このコースで見たことが HTML テキスト要素の完全なリストではないことに注意してください — 私たちは必要不可欠なもの、そしてあなたがどこかで見るであろう、あるいは少なくとも面白いと思うかもしれないより一般的なものの一部をカバーしたいと思いました。もっと多くの HTML 要素を見つけるために、HTML 要素のリファレンス (インラインテキストセマンティクスセクションは始めるのに素晴らしい場所でしょう) を参照することができます。次回の記事では、HTML 文書のさまざまな部分を構造化するために使用する HTML 要素について説明します。

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/introduction_to_html/creating_hyperlinks/index.html b/files/ja/learn/html/introduction_to_html/creating_hyperlinks/index.html new file mode 100644 index 0000000000..34d846cd4c --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/creating_hyperlinks/index.html @@ -0,0 +1,338 @@ +--- +title: ハイパーリンクの作成 +slug: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - Learn + - Links + - Title + - absolute + - hyperlinks + - relative + - urls +translation_of: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}
+ +

ハイパーリンクとは本当に重要なものです— ウェブが網状組織を構成しているのもハイパーリンクのおかげです。この記事ではリンクを作るために必要な構文を示し、リンクに関するベストプラクティスについて議論します。

+ + + + + + + + + + + + +
前提知識:HTML 入門に載っている、基本的な HTML に精通していること。HTML テキストの基礎に載っている、HTML テキストフォーマット。
目的:ハイパーリンクを効率的に実装する方法、複数のファイルを互いにリンクする方法を学ぶ。
+ + + +

ハイパーリンクは Web が提供する最も刺激的なイノベーションです。Web の始まりから機能していましたが、Web を Web たるものにするものです — 文書から別の文書 (やリソース) へとリンクできたり、文書の特定の部分にリンクできたり、簡単な Web アドレスからアプリを利用できるようになります (ネイティブアプリと比較して、そちらはインストールが必要なだけです)。あらゆる Web コンテンツはリンクに変換できて、クリック (またはその他の有効化) した時に Web ブラウザーは別の Web アドレス ({{glossary("URL")}}) に移動します。

+ +
+

メモ: URL は HTML ファイルや、テキストファイル、画像、テキスト文書、動画やオーディオファイルや、その他 Web に載せられるものを指すことができます。Web ブラウザーにそのファイルの扱い方・表示法がわからない場合、それを本当に開きたいのか聞く (この場合ファイルを開いたり扱ったりする義務は適切な端末上のネイティブアプリに渡されます) か、ファイルをダウンロードします (この場合あとで処理することができます)。

+
+ +

例えば、BBC のホームページでは、複数のニュース記事だけでなく、色々なサイトのエリアを指すリンク (ナビゲーション機能) や、ログイン/登録ページ (ユーザーツール) その他多数のリンクがあります。

+ +

bbc.co.uk のフロントページで、たくさんのニュース項目と、ナビゲーションメニューの機能を表示しています

+ + + +

基本的なリンクは、リンクにしたいテキスト (またはその他のコンテンツ、{{anch("Block level links")}} を参照) を {{htmlelement("a")}} 要素の中に囲むことで作成し、{{htmlattrxref("href", "a")}} (ハイパーテキスト参照またはターゲットとも) にリンク先にしたい Web アドレスを入れます。

+ +
<p>I'm creating a link to
+<a href="https://www.mozilla.org/ja/">the Mozilla homepage</a>.
+</p>
+ +

これは以下のような結果をもたらします。

+ +

I'm creating a link to the Mozilla homepage.

+ +

title 属性による補足情報の追加

+ +

あなたのリンクに追加したいかもしれない別の属性は title です。これには、ページに含まれる情報の種類や注意すべき事項など、リンクに関する補足的な有用な情報が含まれています。 例えば、

+ +
<p>I'm creating a link to
+<a href="https://www.mozilla.org/ja/"
+   title="The best place to find more information about Mozilla's
+          mission and how to contribute">the Mozilla homepage</a>.
+</p>
+ +

これにより、次のような結果が得られます (リンクがホバーされるとタイトルがツールチップとして表示されます)。

+ +

I'm creating a link to the Mozilla homepage.

+ +
+

メモ: リンクのタイトルはマウスのホバーでのみ表示されます。つまり、Web ページをナビゲートするためにキーボードコントロールに頼る人々はタイトル情報にアクセスするのが困難になります。タイトルの情報がページの使いやすさにとって本当に重要な場合は、通常のテキストに入れるなどして、すべてのユーザーがアクセスできる方法で表示する必要があります。

+
+ + + +

アクティブラーニングタイム:ローカルのコードエディタを使用して HTML ドキュメントを作成してください (私たちの入門用テンプレートでうまくいくでしょう)。

+ + + + + +

前述したように、ブロックレベル要素であっても、あらゆるコンテンツをリンクに変えることができます。リンクに変換したい画像がある場合は、その画像を <a></a> タグの間に配置することで実現できます。

+ +
<a href="https://www.mozilla.org/ja/">
+  <img src="mozilla-image.png" alt="mozilla logo that links to the mozilla homepage">
+</a>
+ +
+

メモ: 今後の記事では Web 上での画像の使用についてさらに多くのことがわかります。

+
+ +

URL とパスに関する簡単な入門

+ +

リンク先を完全に理解するには、URL とファイルパスを理解する必要があります。このセクションでは、これを達成するために必要な情報を提供します。

+ +

URL (Uniform Resource Locator) は、Web 上のどこにあるのかを定義するテキストの文字列です。たとえば、Mozilla の日本語のホームページは https://www.mozilla.org/ja/ にあります。

+ +

URL はファイルを見つけるためにパスを使います。パスはファイルシステム内の目的のファイルが存在する場所を指定します。ディレクトリー構造の簡単な例を見てみましょう (creating-hyperlinks ディレクトリーを参照してください)。

+ +

A simple directory structure. The parent directory is called creating-hyperlinks and contains two files called index.html and contacts.html, and two directories called projects and pdfs, which contain an index.html and a project-brief.pdf file, respectively

+ +

このディレクトリー構造の rootcreating-hyperlinks と呼ばれます。Web サイトを使用してローカルで作業する場合は、サイト全体が入る 1 つのディレクトリーがあります。ルート内には、index.html ファイルと contacts.html があります。実際の Web サイトでは、index.html が私たちのホームページまたはランディングページ (Web サイトまたは Web サイトの特定のセクションのエントリポイントとして機能する Web ページ) になります。

+ +

私たちのルートの中にも二つのディレクトリー — pdfsprojects  があります。これらはそれぞれ中に PDF (project-brief.pdf) と index.html ファイルというファイルがあります。ファイルシステム内の別の場所にある限り、1 つのプロジェクトに 2 つの index.html ファイルを非常にうまく入れることができることに注意してください。多くの Web サイトはそうします。2番目の index.html は、おそらくプロジェクト関連の情報のメインランディングページになります。

+ + + +
+

メモ: 例えば ../../../complex/path/to/my/file.html のように、必要に応じて、これらの機能の複数のインスタンスを複雑な URL に組み合わせることができます。

+
+ +

ドキュメントフラグメント

+ +

HTML 文書の上部だけでなく、HTML 文書の特定の部分 (ドキュメントフラグメントと呼ばれる) にリンクすることもできます。これを行うには、まずリンク先の要素に {{htmlattrxref("id")}} 属性を割り当てる必要があります。通常は特定の見出しにリンクするのが理にかなっているので、次のようになります。

+ +
<h2 id="Mailing_address">Mailing address</h2>
+ +

次にその特定の id にリンクするには、URL の最後にハッシュ/ポンド記号を付けてそれを含めます。次に例を示します。

+ +
<p>Want to write us a letter? Use our <a href="contacts.html#Mailing_address">mailing address</a>.</p>
+ +

同じドキュメントの別の部分にリンクするために、ドキュメントフラグメント参照を単独で使用することさえできます。

+ +
<p>The <a href="#Mailing_address">company mailing address</a> can be found at the bottom of this page.</p>
+ +

絶対 URL vs 相対 URL

+ +

Web 上で見かける 2 つの用語は絶対 URL相対 URL です。

+ +

絶対 URL: {{glossary("protocol")}} と {{glossary("domain name")}} を含む、Web 上の絶対位置で定義された位置を指します。たとえば、index.html ページが Web サーバーのルート内にある projects というディレクトリーにアップロードされ、その Web サイトのドメインが http://www.example.com の場合、そのページは http://www.example.com/projects/index.html (あるいは http://www.example.com/projects/ だけでも、URL で指定されていない場合、Web サーバーは index.html のようなランディングページを探してロードします) で入手可能です。

+ +

絶対 URL は、使用されている場所に関係なく、常に同じ場所を指します。

+ +

相対 URL: あなたがリンクしているファイルからの相対的な場所を指しています。たとえば、http://www.example.com/projects/index.html にあるサンプルファイルから同じディレクトリー内の PDF ファイルにリンクする場合、URL は単にファイル名 — 例えば project-brief.pdf — となり、追加情報は不要です。PDF が projects 内の pdfs という名前のサブディレクトリーにある場合、相対リンクは pdfs/project-brief.pdf (同等の絶対 URL は http://www.example.com/projects/pdfs/project-brief.pdf) になります。

+ +

相対 URL は内部で使用されているファイルの実際の場所によって、異なる場所を指します。たとえば、index.html ファイルを projects ディレクトリーから Web サイトのルート (最上位レベル、どのディレクトリーの中でもありません) に移動した場合、pdfs/project-brief.pdf 相対 URL リンクの内部は、http://www.example.com/pdfs/project-brief.pdf にあるファイルを指し、http://www.example.com/projects/pdfs/project-brief.pdf にあるファイルではありません。

+ +

もちろん、index.html ファイルを移動しても project-brief.pdf ファイルと pdfs フォルダーの場所が突然変わることはありません — これはリンクが間違った場所を指しているため、クリックしても機能しません。注意する必要があります。

+ + + +

リンクを書くときに従うべきベストプラクティスがいくつかあります。今これらを見てみましょう。

+ + + + + +

ページにリンクを張るのは簡単です。それだと十分じゃありません。現在の状況やツールの好みに関係なく、リンクをすべての読者がアクセスできるようにする必要があります。例えば:

+ + + +

具体的な例を見てみましょう。

+ +

良い リンクテキスト: Download Firefox

+ +
<p><a href="https://firefox.com/">
+  Download Firefox
+</a></p>
+ +

悪い リンクテキスト: Click here to download Firefox

+ +
<p><a href="https://firefox.com/">
+  Click here
+</a>
+to download Firefox</p>
+
+ +

その他のヒント

+ + + + + +

上記の説明から、絶対リンクを常に使用することが賢明だと思うかもしれません。結局のところ、ページが相対リンクのように移動されても壊れません。ただし、同じ Web サイト内の他の場所にリンクする場合は、できるだけ相対リンクを使用する必要があります (他の Web サイトにリンクする場合は、絶対リンクを使用する必要があります)。

+ + + +

HTML 以外のリソースへのリンク - 明確な道標を残す

+ +

(PDF や Word 文書のように) ダウンロードされたり (ビデオやオーディオのように) ストリーミングされたり、ポップアップウィンドウを開いたり、Flash ムービーを読み込んだりするなど、予期せぬ効果をもたらすリソースにリンクする場合は、混乱を避けるために明確な表現を追加します。例えば、それはかなりいらいらさせることができます。

+ + + +

ここではどのような種類のテキストを使用できるかを見るために、いくつかの例を見てみましょう。

+ +
<p><a href="http://www.example.com/large-report.pdf">
+  Download the sales report (PDF, 10MB)
+</a></p>
+
+<p><a href="http://www.example.com/video-stream/" target="_blank">
+  Watch the video (stream opens in separate tab, HD quality)
+</a></p>
+
+<p><a href="http://www.example.com/car-game">
+  Play the car game (requires Flash)
+</a></p>
+ +

ダウンロードへのリンクは download 属性を使う

+ +

ブラウザーで開くのではなくダウンロードするリソースにリンクしている場合は、download 属性を使用してデフォルトの保存ファイル名を指定できます。これは最新の Windows 版 Firefox へのダウンロードリンクの例です。

+ +
<a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=en-US"
+   download="firefox-latest-64bit-installer.exe">
+  Download Latest Firefox for Windows (64-bit) (English, US)
+</a>
+ +

アクティブラーニング: ナビゲーションメニューの作成

+ +

この演習では、ナビゲーションメニューを使用していくつかのページをリンクして、複数ページの Web サイトを作成してください。これは Web サイトが作成される一般的な方法の 1 つです。同じナビゲーションメニューを含め、すべてのページで同じページ構造が使用されます。リンクをクリックすると、同じ場所に留まっているという印象が与えられ、異なるコンテンツが表示されます。

+ +

次の 4 ページのローカルコピーをすべて同じディレクトリーに作成する必要があります (完全なファイルリストについては navigation-menu-start ディレクトリーも参照してください)。

+ + + +

あなたがすべきことは:

+ +
    +
  1. リンク先のページの名前を含む、順序なしリストを 1 ページの指示された場所に追加します。ナビゲーションメニューは通常単なるリンクのリストなので、意味的には問題ありません。
  2. +
  3. 各ページ名をそのページへのリンクにします。
  4. +
  5. ナビゲーションメニューを各ページにコピーします。
  6. +
  7. 各ページで、その同じページへのリンクだけを削除します - ページに自分自身へのリンクを含めることは混乱を招き、無意味です。また、リンクがないことは、現在表示しているページを視覚的に思い出させるものです。
  8. +
+ +

完成した例では、次のようになります。

+ +

An example of a simple HTML navigation menu, with home, pictures, projects, and social menu items

+ +
+

メモ: 動けなくなったり、正しいかどうかわからない場合は、ナビゲーションメニューのマークアップディレクトリーをチェックして正しい答えを確認できます。

+
+ + + +

クリックすると、リソースまたはページにリンクするのではなく、新しい送信メールメッセージを開くリンクまたはボタンを作成することができます。これは {{HTMLElement("a")}} 要素と mailto: URL スキームを使って行われます。

+ +

最も基本的で一般的に使用されている形式では、mailto: リンクは単に意図した受信者のメールアドレスを示します。例えば:

+ +
<a href="mailto:nowhere@mozilla.org">メールをどこにも送信しません</a>
+
+ +

この結果、次のようなリンクが表示されます。メールをどこにも送信しません

+ +

実際、メールアドレスはオプションです。省略した場合 (つまり、{{htmlattrxref("href", "a")}} は単に "mailto:" です)、宛先アドレスがまだ指定されていないユーザーのメールクライアントによって、新しい送信メールウィンドウが開かれます。これは、ユーザーがクリックして自分が選択したアドレスに E メールを送信できる「共有」リンクとして役立つことがよくあります。

+ +

詳細の指定

+ +

メールアドレスに加えて、他の情報を提供することができます。実際、提供する mailto URL には標準のメールヘッダフィールドを追加できます。最も一般的に使用されるのは "subject"、"cc"、および  "body" です (これは本当のヘッダーフィールドではありませんが、新しいメールのための短い内容のメッセージを指定することを可能にします)。各フィールドとその値は、クエリ用語として指定されています。

+ +

これは cc、bcc、件名、本文を含む例です。

+ +
<a href="mailto:nowhere@mozilla.org?cc=name2@rapidtables.com&bcc=name3@rapidtables.com&subject=The%20subject%20of%20the%20email&body=The%20body%20of%20the%20email">
+  Send mail with cc, bcc, subject and body
+</a>
+ +
+

メモ: 各フィールドの値は URL エンコードされている必要があります。つまり、非印刷文字 (タブ、キャリッジリターン、改ページなどの不可視文字) とスペースのパーセントエスケープが含まれています。また、疑問符 (?) を使用してメイン URL とフィールド値を区別し、アンパサンド (&) を使用して mailto: URL 内の各フィールドを区別します。これは標準の URL クエリ表記です。GET メソッドを読んで、どの URL クエリ表記がより一般的に使用されているかを理解してください。

+
+ +

以下は mailto の他の URL の例です。

+ + + +

まとめ

+ +

とにかく今のところ、それはリンクのためのそれです!
+ スタイルの設定を見始めると、コースの後半のリンクに戻ります。次に HTML について説明します。テキストのセマンティクスに戻って、役に立つと思われるより高度な機能や変わった機能について説明します。高度なテキストの書式設定は、次に行うことです。

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/html/introduction_to_html/debugging_html/index.html b/files/ja/learn/html/introduction_to_html/debugging_html/index.html new file mode 100644 index 0000000000..24c4e6c4d3 --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/debugging_html/index.html @@ -0,0 +1,185 @@ +--- +title: HTML のデバッグ +slug: Learn/HTML/Introduction_to_HTML/Debugging_HTML +tags: + - CodingScripting + - HTML + - エラー + - ガイド + - デバッグ + - バリデーション + - バリデーター + - ビギナー +translation_of: Learn/HTML/Introduction_to_HTML/Debugging_HTML +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}
+ +

HTML を書くことは良いですが、何か問題が生じた場合どうなります?また、コード内のどこにエラーがあるか見つけられますか?この記事では HTML 内のエラーの発見、および修正の手助けをしてくれるいくつかのツールを紹介します。

+ + + + + + + + + + + + +
前提条件:HTML の使い方、HTML の始め方や HTML テキストの基礎、そしてハイパーリンクの作成を網羅した例。
目的:HTML内の問題を見つけるためのデバッグ用ツールの基本的な使い方の学習。
+ +

デバッグは怖くない

+ +

何かのコードを書いている時、エラーが起きる (何かしらの間違いを犯したため、コードが全く機能しない、あるいは望んでいた通りに動かない) その恐ろしい瞬間まで、通常は全く問題ありません。たとえば、以下は Rust 言語で書かれた単純なプログラムを {{glossary("compile")}} しようとしたときに報告されるエラーを示しています。A console window showing the result of trying to compile a rust program with a missing quote around a string in a print statement. The error message reported is error: unterminated double quote string.ここに、比較的分かりやすいエラーメッセージがあります。 — "閉じていない二重引用符文字列"。リストを見れば、おそらく論理的に println!(Hello, world!"); に二重引用符がない可能性があるとわかるでしょう。しかし、プログラムが大きくなるにつれてエラーメッセージはすぐに複雑になり、解釈しにくくなります。簡単な場合でも、Rust について何も知らない人には少し威圧的に見えるかもしれません。

+ +

デバッグを怖がる必要はありません —  プログラミング言語やコードの作成、デバッグに慣れるための鍵は、言語とツールの両方に精通していることです。

+ +

HTML とデバッグ

+ +

HTML は Rust ほど理解するのが複雑ではありません。ブラウザが解析して結果を表示するまで、HTML は別の形式にコンパイルされません (解釈されますが、コンパイルはされません)。そして HTML の {{glossary("element")}} 構文は、Rust、{{glossary("JavaScript")}}、または {{glossary("Python")}} のような "実際のプログラミング言語" よりはるかに理解しやすいです。ブラウザが HTML を解析する方法は、プログラミング言語の実行方法よりもはるかに寛容です。これは良いことと悪いことの両方です。

+ +

許容コード

+ +

では寛容とはどういうことでしょうか。まあ、一般的にコードで何か間違ったことをするとき、出くわすことになる2つの主なタイプのエラーがあります:

+ + + +

HTML 自体は構文エラーに悩まされていません。ブラウザが構文解析エラーを許容して解析するからです。つまり、構文エラーがあってもページは表示されたままです。ブラウザには、誤って書かれたマークアップを解釈する方法を決定するための組み込みのルールがあるので、たとえそれが期待したものでなくても、実行することはできます。もちろん、これはまだ問題になる可能性があります。

+ +
+

メモ: Web の世界が最初に構築されたとき、HTML はそれほど厳格には解析されませんでした。これは、構文(シンタックス)が絶対的に正しいことを確認するよりも、人々がコンテンツを公開できることのほうが重要であると判断されたためです。当初から構文がより厳格に処理されていたとすれば、おそらく 現在のような Web は実現されなかったでしょう。

+
+ +

アクティブラーニング: 許容コードの学習

+ +

HTML コードの寛容な性質を学習する時が来ました。

+ +
    +
  1. まず、debug-example のデモをダウンロードしてローカルに保存します。このデモは、調査するために意図的にエラーを含むように書かれています (HTML マークアップは整形式ではないと言われており、整形式とは対照的です)。
  2. +
  3. 次にブラウザで開きます。 このようなものを見るでしょう:A simple HTML document with a title of HTML debugging examples, and some information about common HTML errors, such as unclosed elements, badly nested elements, and unclosed attributes.
  4. +
  5. これはすぐには良く見えません。ソースコードを調べて、問題が解決できるかどうか確認しましょう (本文の内容だけが表示されます)。 +
    <h1>HTML debugging examples</h1>
    +
    +<p>What causes errors in HTML?
    +
    +<ul>
    +  <li>Unclosed elements: If an element is <strong>not closed properly,
    +      then its effect can spread to areas you didn't intend
    +
    +  <li>Badly nested elements: Nesting elements properly is also very important
    +      for code behaving correctly. <strong>strong <em>strong emphasised?</strong>
    +      what is this?</em>
    +
    +  <li>Unclosed attributes: Another common source of HTML problems. Let's
    +      look at an example: <a href="https://www.mozilla.org/>link to Mozilla
    +      homepage</a>
    +</ul>
    +
  6. +
  7. 問題を見てみましょう。 +
      +
    • {{htmlelement("p","paragraph")}} と {{htmlelement("li","list item")}} 要素には終了タグがありません。上の画像を見ると、ある要素がどこで終わり、別の要素が始まるべきかを推測するのは簡単なので、これはマークアップのレンダリングにあまり悪い影響を与えていないようです。
    • +
    • 最初の {{htmlelement("strong")}} 要素には終了タグがありません。要素がどこで終了するのか分かりにくいので、もう少し問題があります。実際、残りのテキスト全体が強調されています。
    • +
    • このセクションはひどくネストされています: <strong>strong <em>strong emphasised?</strong> what is this?</em>。前の問題もあって、これがどのように解釈されたかを見分けるのは容易ではありません。
    • +
    • {{htmlattrxref("href","a")}} 属性値に、閉じ二重引用符がありません。これが最大の問題を引き起こしているようです。リンクはまったくレンダリングされていません。
    • +
    +
  8. +
  9. それでは、ソースコードのマークアップに対して、ブラウザがレンダリングしたマークアップを見てみましょう。これを行うには、ブラウザの開発者ツールを使用できます。ブラウザの開発者ツールの使い方に慣れていない場合は、Discover browser developer tools を数分確認してください。
  10. +
  11. DOM インスペクタでは、レンダリングされたマークアップがどのように見えるかを見ることができます。The HTML inspector in Firefox, with our example's paragraph highlighted, showing the text "What causes errors in HTML?" Here you can see that the paragraph element has been closed by the browser.
  12. +
  13. DOM インスペクタを使用して、ブラウザが HTML エラーを修正しようとしている方法を確認するためにコードを詳しく調べてみましょう (もちろん Firefox で確認していますが、他のモダンなブラウザでも同じ結果が得られるはずです)。 +
      +
    • 段落とリスト項目には終了タグが付けられています。
    • +
    • 最初の <strong> 要素がどこで閉じられるべきかは明確ではないので、ブラウザはそれぞれ別々のテキストブロックをそれぞれの strong タグで、ドキュメントの一番下まで閉じています。
    • +
    • 不正確なネスティングはブラウザによってこのように修正されました: +
      <strong>strong
      +  <em>strong emphasised?</em>
      +</strong>
      +<em> what is this?</em>
      +
    • +
    • 二重引用符がないリンクは完全に削除されました。 最後のリスト項目は次のようになります。 +
      <li>
      +  <strong>Unclosed attributes: Another common source of HTML problems.
      +  Let's look at an example: </strong>
      +</li>
      +
    • +
    +
  14. +
+ +

HTML バリデーション

+ +

上記の例から、HTML が整形式であることを本当に確認したいことがわかります。しかし、どうですか?上のような小さな例では、行を検索してエラーを見つけるのは簡単ですが、巨大で複雑な HTML 文書についてはどうでしょうか。

+ +

最良の戦略は、HTML、CSS、およびその他の Web テクノロジを定義する仕様を管理する組織である W3C によって作成および管理されている Markup Validation Service を介して HTML ページを実行することです。この Web ページは入力として HTML ドキュメントを受け取り、それを通して、あなたの HTML の何が悪いのかを伝えるレポートを提供してくれます。

+ +

The HTML validator homepage

+ +

検証する HTML を指定するには、Web アドレスを指定するか、HTML ファイルをアップロードするか、または HTML コードを直接入力します。

+ +

アクティブラーニング: HTML ドキュメントの検証

+ +

サンプル文書でこれを試してみましょう。

+ +
    +
  1. まず、Markup Validation Service を1つのブラウザタブに読み込みます (まだ読み込まれていない場合)。
  2. +
  3. Validate by Direct Input タブに切り替えます。
  4. +
  5. 本文だけでなく、すべてのサンプルドキュメントのコードをコピーして、Markup Validation Service に表示される大きなテキスト領域に貼り付けます。
  6. +
  7. Check ボタンを押します
  8. +
+ +

これでエラーと他の情報のリストを提供してくれるはずです。

+ +

A list of of HTML validation results from the W3C markup validation service

+ +

エラーメッセージの解釈

+ +

エラーメッセージは通常役に立ちますが、あまり役に立たないこともあります。少し訓練すれば、これらを解釈してコードを修正する方法を考え出すことができます。エラーメッセージとその意味を見ていきましょう。各メッセージには行番号と列番号が付いているので、エラーを簡単に見つけることができます。

+ + + +

すべてのエラーメッセージが何を意味するのかわからない場合でも、心配しないでください一度にいくつかのエラーを修正してみることをお勧めします。 それから、どんなエラーが残っているかを示すためにあなたの HTML を再検証することを試みてください。以前のエラーを修正すると他のエラーメッセージも消えてしまうことがあります。つまりはドミノ効果で、単一の問題が原因でいくつかのエラーが発生することがあるということです。

+ +

出力に次のバナーが表示されたら、エラーがすべて解決したことがわかります。

+ +

Banner that reads "The document validates according to the specified schema(s) and to additional constraints checked by the validator."

+ +

まとめ

+ +

ここでは HTML のデバッグについて紹介しました。これは、後で CSS、JavaScript、およびその他の種類のコードのデバッグを始めるときに頼りになる便利なスキルです。
+ また HTMLモジュールの学習に関する記事の紹介の終わりにもなります。今、あなたは私たちの評価で自分自身をテストすることに進むことができます。最初のものは以下にリンクされています。

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/introduction_to_html/document_and_website_structure/index.html b/files/ja/learn/html/introduction_to_html/document_and_website_structure/index.html new file mode 100644 index 0000000000..86cb004b5e --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/document_and_website_structure/index.html @@ -0,0 +1,293 @@ +--- +title: ドキュメントと Web サイトの構造 +slug: Learn/HTML/Introduction_to_HTML/Document_and_website_structure +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - Layout + - Page + - Site + - blocks + - semantics +translation_of: Learn/HTML/Introduction_to_HTML/Document_and_website_structure +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}
+ +

{{glossary("HTML")}} は、ページの個々の部分 (「段落」や「画像」など) を定義するだけでなく、ウェブサイトの領域を定義するために使用される多数のブロックレベル要素 (「ヘッダー」、「ナビゲーションメニュー」、「メインコンテンツ列」など) も備えています。この記事では、基本的なウェブサイト構造を計画し、この構造を表す HTML を記述する方法について説明します。

+ + + + + + + + + + + + +
前提条件:HTML を始めよう」で説明されている基本的な HTML の理解。「HTML テキストの基礎」で説明されている HTML テキストの書式設定。「ハイパーリンクの作成」で説明されている、ハイパーリンクのしくみ。
目的:セマンティックタグを使用して文書を構造化する方法、および単純なウェブサイトの構造を作成する方法を学びます。
+ +

文書の基本部分

+ +

ウェブページはひとつひとつの見た目が異なるものですが、全画面表示のビデオやゲームを表示している場合やアートプロジェクトの一部分である場合や単にまずく構成されている場合を除いて、よく似た標準コンポーネントを共有している傾向にあります:

+ +
+
ヘッダー:
+
通常は大きな見出しやロゴの付いた上部の大きな部分。通常、ウェブページ間を移動しても、ウェブサイトに関する主な共通情報がととどまっている場所です。
+
ナビゲーションバー:
+
サイトの主要セクションへのリンク。通常はメニューボタン、リンク、またはタブで表されます。ヘッダーと同様に、このコンテンツは通常、あるウェブページから別のウェブページへと一貫性を保っています — あなたのウェブサイト上でナビゲーションが矛盾していると、混乱して欲求不満のあるユーザーになるだけです。多くの Web デザイナーはナビゲーションバーを個々のコンポーネントではなくヘッダーの一部と見なしていますが、これは必須ではありません。実際、スクリーンリーダーは 2 つの機能を別々にした方が読みやすくなるため、2 つの機能を別々に使用するほうがアクセシビリティに優れていると主張する人もいます。
+
メインコンテンツ:
+
特定のウェブページのほとんどのユニークなコンテンツが含まれている中央の大きな領域。たとえば、見たいビデオ、読んでいる本編、表示したい地図、ニュースの見出しなど これは間違いなくページごとに異なるウェブサイトの一部です。
+
サイドバー:
+
いくつかの周辺情報、リンク、引用、広告など。通常これはメインコンテンツ (例えば、ニュース記事ページ、サイドバーに作者の略歴、または関連記事へのリンクなど) に含まれているものとの関連性があります。また、二次ナビゲーションシステムのように繰り返し発生する要素がある場合もあります。
+
フッター:
+
通常、注意事項、著作権表示、または連絡先情報が含まれているページの下部にある部分。これは共通の情報 (ヘッダーなど) を入れる場所ですが、通常、その情報はウェブサイト自体にとって重要ではありません。フッターは、人気のあるコンテンツにすばやくアクセスするためのリンクを提供することで、{{Glossary("SEO")}} の目的で使用されることもあります。
+
+ +

「典型的なウェブサイト」は下記のようなレイアウトになります:

+ +

a simple website structure example featuring a main heading, navigation menu, main content, side bar, and footer.

+ +

コンテンツを構造化する HTML

+ +

上に示した簡単な例はきれいではありませんが、典型的なウェブサイトのレイアウト例を示すのには最適です。一部のウェブサイトはより多くのコラムを持っています、いくつかはかなり複雑ですが、アイデアはあります。適切な CSS を使用すれば、さまざまなセクションをラップして望みどおりの外観にするためにほとんどすべての要素を使用できますが、前述のとおり、セマンティクスを尊重し、適切な役割に適切な要素を使用する必要があります。

+ +

なぜならビジュアルがすべてを伝えるわけではないからです。私たちはナビゲーションメニューや関連リンクなど、コンテンツの最も有用な部分に目の見えるユーザーの注意を引くために、色とフォントサイズを使用します。しかし、例えば「ピンク」や「大きいフォント」のような概念があまり有用ではないと思われる視覚障害者についてはどうでしょうか。

+ +
+

: 色覚障害者は世界の人口の約 4 %を占めています。言い換えれば、男性 12 人に 1 人、女性 200 人に 1 人が色覚異常です。視覚障害のある人々は世界の人口の約 4〜5 %を占めています (2012 年には全世界で 2 億 8,500 万人の人々がいましたが、総人口は約 70 億人でした)。

+
+ +

HTML コードでは、それらの機能に基づいてコンテンツのセクションをマークアップすることができます — スクリーンリーダーのような支援技術はそれらの要素を認識し、「メインナビゲーションを見つける」や「メインコンテンツを見つける」といった作業を手助けすることができます。
+ コースの前半で述べたように、適切な役割に適切な要素構造とセマンティクスを使用しないことによる影響は多くあります。

+ +

このようなセマンティックマークアップを実装するために、HTML には、そのようなセクションを表すために使用できる専用のタグが用意されています。次に例を示します。

+ + + +

アクティブ学習: 実例のコードを見てみる

+ +

上記の例は次のコードで表されています (この例は GitHub リポジトリにもあります)。上の例を見てから、下のリストを見て、どの部分がビジュアルのどの部分を構成しているかを確認してください。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+
+    <title>My page title</title>
+    <link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One" rel="stylesheet" type="text/css">
+    <link rel="stylesheet" href="style.css">
+
+    <!-- the below three lines are a fix to get HTML5 semantic elements working in old versions of Internet Explorer-->
+    <!--[if lt IE 9]>
+      <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
+    <![endif]-->
+  </head>
+
+  <body>
+    <!-- Here is our main header that is used across all the pages of our website -->
+
+    <header>
+      <h1>Header</h1>
+    </header>
+
+    <nav>
+      <ul>
+        <li><a href="#">Home</a></li>
+        <li><a href="#">Our team</a></li>
+        <li><a href="#">Projects</a></li>
+        <li><a href="#">Contact</a></li>
+      </ul>
+
+       <!-- A Search form is another commmon non-linear way to navigate through a website. -->
+
+       <form>
+         <input type="search" name="q" placeholder="Search query">
+         <input type="submit" value="Go!">
+       </form>
+     </nav>
+
+    <!-- Here is our page's main content -->
+    <main>
+
+      <!-- It contains an article -->
+      <article>
+        <h2>Article heading</h2>
+
+        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Donec a diam lectus. Set sit amet ipsum mauris. Maecenas congue ligula as quam viverra nec consectetur ant hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.</p>
+
+        <h3>subsection</h3>
+
+        <p>Donec ut librero sed accu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor.</p>
+
+        <p>Pelientesque auctor nisi id magna consequat sagittis. Curabitur dapibus, enim sit amet elit pharetra tincidunt feugiat nist imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros.</p>
+
+        <h3>Another subsection</h3>
+
+        <p>Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum soclis natoque penatibus et manis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+
+        <p>Vivamus fermentum semper porta. Nunc diam velit, adipscing ut tristique vitae sagittis vel odio. Maecenas convallis ullamcorper ultricied. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, is fringille sem nunc vet mi.</p>
+      </article>
+
+      <!-- the aside content can also be nested within the main content -->
+      <aside>
+        <h2>Related</h2>
+
+        <ul>
+          <li><a href="#">Oh I do like to be beside the seaside</a></li>
+          <li><a href="#">Oh I do like to be beside the sea</a></li>
+          <li><a href="#">Although in the North of England</a></li>
+          <li><a href="#">It never stops raining</a></li>
+          <li><a href="#">Oh well...</a></li>
+        </ul>
+      </aside>
+
+    </main>
+
+    <!-- And here is our main footer that is used across all the pages of our website -->
+
+    <footer>
+      <p>©Copyright 2050 by nobody. All rights reversed.</p>
+    </footer>
+
+  </body>
+</html>
+ +

コードを見て理解するためにしばらく時間をかけてください — コード内のコメントもそれを理解するのに役立ちます。ドキュメントのレイアウトを理解するための鍵は、正しい HTML 構造を作成し、それを CSS でレイアウトすることです。CSS トピックの一部として CSS レイアウトの学習を始めるまで、これを待ちます。

+ +

HTML レイアウト要素の詳細

+ +

すべての HTML セクショニング要素の全体的な意味を詳細に理解しておくとよいでしょう。これは、ウェブ開発でより多くの経験を積むようになるにつれて徐々に取り組むものです。  HTML 要素のリファレンスを読むことによって多くの詳細を見つけることができます。今のところ、これらは理解するべき主な定義です:

+ + + +

非セマンティックなラッパー

+ +

時にはいくつかのアイテムをまとめたり、コンテンツをラップしたりするための理想的なセマンティック要素が見つからない場合があります。いくつかの {{glossary("CSS")}} や {{glossary("JavaScript")}} を持つ単一のエンティティとしてそれらすべてに影響を与えるために単に要素のセットを一緒にグループ化したいことがあります。このような場合に、HTML は {{HTMLElement("div")}} と {{HTMLElement("span")}} 要素を提供します。これらを適切な {{htmlattrxref('class')}} 属性と一緒に使用して、簡単にターゲティングできるようにそれらに何らかの種類のラベルを提供することをお勧めします。

+ +

{{HTMLElement("span")}} はインラインの非セマンティック要素です。コンテンツをラップするより良い意味的なテキスト要素が思いつかないか、または特定の意味を加えたくない場合にだけ使うべきです。例えば:

+ +
<p>The King walked drunkenly back to his room at 01:00, the beer doing nothing to aid
+him as he staggered through the door <span class="editor-note">[Editor's note: At this point in the
+play, the lights should be down low]</span>.</p>
+ +

この場合、編集者のメモは単に演劇の監督に追加の指示を与えることになっています。特別な意味を持つことは想定されていません。視覚のある人にとっては、CSS はメモを本文からわずかに離すように使われます。

+ +

{{HTMLElement("div")}} はブロックレベルの非セマンティック要素であり、使用するセマンティックブロック要素を考えない場合、または特定の意味を追加したくない場合にのみ使用してください。たとえば、電子商取引サイトで、いつでも買い物をすることができるショッピングカートのウィジェットを想像してみてください。

+ +
<div class="shopping-cart">
+  <h2>Shopping cart</h2>
+  <ul>
+    <li>
+      <p><a href=""><strong>Silver earrings</strong></a>: $99.95.</p>
+      <img src="../products/3333-0985/thumb.png" alt="Silver earrings">
+    </li>
+    <li>
+      ...
+    </li>
+  </ul>
+  <p>Total cost: $237.89</p>
+</div>
+ +

これは必ずしも <aside> ではありません。必ずしもページのメインコンテンツに関連しているわけではないからです (どこからでも見られるようにしたいのです)。ページのメインコンテンツの一部ではないので、<section> の使用を特に保証するものではありません。したがって、この場合は <div> で問題ありません。スクリーンリーダーのユーザーが見つけやすいように、道標として見出しを追加しました。

+ +
+

警告: Div は使い勝手が良いので使いすぎになりがちです。それらは意味的な価値を持たないので、HTML コードを乱雑にするだけです。より良い意味的な解決策がない場合にのみ使用するように気を付けてください。

+
+ +

改行と垂直方向のルール

+ +

時々使う、そして知りたい 2 つの要素は {{htmlelement("br")}} と {{htmlelement("hr")}} です:

+ +

<br> は段落内に改行を作成します。これは、住所や詩のように一連の短い固定線が必要な状況で硬い構造を強制する唯一の方法です。例えば:

+ +
<p>There once was a girl called Nell<br>
+Who loved to write HTML<br>
+But her structure was bad, her semantics were sad<br>
+and her markup didn't read very well.</p>
+ +

<br> 要素がないと、段落は 1行で表示されます (コースの前半で述べたように、HTML はほとんどの空白を無視します)。コード内でこれらを使用すると、マークアップは次のようにレンダリングされます。

+ +

There once was a man named O'Dell
+ Who loved to write HTML
+ But his structure was bad, his semantics were sad
+ and his markup didn't read very well.

+ +

<hr> 要素は、テキストの主題の変更 (トピックやシーンの変更など) を示す水平方向の罫線をドキュメントに作成します。視覚的には単に横線のように見えます。例として:

+ +
<p>ロンは荒廃した地獄の獣たちによって隅に追いやられた。怖がっていたが、彼の友達を守ることを決心していたので、彼は自分の杖を上げて戦いをする準備をした。</p>
+<hr>
+<p>その間、ハリーは家に座って、彼の使用料の声明を見つめてそして魅惑の苦痛の手紙が彼の窓を通って飛んで、そして彼の膝に着陸したときに次のスピンオフシリーズが出るだろう時を考えました。彼はそれをぼんやりと読んでため息をついた。「その時は仕事に戻るほうがいい」と彼は言った。</p>
+ +

このようにレンダリングされます:

+ +

ロンは荒廃した地獄の獣たちによって隅に追いやられた。怖がっていたが、彼の友達を守ることを決心していたので、彼は自分の杖を上げて戦いをする準備をした。

+ +
+

その間、ハリーは家に座って、彼の使用料の声明を見つめてそして魅惑の苦痛の手紙が彼の窓を通って飛んで、そして彼の膝に着陸したときに次のスピンオフシリーズが出るだろう時を考えました。彼はそれをぼんやりと読んでため息をついた。「その時は仕事に戻るほうがいい」と彼は言った。

+ +

簡単なウェブサイトを計画する

+ +

簡単なウェブページのコンテンツの構造を計画したら、次の論理的なステップは、ウェブサイト全体に掲載したいコンテンツ、必要なページ、および可能な限り最高のユーザーエクスペリエンスを実現するために、それらをどのように配置して互いにリンクさせるかを解決することです。これは {{glossary("Information architecture")}} と呼ばれます。大規模で複雑なウェブサイトでは、このプロセスに多くの計画を立てることがありますが、数ページの単純なウェブサイトでは、かなり単純で楽しいものになります。

+ +
    +
  1. ナビゲーションメニューやフッターコンテンツなど、(全部ではないにしても) ほとんどのページに共通の要素がいくつかあることに注意してください。たとえば、サイトがビジネスのためのものである場合、連絡先情報を各ページのフッターで利用可能にすることは良い考えです。すべてのページに共通にしたいものを書き留めます。the common features of the travel site to go on every page: title and logo, contact, copyright, terms and conditions, language chooser, accessibility policy
  2. +
  3. 次に、各ページの構造をどのようにしたらよいかを大まかにスケッチします (上の単純なウェブサイトのようになります)。各ブロックがどうなるかに注意してください。A simple diagram of a sample site structure, with a header, main content area, two optional sidebars, and footer
  4. +
  5. さて、自身のウェブサイトに載せたい他のすべての (全ページに共通ではない) コンテンツをブレインストーミングしましょう — 大きなリストに書き留めます。A long list of all the features that we could put on our travel site, from searching, to special offers and country-specific info
  6. +
  7. 次に、これらすべてのコンテンツ項目をグループに分類して、どの部分が異なるページに共存しているかを把握します。これは {{glossary("Card sorting")}} と呼ばれるテクニックと非常によく似ています。The items that should appear on a holiday site sorted into 5 categories: Search, Specials, Country-specific info, Search results, and Buy things
  8. +
  9. それでは、大まかなサイトマップをスケッチしてみましょう。サイト上の各ページにバブルを付け、ページ間の典型的なワークフローを示すために線を引きます。
    + ホームページはおそらく中心にあり、すべてではないにしてもほとんどのページにリンクするでしょう。例外はありますが、小規模サイトのほとんどのページはメインナビゲーションから利用できるはずです。物事がどのように提示されるかもしれないかについてのメモも含めることをお勧めします。A map of the site showing the homepage, country page, search results, specials page, checkout, and buy page
  10. +
+ +

アクティブラーニング: 自身のサイトマップを作成する

+ +

自身が作成したウェブサイトのために上記の演習を実行してみてください。何についてサイトを作りたいですか?

+ +
+

: 作業をどこかに保存してください。後で必要になるかもしれません。

+
+ +

まとめ

+ +

この時点であなたはウェブページ/サイトをどのように構成するかについてより良い考えを持っているはずです。このモジュールの最後の記事では、HTML をデバッグする方法を学びます。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/html/introduction_to_html/getting_started/index.html b/files/ja/learn/html/introduction_to_html/getting_started/index.html new file mode 100644 index 0000000000..6cfcea234e --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/getting_started/index.html @@ -0,0 +1,786 @@ +--- +title: HTML を始めよう +slug: Learn/HTML/Introduction_to_HTML/Getting_started +tags: + - Attribute + - Beginner + - CodingScripting + - Comment + - Element + - Guide + - HTML + - entity reference + - whitespace +translation_of: Learn/HTML/Introduction_to_HTML/Getting_started +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}
+ +

この記事では HTML の不変的な基礎を扱って、始められるようにします。要素や属性などの重要な用語 (すでに聞き覚えはあるかもしれません)、それらが言語にどう組み込まれているか説明します。また、HTML 要素の構造、典型的な HTML ページの構造を見せて、その他の重要な基礎言語機能について説明します。それでは、 HTML の例とともに見ていきましょう。

+ + + + + + + + + + + + +
前提条件:基礎的なコンピュータリテラシー、基本的なソフトウェアのインストールファイル取扱いの基礎理解。
目的: +

HTML 言語の基礎習得と、いくつかの HTML 要素を書く練習

+
+ +

HTML とは?

+ +

{{glossary("HTML")}} (ハイパーテキスト・マークアップ・ランゲージ/Hypertext Markup Language) はプログラミング言語ではありません。HTML 言語は、訪れたウェブサイトの構成をブラウザに対して伝えるために使うマークアップ言語です。HTML 言語はウェブ開発者が望むこと次第で、複雑なものにも簡単なものにもなります。HTML は{{glossary("Element", "要素")}}の集まりからなり、コンテンツの一部を要素で囲む(マークアップする)ことで、特定の見せ方・動かし方に変えられます。囲むための{{glossary("Tag", "タグ")}}は、コンテンツの一部をハイパーリンク (ウェブ上の別ページへリンクすること) にしたり、単語を斜体にしたりすることができます。たとえば、次の一行を見てください:

+ +
My cat is very grumpy
+ +

この行を独立させたい場合、それを段落タグ ({{htmlelement("p")}}) 要素で囲んで段落指定することで実現できます:

+ +
<p>My cat is very grumpy</p>
+ +
+

:HTML の要素は大文字小文字を区別しません。つまり大文字でも小文字でも書くことができます。例えば {{htmlelement("title")}} 要素は <title><TITLE><Title><TiTlE> などと書くことができて、どれも正しく動作します。最も良いのは、一貫性や信頼性、その他の理由のためにすべての要素を小文字で書くことです。

+
+ +

HTML 要素の分解

+ +

先ほどの段落タグの要素についてもう少し詳しく見ていきましょう:

+ +

+ +

この要素の主要な部分は次のとおりです:

+ +
    +
  1. 開始タグ(Opening tag): 要素名 (この場合は "p")、囲んでいる開き山括弧と閉じ山括弧で構成されています。これは要素が始まってその効果が開始する位置を宣言しますーこの場合、段落が始まる位置です。
  2. +
  3. 終了タグ(Closing tag): 要素名の前に一つのスラッシュが含まれることを除けば、開始タグと同じです。これは要素の終了を宣言しますーこの場合、段落が終わる位置です。終了タグを忘れるのは初心者にありがちなミスで、おかしな結果になってしまいます。
  4. +
  5. 内容(Content): これは要素の内容で、この場合、テキストそのものです。
  6. +
  7. 要素(Element): 開始タグ + 内容 + 終了タグが要素になります。
  8. +
+ +

実習: 最初の HTML 要素を作ってみる

+ +

以下の Input 欄にある行を <em></em> で囲んでください (要素を開始するために行の先頭に <em> を、要素を終了するために行の末尾に </em> をそれぞれ置きます) — これによりその行はイタリック体 (斜体) によって強調表示されるはずです! この変化は Output 欄でリアルタイムで確認できているはずです。

+ +

もし入力ミスをしても、Reset ボタンを押すことでいつでもリセットできます。立ち往生してしまっても Show solution ボタンを押せばいつでもカンニングできます。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 300, "", "", "hide-codepen-jsfiddle") }}

+ +

要素のネスト

+ +

要素の中に要素を入れることができますーこれは“ネスト” (入れ子) と呼ばれています。たとえば “My cat is very grumpy.” と記述したい場合、“very” という語を {{htmlelement("strong")}} 要素で囲むことができ、それはその語がより強く強調表示されることを意味します:

+ +
<p>My cat is <strong>very</strong> grumpy.</p>
+ +

ただし、要素が正しくネストされていることを確認する必要はあります: 上の例では、開始タグは最初に p 要素、その次に strong 要素が来ますから、終了タグは最初に strong 要素を、一番最後に p 要素を置くことになります。次は間違った例です:

+ +
<p>My cat is <strong>very grumpy.</p></strong>
+ +

タグのセットが互いに内側か外側なのかがはっきり分かるように、要素の開始と終了は正しく配置する必要があります。もし上の例のように互いに “掛け違って” しまっている場合、ブラウザーはそのマークアップが本来意図していただろうことを出来るだけ読み取ろうとはしますが、予期しない結果となることは当然に想定されます。ですからこうした “掛け違い” はやめましょう!

+ +

ブロック要素とインライン要素

+ +

HTML の要素には 2 つの重要なカテゴリーがあり、それは知っておくべきことです。すなわち、ブロックレベル要素とインライン要素です。

+ + + +

次の例で考えてみましょう:

+ +
<em>first</em><em>second</em><em>third</em>
+
+<p>fourth</p><p>fifth</p><p>sixth</p>
+
+ +

{{htmlelement("em")}} 要素はインライン要素なので、以下で確認できるように、最初の 3 つの要素は同じ行で他の要素と互いにスペースを空けずにたたずんでいます。一方で、{{htmlelement("p")}} 要素はブロックレベル要素なので、各要素はその上下にスペースを伴った新たな行で表示されます (この間隔はブラウザーが段落に対して適用するデフォルトの CSS のスタイルによるものです)。

+ +

{{ EmbedLiveSample('Block_versus_inline_elements', 700, 200, "", "") }}

+ +
+

注意: HTML5 においては要素カテゴリが再定義されています: 要素のコンテンツ・カテゴリーを見てください。これらの定義は従来のものに比べてより正確で、なおかつ曖昧さが少ないものとなっていますが、一方では、それらは “ブロックレベル要素” と “インライン要素” の対比よりも遥かに理解することが難しくなっています。このため、私たちはここのトピックを通じて従来の分類を堅持するつもりです。

+
+ +
+

注意: このトピックで使っている “ブロック” と “インライン” の用語は CSS ボックスのタイプと同じ名前で混同するでしょう。既定ではこれらは関係ありますが、CSS の表示タイプの変更は要素のカテゴリーを変更しませんし、どの要素が入っているべきでどの要素に入れられるべきかにも影響しません。HTML5 でこの用語が落とされた理由は、このとてもよくある混同を防ぐためです。

+
+ +
+

注意: ブロックレベル要素とインライン要素のリストを含む有用なリファレンスページがあります — ブロックレベル要素インライン要素をご覧ください。

+
+ +

空要素

+ +

全ての要素が上述の開始タグ・コンテンツ・終了タグのパターンに従っているわけではありません。いくつかの要素は 1 つのタグのみで構成され、それは通常、ドキュメント内でそれが含まれている場所に何かを挿入したり埋め込むために使用されます。例えば、以下の {{htmlelement("img")}} 要素はウェブページ上のそれが含まれた場所に 1 つの画像ファイルを埋め込みます:

+ +
<img src="https://raw.githubusercontent.com/mdn/beginner-html-site/gh-pages/images/firefox-icon.png">
+ +

これはページに次の画像を出力するはずです:

+ +

{{ EmbedLiveSample('Empty_elements', 700, 300, "", "", "hide-codepen-jsfiddle") }}

+ +
+

注意: 空要素 (Empty elements) は Void 要素 (Void elements) と呼ばれていることがあります。

+
+ +

属性

+ +

要素は次のように属性(Attribute)を持つこともできます:

+ +

&amp;amp;lt;p class="editor-note">My cat is very grumpy&amp;amp;lt;/p>

+ +

属性は実際のコンテンツの中で表示させたくない「要素に関する追加情報」を保有します。上のケースでは class 属性は、その要素に後でスタイル情報などが適用される対象であることを示すものとして使用できるような、固有の名前を持つことを許容します。

+ +

各属性は次の要件を満たす必要があります:

+ +
    +
  1. 属性名と要素名の間に 1 つの半角スペース (その要素内にすでに 1 つ以上の属性が設定されている場合は、併せて各属性名の間)
  2. +
  3. 属性名とそれに続く等号 (=)
  4. +
  5. 属性値。始端から終端までをクォーテーションマーク (引用符) で囲む
  6. +
+ +

実習: 要素に属性を追加する

+ +

要素のもう一つの例として {{htmlelement("a")}} (これを「アンカー」と言って、テキストの一部を囲んでハイパーリンクにするものです) を考えます。アンカー要素は多くの属性を持つことができますが、例えばこれらのものが使われます:

+ + + +

それでは以下の Input 欄を編集して、あなたの好きなサイトのリンクを張ってみましょう。まず、<a> 要素を追加します。次に、<a> 要素に href 属性と title 属性を追加します。最後に、新しいタブでリンク先を開くために target 属性を追加します。この変化は Output 欄でリアルタイムで確認できているはずです。まずテキストがハイパーリンクに変わります。そのリンクをホバーしてやる (マウスホバー) と title 属性のコンテンツが表示されます。そのリンクをクリックすると href 属性で指定したページに遷移します。要素名と各属性の間に半角スペースを挿入することに気を付けてください。

+ +

もし入力ミスをしても、Reset ボタンを押すことでいつでもリセットできます。立ち往生してしまっても Show solution ボタンを押せばいつでもカンニングできます。

+ + + +

{{ EmbedLiveSample('Playable_code2', 700, 360, "", "", "hide-codepen-jsfiddle") }}

+ +

真偽値属性

+ +

沢山の HTML ソースを見ていくうちに、属性値のない属性を発見するでしょう。このことは文法的に許されています。こういった属性のことを「真偽値属性」と言います。真偽値属性は一般的に属性名と同じ属性値だけを取ることができます。例えば、input 要素の {{htmlattrxref("disabled", "input")}} 属性は真偽値属性ですが、下記のように記述した場合、 input 要素が "使用不可能に" (disabled, グレーアウト表示) なり、データを入力することができなくなります。

+ +
<input type="text" disabled="disabled">
+
+ +

真偽値属性は、略記法として次のように書くことが文法的に許されています。比較のために "使用不可能に" (disabled, グレーアウト表示) しなかった場合の input 要素も併記しています。

+ +
<input type="text" disabled>
+
+<input type="text">
+ +

上記の HTML コードの結果は下記のようになります。

+ +

{{ EmbedLiveSample('Boolean_attributes', 700, 50, "", "", "hide-codepen-jsfiddle") }}

+ +
+

訳者注:下記の様な真偽値属性の属性名と属性値を一致させない記述は HTML の仕様としては誤りです。このような誤りを防ぐために、真偽値属性の真偽値は必ず省略するようにしましょう。

+ +
<input type="text" disabled="foo bar baz">
+
+
+ +

属性値のクォーテーションマークを省略することについて

+ +

ウェブ (正式にはワールド・ワイド・ウェブ) 上の HTML 文章の中には奇妙なマークアップスタイルで記述されているものもあります。その一つとして、「属性値をクォーテーションマークで囲まない」というのがあります。このスタイルでは正しく動作する場合としない場合があります。先ほどの <a> タグの例で言うと、このような href 属性だけの基本的な使い方では正しく動作します。

+ +
<a href=https://www.mozilla.org/>favourite website</a>
+ +

しかし、例えば次のように半角スペースの入った title 属性を追加すると動作がおかしくなります。

+ +
<a href=https://www.mozilla.org/ title=The Mozilla homepage>favourite website</a>
+ +

この場合だと「title 属性は "The" という属性値を持ち、それとは別に <a>要素が Mozillahomepage という真偽値属性を持つ」というようにブラウザーは誤解します。このように、「属性値をクォーテーションマークで囲まない」ことによる違いは HTML を見ただけでは分からないので、コードのエラーや予期しない動作の原因となります。このコードをブラウザーに解釈させたものを下に用意しましたので、このリンク上をホバーしてツールチップに表示される文字がどうなっているかを確認してみましょう。

+ +

{{EmbedLiveSample('Omitting_quotes_around_attribute_values', 700, 100, "", "", "hide-codepen-jsfiddle") }}

+ +

安全なコードを書くために、必ず属性値にはクォーテーションマークをつけましょう。そうすれば、先ほどのような問題を避けることができ、コードの可読性も向上します。

+ +

ダブルクォートかシングルクォートか?

+ +

この記事では属性を囲むクォーテーションマークとしてすべてダブルクォート ( " ) を使用しています。しかし誰かの HTML でシングルクォート ( ' ) を見ることがあるかもしれません。これは書き方の問題なので、属性値はダブルクォートで囲んでもシングルクォートで囲んでも構いません。例えば次の 2 つの行は等価です。

+ +
<a href="http://www.example.com">A link to my example.</a>
+
+<a href='http://www.example.com'>A link to my example.</a>
+ +

但し、これらを混在させて使うことはできません。次の記述は誤りです。

+ +
<a href="http://www.example.com'>A link to my example.</a>
+ +

属性値をダブルクォートで囲んでいる場合は、その内部でシングルクォートを書くこともできますし、シングルクォートの中でダブルクォートを書くこともできます。

+ +
<a href="http://www.example.com" title="Isn't this fun?">A link to my example.</a>
+ +

ただし、両方の引用符が同じ種類 (一重引用符または二重引用符) の引用符の中に引用符を含める場合は、引用符に HTML エンティティを使用する必要があります。たとえば、これは壊れます:

+ +
<a href='http://www.example.com' title='Isn't this fun?'>A link to my example.</a>
+ +

だからあなたはこのようにする必要があります:

+ +
<a href='http://www.example.com' title='Isn&#39;t this fun?'>A link to my example.</a>
+ +

HTML 文書の構成

+ +

これまで、個々の HTML の要素の基礎を説明しましたが、それら単体ではあまり有用ではありません。ここでは個々の HTML の要素を使って HTML ページを構成する方法を説明していきます。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My test page</title>
+  </head>
+  <body>
+    <p>This is my page</p>
+  </body>
+</html>
+ +

上記の HTML 文書を例に、順に解説していきます。

+ +
    +
  1. +

    <!DOCTYPE html>: いわゆる "doctype" というものです。 HTML の黎明期(1991~1992年あたり)には、 "doctype" というものは HTML の文法セットへのリンクとしての役割を持っていました。当時の "doctype" の記述は自動エラーチェックが容易であるなどの長所も持っていました。当時の "doctype" は、次のようなものでした。

    + +
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    + +

    しかし、今日においては誰も HTML における "doctype" の本来的な役割なんて考えていません。 "doctype" はつじつま合わせのための歴史的な産物です。今日においてには <!DOCTYPE html> は正しい "doctype" と認識させるための最も簡潔な記述です。 "doctype" について、これ以上知る必要はありません。

    +
  2. +
  3. <html></html>: {{htmlelement("html")}} 要素。 HTML 文書は<html>要素 1 つだけからなります。この要素はページ全体であり、<html> タグはページ全体を囲んでいます。<html> 要素はルート要素とも呼ばれます。
  4. +
  5. <head></head>: {{htmlelement("head")}} 要素。この要素は、HTML ページに入れておきたいが見せたくないすべてのものを入れておくコンテナーの働きをします。例えば、検索結果に出したいページのキーワードや説明や、ページのスタイルを指定するための CSS や、文字エンコーディングの定義などが含まれます。より詳しくは、このシリーズの次の記事で詳しく説明します。
  6. +
  7. <meta charset="utf-8">: この要素はこの文書が UTF-8 という文字コードを使用しているということをブラウザーに伝えるためのものです。UTF-8 は世界中の自然言語の大半をカバーしている文字コードです。重要なこととしてあらゆるテキストコンテンツを扱うことができます。文字コードとして UTF-8 を指定しない手はなく、そうしておけば後で説明する問題を回避できます。
  8. +
  9. <title></title>: {{htmlelement("title")}} 要素。これはページのタイトルを指定するもので、ページが読み込まれたブラウザーのタブに表示されます。また、このページをブラウザー上でブックマークしたりお気に入りに追加したりすると <title> 要素の内容がページの説明として使われます。
  10. +
  11. <body></body>: {{htmlelement("body")}} 要素。この中にユーザーがページを訪問した時に表示したいコンテンツ (例えば、テキスト、画像、ビデオ、ゲーム、オーディオトラック等) を記述します。
  12. +
+ +
+

訳者注: 1. の "doctype" は文書型宣言(DTD)と呼ばれております。 HTML 以外のマークアップ言語(XML, SVG, MathML等)においては今日においても重要な意味を持っています。

+
+ +

実習: HTML 文書をカスタマイズする

+ +

もし HTML 文書を書く練習をローカルコンピューターで試したい場合は、次のようにします。

+ +
    +
  1. 上記の HTML ページのコードサンプルの全体を選択して「コピー」します。
  2. +
  3. テキストエディタ上で新規ファイルを作成します。
  4. +
  5. 新規テキストファイルの中で「貼り付け」、または「ペースト」します。
  6. +
  7. index.html という名前でファイルを保存します。
  8. +
+ +
+

脚注: 元となる HTML テンプレートは MDN ラーニングエリア GitHub リポジトリ にも置いてあります。

+
+ +

ウェブブラウザーでこのファイルを開くとレンダリングされた HTML 文書が表示されます。コードを編集した場合は、ブラウザー上でページの更新 (または、再読み込み) を行うと編集結果が反映されます。最初はこんな表示です。

+ +

A simple HTML page that says This is my pageこの実習では、 上に示したようにあなたのコンピューター内部でコード編集してもいいですが、この節の下の方に編集できるフォーム (Input, Output と付されているものです) を使うこともできます。スマートフォンなどで学習する際はこのフォームが役に立つと思います。この節のフォームの Input の部分は、 {{htmlelement("body")}} 要素の中身を表しています。以下の手順を踏んで、ページをカスタマイズしてみましょう。

+ +
+

訳者注: 下記の演習項目は後で詳しく学習できますので、できなくても構いません。

+
+ + + +

間違えた場合は Reset ボタンを押すことで元に戻すことができます。分からない場合は Show solution ボタンを押して答えを見てみましょう。

+ + + +

{{ EmbedLiveSample('Playable_code3', 700, 360, "", "", "hide-codepen-jsfiddle") }}

+ +

HTML 内の空白

+ +

上記の例において、大量の半角スペースが挿入されていることに気づいたかもしれません。大量の半角スペースはあっても無くても構わないものです。次の2つのコードスニペット (それ単体では動作しないコード例のこと) は等価です。

+ +
<p>Dogs are silly.</p>
+
+<p>Dogs        are
+         silly.</p>
+ +

半角スペースをどれ程入力しても (そして、どれ程改行しても)、 HTML パーサはそれを1つの半角スペースとして認識します。ではどうして半角スペースを沢山入力するのでしょうか。それは HTML コードの可読性を向上させるためです。 HTML のコードがいいフォーマット(書式)で記述されていて、1行の中に沢山タグをゴチャゴチャに詰め込まなければ、そのコードの中がどうなっているかが分かりやすくなります。この記事ではインデント(字下げ)として半角スペース2文字分を挿入しています。 HTML のフォーマット(例えば、インデントとして半角スペース何文字分を挿入するのか等)については HTML の書き手によって様々ですが、フォーマットを意識して記述しなければなりません。

+ +
+

訳者注: 全角スペースは、 HTML の文法としては半角スペースや改行とは全く異なる扱いになるので、全角スペースを用いてインデントを行ったりしないでください。また、日本語の文章を段落要素<p>の中で改行すると、半角スペースが挿入されます。

+ +
<p>私は日本人です。
+四季を好みます。</p>
+ +

従って、段落要素(<p>)の中では一切改行はしないでください。ただ、長い文章では段落要素の中身が横に長くなってしまいます。その場合は、テキストエディタで「右端で折り返す」などの設定を行ってみてください。

+ +
<p>私は日本人です。四季を好みます。</p>
+ +

段落要素の中で改行したい場合は、改行要素<br>を用います(文章内の会話や、詩などに用います)。

+ +
<p>彼は言いました。<br>
+「私は日本人です。四季を好みます。」<br>
+私は彼の発した突然の一言にはっと驚きました。</p>
+
+ +

実体参照: HTML に特殊文字を含める

+ +
+

訳者注: HTML エンティティ、実体参照、文字参照、文字実体参照、は、それぞれほぼ同じ意味で用いられます。

+
+ +

HTML では<>"'&の5つの文字は特殊文字と呼ばれています。これら5つの文字は HTML の文法自身の一部です。ではこれらの文字そのものを組版したい場合はどうすればいいのでしょうか。例えば「 You & Me 」や「 x < y 」等の表記をしたい場合です。

+ +

そのような場合は、「文字参照」を使用する必要があります。文字参照とは「文字を表す特別なコード」のことであり、これを使うことで正確な組版を行うことができます。文字参照は必ずアンパサンド (&) で始まり、セミコロン(;)で終わります。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
実際の文字等価な文字参照
<&lt;
>&gt;
"&quot;
'&apos;
&&amp;
+ +

次の例では Web 技術について記述している段落要素を2つ並べています。

+ +
<p>HTML では、<p>要素で段落を定義します。</p>
+
+<p>HTML では、&lt;p&gt;要素で段落を定義します。</p>
+
+ +

上記の例をブラウザーに解釈させたものを下記に出力しています。1つ目の段落の出力が間違っていることが分かるかと思います。2 つ目の <p> を新しい段落の始まりとして認識しているためです。2つ目の段落は正しく出力されています。山括弧(<>)を文字参照に置き換えているためです。

+ +

{{ EmbedLiveSample('Entity_references_Including_special_characters_in_HTML', 700, 200, "", "", "hide-codepen-jsfiddle") }}

+ +
+

脚注: HTML で使用することのできる文字実体参照のリストはこの Wikipedia の記事で確認することができます: List of XML and HTML character entity references.

+
+ +

HTML におけるコメント

+ +

大抵のプログラミング言語同様、HTML においてもコード内にコメントを書くことができます。コメントはブラウザーによって無視されるので、組版には反映されません。コメントの目的としては、 HTML コードがどのように動作するのかや、コードの別の部分がどのように動作するのかを述べるることできます。コメントは、 HTML のコードを書いて半年以上経ってから自分で見返して、自分が何をしたのかを思い出すことができない時に大変有用となります。また、自分のコードを他の人に読んでもらう時にも有用です。

+ +

HTML ファイル内の一部をコメントにするには、その箇所を特別なマーカーの <!----> で囲みます。例えば次のような感じです。

+ +
<p>私はコメントの外にいます。</p>
+
+<!-- <p>私はコメントの中にいます。</p> -->
+ +

下記を見ると、最初の段落は表示されますが、次の段落は表示されないことが分かります。

+ +

{{ EmbedLiveSample('HTML_comments', 700, 100) }}

+ +

要約

+ +

この記事の最後にたどり着きました — HTML のほんの初歩のツアーを楽しんでこられたことを望んでいます!ここではこの言語がどのようなものか、基本的にどうやって動作するのかを理解し、いくつかの要素と属性を書くことができるようになったでしょう。あなたがいる場所は完璧な場所です、続きの記事ではすでに見てきたことをもっと詳細に経験して、いくつか新しい言語機能を紹介します。引き続き注目!

+ +
+

脚注: さて、 HTML についてより深く学習するために CSS (Cascading Style Sheets)の基礎についても理解しておきましょう。 CSS はウェブページのスタイルをカスタマイズするために使用します。具体的には、テキストのフォントや色を変えたり、ページレイアウトを設定したりといったことがあげられます。 HTML と CSS は相互補完、つまり2つで1つです。両方学習するとすぐ気づくでしょう。

+
+ +

関連情報

+ + + +
{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}
+ +

このモジュール内

+ + diff --git a/files/ja/learn/html/introduction_to_html/html_text_fundamentals/index.html b/files/ja/learn/html/introduction_to_html/html_text_fundamentals/index.html new file mode 100644 index 0000000000..c4222a362d --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/html_text_fundamentals/index.html @@ -0,0 +1,717 @@ +--- +title: HTML テキストの基礎 +slug: Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - Introduction to HTML + - Learn + - Text + - headings + - paragraphs + - semantics +translation_of: Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals +--- +
 {{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}
+ +

HTML の役割の 1 つはテキストに構造と意味 ({{glossary("semantics", "セマンティクス")}}ともいう) を与え、ブラウザーが正しく表示できるようにすることです。この記事では {{glossary("HTML")}} を使ってテキストのページを構造化する方法、見出しとパラグラフをつけたり、言葉を強調したり、リストを作ったり、などを説明します。

+ + + + + + + + + + + + +
前提条件:HTML 入門に載っている、基本的な HTML に精通していること。
目的:基本的なテキストページをマークアップして構造や意味を設定する方法を学ぶ — パラグラフ、見出し、リスト、強調、クォーテーションを含む。
+ +

基本: 見出しとパラグラフ

+ +

たいていの構造化されたテキストは見出しとパラグラフで構成されていて、それは物語でも、新聞でも、大学の教科書でも、雑誌などでも、何を読んでいるのかにかかわらずそうです。

+ +

An example of a newspaper front cover, showing use of a top level heading, subheadings and paragraphs.

+ +

構造化されたコンテンツは読み手にとって読みやすく楽しい体験になります。

+ +

HTML では、各パラグラフは {{htmlelement("p")}} 要素で囲む必要があり、次のようです:

+ +
<p>I am a paragraph, oh yes I am.</p>
+ +

それぞれの見出しは見出しの要素に囲まれます:

+ +
<h1>I am the title of the story.</h1>
+ +

6 つの見出し要素があります — {{htmlelement("h1")}}, {{htmlelement("h2")}}, {{htmlelement("h3")}}, {{htmlelement("h4")}}, {{htmlelement("h5")}},  {{htmlelement("h6")}} です。各要素は文書内で別々のコンテンツレベルを表現します; <h1> は主な見出しで、<h2> はサブの見出しで、<h3> はサブのサブの見出しを表して、といったように。

+ +

構造的な階層を実装する

+ +

例として, 物語を考えましょう。 <h1> は物語の題名を表し、<h2> は各章の題名を表し、<h3> は各章の節を表す、といったようでしょう。

+ +
<h1>The Crushing Bore</h1>
+
+<p>By Chris Mills</p>
+
+<h2>Chapter 1: The dark night</h2>
+
+<p>It was a dark night. Somewhere, an owl hooted. The rain lashed down on the ...</p>
+
+<h2>Chapter 2: The eternal silence</h2>
+
+<p>Our protagonist could not so much as a whisper out of the shadowy figure ...</p>
+
+<h3>The specter speaks</h3>
+
+<p>Several more hours had passed, when all of a sudden the specter sat bolt upright and exclaimed, "Please have mercy on my soul!"</p>
+ +

階層が意味を成す限り、関係する要素が何を意味するかは正にあなた次第です。このような構造を作成する際には、いくつかのベストプラクティスを覚えておく必要があります:

+ + + +

なぜ構造が必要なのか?

+ +

この質問に答えるには、text-start.html を見てください — この記事の動作例の開始点です (すてきなハマスのレシピです)。あとの練習で必要になるため、ローカルマシンにこのファイルのコピーを保存します。この文書の本文は現在、複数の部分のコンテンツが入っています — まったくマークアップされていませんが、改行で区切られています (次の行に移るのに Enter/Return を押します)。

+ +

しかし、この文書をブラウザーで開くと、テキストが 1 つの大きな塊に見えるでしょう!

+ +

A webpage that shows a wall of unformatted text, because there are no elements on the page to structure it.

+ +

これはコンテンツの構造を与える要素がないためですので、ブラウザーはどれが見出しでどれが本文かがわかりません。さらには:

+ + + +

このため、コンテンツに構造的なマークアップが必要となります。

+ +

アクティブラーニング: コンテンツに構造を与える

+ +

ライブな実例に飛び込んでみましょう。下記の実例で、入力フィールドの生テキストに要素を与え、出力フィールドに見出しと2つの段落が見えるようにしてみましょう。

+ +

間違えた場合、リセットボタンでいつでもリセットできます。行き詰まったら、「Show solution(答えを見る)」ボタンで回答を見ます。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 400, "", "", "hide-codepen-jsfiddle") }}

+ +

なぜセマンティクスが必要なのか?

+ +

私たちはあらゆる場面でセマンティクスに頼っています。 —私たちは日常にある物の機能が何かを判断するために過去の経験を頼りにします。つまり、私たちは物を見れば、 それがどのような機能をもつかを知っています。  例えば、赤信号は「止まれ」を、「青信号」は「進め」を意味すると期待します。もしも、間違ったセマンティクスを適用すれば、ものごとは一瞬にして扱いにくくなることがあります。(赤を「進め」の意味で使っている国はあるのでしょうか?そんな国がないといいのですが。 )

+ +

同様に、正確な要素を使い、コンテンツに正しい意味や機能、見た目をを与えられているかどうかを確かめる必要があります。この文脈では、{{htmlelement("h1")}} 要素は要素によって囲んだテキストを「ページのトップレベル見出し」の役割 (または意味) にします。

+ +
<h1>This is a top level heading</h1>
+ +

既定では、ブラウザーはヘッダに見えるようにこれを大きなフォントサイズにします (もっとも、CSSを使えばあなたのやりたいようにできますが)。より重要なことは、その意味する値が (上記で述べましたが) サーチエンジンと画面を読む人によって、異なる方法で使われるということです。

+ +

一方、任意の要素をトップレベル見出しのように見せることもできます。以下の例を見てください。

+ +
<span style="font-size: 32px; margin: 21px 0;">Is this a top level heading?</span>
+ +

これは {{htmlelement("span")}} 要素です。これにはセマンティクスはありません。意味を与えずにCSSを適用させたいとき (あるいはJavaScriptで何かをしたいとき)、コンテンツを囲むために使います (このあと、このコースではこの要素についてより多くのことについて発見することになります)。CSS の中にはトップレベル見出しのような見栄えにするために使えるものもあります。しかし、意味的な値はないため、上記で述べたような付加的な恩恵を得ることはできないでしょう。その役割に応じた適切な HTML 要素を使うことは良い考え方です。

+ +

リスト

+ +

さて、リストに目を向けてみましょう。リストは生活のあらゆる場所にあります。買い物のリストから、自分の家にたどり着くために意識することなく毎日従っている経路のリスト、このチュートリアルであなたが見ている説明のリストまであります。Web 上にもリストはどこにでもあり、気にかけるものに応じて、3種類が用意されています。

+ +

順序なし

+ +

順序なしリストは、買い物リストに使うときのように、項目の並びに関係がないものについてマークアップするときに使います。

+ +
milk
+eggs
+bread
+hummus
+ +

すべての順序なしリストは {{htmlelement("ul")}} で開始し、すべてのリストの項目を囲みます。

+ +
<ul>
+milk
+eggs
+bread
+hummus
+</ul>
+ +

最後にリストの項目をそれぞれ {{htmlelement("li")}} (list item)で囲みます。

+ +
<ul>
+  <li>milk</li>
+  <li>eggs</li>
+  <li>bread</li>
+  <li>hummus</li>
+</ul>
+ +

アクティブラーニング: 順序なしリストをマークアップする

+ +

自身の HTML 順序なしリストを作るために下のライブサンプルを編集してみましょう。

+ + + +

{{ EmbedLiveSample('Playable_code_2', 700, 400) }}

+ +

順序つき

+ +

順序付きリストは、以下のような一連の指示のように、項目に順序があるリストのことです。

+ +
Drive to the end of the road
+Turn right
+Go straight across the first two roundabouts
+Turn left at the third roundabout
+The school is on your right, 300 meters up the road
+ +

マークアップの構造は順序なしリストと同じです。違うのは、<ul> の代わりに {{htmlelement("ol")}} 要素でリストの項目をそれぞれ囲まなければならないということです。

+ +
<ol>
+  <li>Drive to the end of the road</li>
+  <li>Turn right</li>
+  <li>Go straight across the first two roundabouts</li>
+  <li>Turn left at the third roundabout</li>
+  <li>The school is on your right, 300 meters up the road</li>
+</ol>
+ +

アクティブラーニング: 順序つきリストをマークアップする

+ +

自身の HTML 順序つきリストを作るために下のライブサンプルを編集してみましょう。

+ + + +

{{ EmbedLiveSample('Playable_code_3', 700, 500) }}

+ +

手をうごかしてみよう: Marking up our recipe page

+ +

この記事のこの時点で、レシピページの例をマークアップするために必要な情報はすべて揃っています。text-start.html 開始ファイルのローカルコピーを保存してそこで作業を行うか、または下記の編集可能な例で実行するかを選択できます。編集した例に記入すると、次にページを開いたときに失われるため、ローカルで実行するのがおそらくよりよいでしょう。どちらにも長所と短所があります。

+ + + +

{{ EmbedLiveSample('Playable_code_4', 700, 500) }}

+ +

立ち往生した場合は、いつでも [ソリューションを表示] ボタンを押すか、github レポジトリの text-complete.html の例をご覧ください。

+ +

入れ子のリスト

+ +

あるリストを別のリストの中に入れ子にしてもまったく問題ありません。いくつかのサブ箇条書きを最上位の箇条書きの下に配置することをお勧めします。 レシピの例から2番目のリストを見てみましょう。

+ +
<ol>
+  <li>Remove the skin from the garlic, and chop coarsely.</li>
+  <li>Remove all the seeds and stalk from the pepper, and chop coarsely.</li>
+  <li>Add all the ingredients into a food processor.</li>
+  <li>Process all the ingredients into a paste.</li>
+  <li>If you want a coarse "chunky" hummus, process it for a short time.</li>
+  <li>If you want a smooth hummus, process it for a longer time.</li>
+</ol>
+ +

最後の2つの箇条書きはそれらの前の箇条書きと非常に密接に関係しているので (それらはその箇条書きの下に収まるサブ命令や選択のように読みます)、それらを自身の順序なしリストの中に入れ子にして現在のリストの中に入れることは意味があります。4番目の箇条書き。 これは次のようになります。

+ +
<ol>
+  <li>Remove the skin from the garlic, and chop coarsely.</li>
+  <li>Remove all the seeds and stalk from the pepper, and chop coarsely.</li>
+  <li>Add all the ingredients into a food processor.</li>
+  <li>Process all the ingredients into a paste.
+    <ul>
+      <li>If you want a coarse "chunky" hummus, process it for a short time.</li>
+      <li>If you want a smooth hummus, process it for a longer time.</li>
+    </ul>
+  </li>
+</ol>
+ +

前のアクティブラーニングの例に戻り、2番目のリストを次のように更新してみてください。

+ +

強調と重要性

+ +

人間の言語では、文の意味を変えるために特定の単語を強調することが多く、特定の単語を何らかの意味で重要または異なるものとしてマークしたい場面がよくあります。HTML は、そのような効果でテキストコンテンツをマークアップすることを可能にするためにさまざまなセマンティック要素を提供します。そしてこのセクションでは、最も一般的なもののいくつかを見ていきます。

+ +

強調

+ +

話されている言葉を強調したいときは、ある言葉を強調して、自分の言っていることの意味を微妙に変えます。同様に、書かれた言語では、イタリック体でそれらを置くことによって単語を強調する傾向があります。たとえば、次の2つの文は意味が異なります。

+ +

I am glad you weren't late.

+ +

I am glad you weren't late.

+ +

最初の文は、その人が遅刻していないことを本当に安心しているように思われます。対照的に、2番目のものは皮肉的または受動的 - 攻撃的に聞こえ、その人が少し遅れて到着したという不快感を表しています。

+ +

HTML では、このようなインスタンスをマークアップするために {{htmlelement("em")}} (強調) 要素を使用します。文書を読みやすくするだけでなく、これらはスクリーンリーダーによって認識され、異なるトーンの音声で話されます。ブラウザではデフォルトでイタリック体になっていますが、純粋にイタリック体にするだけの場合にはこのタグを使用しないでください。そのためには、{{htmlelement("span")}} 要素と CSS、あるいは {{htmlelement("i")}} 要素 (下記参照) を使用します。

+ +
<p>I am <em>glad</em> you weren't <em>late</em>.</p>
+ +

重要性が高い

+ +

重要な言葉を強調するために、話し言葉でそれらを強調し、そして書面でそれらを bold にする傾向があります。例えば:

+ +

This liquid is highly toxic.

+ +

I am counting on you. Do not be late!

+ +

HTML では、このようなインスタンスをマークアップするために {{htmlelement("strong")}} (強い重要性) 要素を使用します。 この文書をより便利にするだけでなく、これらもスクリーンリーダーによって認識され、異なるトーンの音声で話されています。ブラウザではデフォルトで太字のテキストとしてスタイル設定されていますが、太字のスタイルにするだけの場合にはこのタグを使用しないでください。そのためには、{{htmlelement("span")}} 要素といくつかの CSS、あるいは {{htmlelement("b")}} 要素 (下記参照) を使用します。

+ +
<p>This liquid is <strong>highly toxic</strong>.</p>
+
+<p>I am counting on you. <strong>Do not</strong> be late!</p>
+ +

必要に応じて、 strong と emphasis を相互に入れ子にすることができます。

+ +
<p>This liquid is <strong>highly toxic</strong> —
+if you drink it, <strong>you may <em>die</em></strong>.</p>
+ +

アクティブラーニング: 重要にしましょう!

+ +

このアクティブラーニングセクションでは、編集可能な例を示しました。その中で、それらを必要としていると思う言葉に強調と強い重要性を付け加えてみてください。

+ + + +

{{ EmbedLiveSample('Playable_code_5', 700, 500) }}

+ +

イタリック、太字、下線...

+ +

これまで説明してきた要素には明確な意味があります。{{htmlelement("b")}}、{{htmlelement("i")}} および {{htmlelement("u")}} の状況はやや複雑です。CSS がまだ十分にサポートされていないかまったくサポートされていなかった時代に、太字、斜体、または下線付きのテキストを書くことができるようにそれらはできました。このような要素は表示にのみ影響を与え、意味には影響を与えない表示要素として知られていますが、もはや使用されるべきではありません。これまで見てきたように、セマンティクスはアクセシビリティ、SEO などにとって非常に重要だからです。

+ +

HTML5では <b><i><u> が新しい、やや混乱しやすいセマンティックロールで再定義されました。

+ +

最適な経験則は次のとおりです。これ以上適切な要素がない場合に、太字、斜体、または下線で伝統的に伝えられてきたような意味を伝えるために <b><i> または <u> を使用するのが適切です。ただし、アクセシビリティの考え方を守ることは常に重要です。 イタリック体の概念は、スクリーンリーダーを使っている人、またはラテン系のアルファベット以外の書記体系を使っている人にとってはあまり役に立ちません。

+ + + +
+

下線についての親切な警告:人々は下線をハイパーリンクと強く関連付けています。したがって、Web 上では、リンクのみに下線を引くのが最善です。意味的に適切な場合は <u> 要素を使用しますが、CSS を使用してデフォルトの下線を Web 上でより適切なものに変更することを検討してください。以下の例はその方法を示しています。

+
+ +
<!-- scientific names -->
+<p>
+  The Ruby-throated Hummingbird (<i>Archilochus colubris</i>)
+  is the most common hummingbird in Eastern North America.
+</p>
+
+<!-- foreign words -->
+<p>
+  The menu was a sea of exotic words like <i lang="uk-latn">vatrushka</i>,
+  <i lang="id">nasi goreng</i> and <i lang="fr">soupe à l'oignon</i>.
+</p>
+
+<!-- a known misspelling -->
+<p>
+  Someday I'll learn how to <u style="text-decoration-line: underline; text-decoration-style: wavy;">spel</u> better.
+</p>
+
+<!-- Highlight keywords in a set of instructions -->
+<ol>
+  <li>
+    <b>Slice</b> two pieces of bread off the loaf.
+  </li>
+  <li>
+    <b>Insert</b> a tomato slice and a leaf of
+    lettuce between the slices of bread.
+  </li>
+</ol>
+ +

要約

+ +

今はここで終わりとしましょう。 この記事では、HTMLでテキストをマークアップする方法についての優れたアイデアを説明し、この分野で最も重要な要素のいくつかを紹介しました。この分野には、さらに多くのセマンティック要素を網羅する必要があります。この後の「その他のセマンティック要素」の記事で、さらに詳しく説明します。 次回の記事では、Web上で最も重要な要素と思われるハイパーリンクの作成方法について詳しく説明します。

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/html/introduction_to_html/index.html b/files/ja/learn/html/introduction_to_html/index.html new file mode 100644 index 0000000000..6711d0012a --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/index.html @@ -0,0 +1,65 @@ +--- +title: HTML 入門 +slug: Learn/HTML/Introduction_to_HTML +tags: + - CodingScripting + - HTML + - Introduction to HTML + - Landing + - Links + - Structure + - Text + - head + - semantics +translation_of: Learn/HTML/Introduction_to_HTML +--- +
{{LearnSidebar}}
+ +

本来、{{glossary("HTML")}} は、要素で構成される極めてシンプルな言語です。HTMLは、テキストの断片に、文書における他とは異なる意味 (段落なのか?箇条書きなのか?表の一部なのか?) を与え、文書を論理的なセクションに構成し (ヘッダを持つのか?コンテンツを3段組にするのか?ナビゲーションメニューを持つのか?) 、ページに画像や動画のようなコンテンツを貼り付けるために使うことができます。このモジュールでは、これらのうち最初の2つについて紹介し、HTMLを理解する上で知る必要がある基本的な概念や文法について紹介します。

+ +

前提条件

+ +

このモジュールを始めるにあたり、HTML の知識は一切必要ありません。しかし、最低でもコンピューターを利用したり、ウェブを受動的に利用 (つまり単にそれらを見たり、コンテンツを消費する) したりすることについては、慣れ親しんでいるべきです。基本的なソフトウェアをインストールするに挙がっている基本的な作業環境を整えておき、ファイルを扱うにあるような、ファイルを作成して管理する方法についても理解するべきです。これらの記事は両方共に、完全な初心者用のモジュール「Web入門」の一部です。

+ +
+

:自分自身でファイルを作れない環境 (タブレットやその他の端末) で作業する場合、(ほとんどの) コードサンプルは JSBin や Thimble のようなオンラインコーディングプログラムで試すことが可能です。

+
+ +

ガイド

+ +

このモジュールは以下の記事を含んでいます。これらを読むことで、HTMLの基礎理論の全てを学び、スキルを試すのに十分な機会が得られるでしょう。

+ +
+
HTML入門
+
HTML を開始するための、完全な基本を網羅します — 要素、属性やその他の重要な用語を定義します。この用語を聞いたことがあるかもしれませんし、ここが言語に溶け込んでいる所です。また HTML 要素が構成される方法や、典型的な HTML ページが校正される方法を示し、その他の重要な言語機能を説明します。進むにつれ、HTML で遊んでみて、興味が沸いてくるでしょう!
+
Headとは? HTML のメタデータ
+
HTML ドキュメントの Head は、ページが読み込まれてもウェブブラウザーで表示されない部分です。これはページ{{htmlelement("title", "タイトル")}}や、(HTML コンテンツを CSS でスタイリングする場合に) {{glossary("CSS")}} へのリンクや、カスタム favicon や、メタデータ (HTML についてのデータ、例えば誰が書いたかや、文書を記述する重要なキーワードなど) です。
+
HTML テキストの基礎
+
HTML の主な役割の1つは、テキストの意味付け (セマンティクスとしても知られます) で、それによってブラウザーは正しくテキストを表示する方法がわかります。この記事では HTML を使ってテキストブロックを見出しとパラグラフに分けたり、単語を強調/重要にしたり、リストを作成したりする方法を見て行きます。
+
ハイパーリンクを作成する
+
ハイパーリンクは本当に重要です — これはウェブをウェブにしているものです。この記事ではリンクを作成するのに必要な文法を表して、リンクの最も良いやり方を考察します。
+
上級のテキスト整形
+
HTML ではテキスト整形用として、HTML テキストの基礎 の記事で扱ってきてない多くの要素があります。ここでの要素はあまり知られてないですが、知っておくと役立ちます。ここでは引用や、説明リストや、コンピューターのコードや関連するテキスト、下付き上付きや、連絡先情報などのマークアップを学習します。
+
ドキュメントとウェブサイトの構造
+
ページの個々の部分 (例えば「パラグラフ」や「画像」) を定義するのと同様に、ウェブサイトのエリアも (例えば「ヘッダー」、「ナビゲーションメニュー」、「本文のカラム」) HTML で定義されます。この記事では基本的なウェブサイトの構造を計画する方法と、構造を表現する HTML を書く方法を見て行きます。
+
HTMLをデバッグする
+
HTML を書くのは良いですが、うまくいかなくて、コードのエラーが収まらない場合はどうでしょうか?この記事では手助けとなるいくつかのツールを紹介します。
+
+ +

評価

+ +

以下の評価で、上記のガイドにある HTML 基礎の理解をテストできます。

+ +
+
手紙をマークアップする
+
早かれ遅かれ、手紙を書くことを学びます; これはテキストフォーマットの技術をテストするのにも役立ちます!この評価ではマークアップすべき手紙が与えられます。
+
コンテンツページを構造化する
+
この評価では、ヘッダー・フッター・ナビゲーションメニュー・メインコンテンツ・サイドバーを含む、簡単なコンテンツページを構造化する HTML の能力をテストします。
+
+ +

関連情報

+ +
+
Web literacy basics 1
+
HTML 概論のモジュールで話されたたくさんのスキルを見て回ったりテストしたりできる、素晴らしい Mozilla ファウンデーションのコースです。学習者はこの6つのモジュールにて Web について読んだり書いたり参加したりするのに慣れていきます。製作と共同作業を通じて Web の基礎を発見してください。
+
diff --git a/files/ja/learn/html/introduction_to_html/marking_up_a_letter/index.html b/files/ja/learn/html/introduction_to_html/marking_up_a_letter/index.html new file mode 100644 index 0000000000..055a2afb5d --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/marking_up_a_letter/index.html @@ -0,0 +1,105 @@ +--- +title: 手紙をマークアップする +slug: Learn/HTML/Introduction_to_HTML/Marking_up_a_letter +tags: + - Beginner + - CodingScripting + - HTML + - head + - テキスト + - リンク + - 評価 +translation_of: Learn/HTML/Introduction_to_HTML/Marking_up_a_letter +--- +
+
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}
+私たちはみんな遅かれ早かれ手紙を書くことを学びます。 + +

テキストの書式設定のスキルを試すのも便利な例です。この課題では、ハイパーリンクを含む基本的な HTML テキストフォーマットスキルと高度な HTML テキストフォーマットスキルをテストするためにマークアップするための文字が与えられます。さらに HTML <head> コンテンツに対するあなたの慣れをテストします。

+
+ + + + + + + + + + + + +
前提条件:このアセスメントを試みる前に、「HTML を始めよう」、「head には何が入る? HTML のメタデータ」、「HTML テキストの基礎」、「ハイパーリンクの作成」、および「高度なテキスト処理」をすでに読んでおく必要があります。
目的:基本的な HTML テキストの書式設定とハイパーリンクのスキル、および HTML <head> の内容に関する知識をテストします。
+ +

スタートポイント

+ +

この課題を開始するには、マークアップする必要がある生のテキストと、HTML に含める必要がある CSS を入手します。テキストエディタを使用して新しい .html ファイルを作成し、作業を行います (または、JSBinThimble などのサイトを使用して課題を行います)。

+ +

簡単なプロジェクト

+ +

このプロジェクトの場合、あなたの仕事は大学のイントラネットでホストされる必要がある手紙をマークアップすることです。手紙は、大学で働くことへの申し込みに関する研究フェローから博士課程の学生への返事です。

+ +

ブロック/構造セマンティクス

+ + + +

インラインセマンティクス:

+ + + +

ドキュメントの head:

+ + + +

ヒントとコツ

+ + + +

+ +

次のスクリーンショットは、マークアップ後の文字の表示例を示しています。

+ +

Example

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合、採点のために作品を教師/メンターに渡すことができるはずです。もし自己学習しているのであれば、この練習問題についてのディスカッションスレッド、または Mozilla IRC#mdn IRC チャンネルで尋ねることで、非常に簡単にマーキングガイドを入手することができます。最初にエクササイズをしてみてください - 不正をすることによって得られるものは何もありません!

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/introduction_to_html/structuring_a_page_of_content/index.html b/files/ja/learn/html/introduction_to_html/structuring_a_page_of_content/index.html new file mode 100644 index 0000000000..b434a3fea4 --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/structuring_a_page_of_content/index.html @@ -0,0 +1,107 @@ +--- +title: コンテンツページを構造化する +slug: Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content +tags: + - Beginner + - CodingScripting + - HTML + - セマンティクス + - デザイン + - レイアウト + - 学習 + - 構造 + - 評価 +translation_of: Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}
+ +

CSS を使用してレイアウトできるようにコンテンツのページを構成することは、習得が非常に重要なスキルです。そのためこの評価では、ページがどのように表示されるのかを検討し、適切な構造セマンティクスを選択してその上にレイアウトを構築する能力についてテストします。

+ + + + + + + + + + + + +
前提条件:この評価を試みる前に、「ドキュメントとWebサイトの構造」に特に重点を置いて、コースの残りの部分を通してすでに学習していること。
目的:Web ページ構造の知識、および将来のレイアウト設計をマークアップで表現する方法をテストする。
+ +

スタートポイント

+ +

この評価を開始するには、すべての開始アセットを含むzipファイルを入手してください。 zip ファイルには以下が含まれています。

+ + + +

ローカルコンピュータで例を作成するか、あるいは JSBinThimble などのサイトを使用して評価を行います。

+ +

プロジェクト概要

+ +

このプロジェクトでは、あなたの仕事は、バードウォッチング Web サイトのホームページのコンテンツを取得し、それにページレイアウトを適用できるように構造要素を追加することです。持っている必要があるものは:

+ + + +

以下に適したラッパーを追加する必要があります。

+ + + +

また、する必要があることは:

+ + + +

ヒント

+ + + +

+ +

次のスクリーンショットは、マークアップされた後のホームページの外観の例を示しています。

+ +

The finished example for the assessment; a simple webpage about birdwatching, including a heading of "Birdwatching", bird photos, and a welcome message

+ +

評価

+ +

あなたが組織的コースの一環としてこの評価に従っている場合、採点のために作品を教師/メンターに渡すことができるはずです。もしあなたが自己学習しているのであれば、この練習問題についてのディスカッションスレッド、または Mozilla IRC#mdn IRC チャンネルで尋ねることで、非常に簡単にマーキングガイドを入手することができます。最初にエクササイズをしてみてください — 不正をすることによって得られるものは何もありません!

+ +

{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/introduction_to_html/the_head_metadata_in_html/index.html b/files/ja/learn/html/introduction_to_html/the_head_metadata_in_html/index.html new file mode 100644 index 0000000000..15394f6e79 --- /dev/null +++ b/files/ja/learn/html/introduction_to_html/the_head_metadata_in_html/index.html @@ -0,0 +1,292 @@ +--- +title: head には何が入る? HTML のメタデータ +slug: Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML +tags: + - Beginner + - CodingScripting + - Guide + - HTML + - Meta + - favicon + - head + - lang + - metadata +translation_of: Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}
+ +

HTML の文書の {{glossary("Head", "head")}} 部分は、ページが読み込まれてもウェブブラウザーには表示されない部分です。この部分には、例えば、 {{htmlelement("title")}} といった情報や {{glossary("CSS")}} へのリンク (もし HTML を CSS で修飾したいならば)、独自のファビコンへのリンク、そしてほかのメタデータ (HTML を誰が書いたのかとかその HTML を表現する重要なキーワードなど) の情報を含んでいます。この記事では、上記のすべてのことと、さらに、読者にマークアップ言語と頭に入れておくべきほかのコードについてよい基礎を与えます。

+ + + + + + + + + + + + +
前提知識:基本的な HTML の知識。 HTML を始めようで扱うようなもの。
目的:HTML の head について学ぶこと。 head の目的は何か、そして head が含む情報の中で最も重要なのは何か、加えてそれが HTML 文書の中でどれほどの影響を持つか。
+ +

HTML の head とは何か?

+ +

前の記事で扱った HTML 文書をもう一度見てみましょう。

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>My test page</title>
+  </head>
+  <body>
+    <p>This is my page</p>
+  </body>
+</html>
+ +

HTML の head は {{htmlelement("head")}} 要素のコンテンツです — {{htmlelement("body")}} 要素のコンテンツ (これはブラウザーに読み込まれた時に表示されます) とは違っていて、head のコンテンツはページに表示されません。その代わり、head の仕事は文書の {{glossary("Metadata", "メタデータ")}} を含んでいます。上記の例では、head はとても小さいです。

+ +
<head>
+  <meta charset="utf-8">
+  <title>My test page</title>
+</head>
+ +

しかし、大きなページでは、 head にたくさんの項目があることもあります — お気に入りのウェブサイトに移動して、ウェブ開発ツールを使って head コンテンツを確認してみます。ここでの狙いは head に置くことのできるすべての使い方を示すことではなく、むしろ head に入れたくなるのが最も明らかなものの使い方を教えて、なじんでもらうことです。始めましょう。

+ +

タイトルをつける

+ +

{{htmlelement("title")}} 要素についてはすでに見てきました — これは文書にタイトルを追加するのに使います。しかしこれは {{htmlelement("h1")}} 要素 (これは body コンテンツの最上位レベルの見出し(head)を追加します — 時々ページタイトルとしても参照されます) と混同されます。しかしこれらは別のものです!

+ + + +

アクティブラーニング: 単純な例を検討する

+ +
    +
  1. このアクティブラーニングを始めるのに、我々の GitHub リポジトリに移動して title-example.html page のコピーをダウンロードして頂きたいです。これは次のいずれかでできます + +
      +
    1. ページのコードをコピー&ペーストして、コードエディターの新規ファイルに入れて、ふさわしい場所に保存します
    2. +
    3. ページの "Raw" を押すと、新しいタブに生のコードが出ます。次に、ブラウザーメニューから ファイル > 名前を付けて保存... を選んで、ファイルの保存場所を選びます
    4. +
    +
  2. +
  3. ファイルをブラウザーで開きます。このようなものが見えるでしょう: +

    A simple web page with the title set to <title> element, and the <h1> set to <h1> element.<h1> コンテンツが出ている場所と、<title> コンテンツが出ている場所がひと目で分かります!

    +
  4. +
  5. 自分のコードエディターで開いて、この要素を編集して、ブラウザーで再読み込みしてもよいです。楽しんでみてください。
  6. +
+ +

<title> 要素はいろいろな方法で使われます。例えば、ページのブックマーク (ブックマーク > このページをブックマーク または Firefox の URL バーのスターアイコンにて) してみると、提案されたブックマーク名として <title> コンテンツが記入されています。

+ +

A webpage being bookmarked in firefox; the bookmark name has been automatically filled in with the contents of the <title> element

+ +

<title> の内容は後述するように、コンテンツは検索結果にも使われます。

+ +

メタデータ: <meta>要素

+ +

メタデータはデータを説明するデータで、 HTML には文書にメタデータを追加する「公式な」方法があります — {{htmlelement("meta")}} 要素です。もちろん、この記事で話しているその他のものもメタデータと考えられます。ページの <head> に入る <meta> 要素にはさまざまな種類がありますが、この段階では、ややこしすぎるため、すべては説明しません。その代わり、よく見かけるいくつかのものを説明し、理解を与えます。

+ +

HTML文書の文字コードを指定する

+ +

上で見てきた例では、この行が含まれていました。

+ +
<meta charset="utf-8">
+ +

この要素は単に文書のキャラクターエンコーディングを指定しています — それは文書が使うことが許されるキャラクターセットです。utf-8 はあらゆる言語からとてもたくさんの文字を含む汎用的なキャラクターセットです。つまりウェブページがあらゆる言語の表示を取り扱えるのです; このため、作成するすべてのウェブページにこれをセットするのが良いです!例えば、ページで英語と日本語を正しく扱うことができます:

+ +

a web page containing English and Japanese characters, with the character encoding set to universal, or utf-8. Both languages display fine,文字エンコーディングを、例えば ISO-8859-1 (ラテン文字のアルファベットの文字セット) に指定すると、ページの表示はメチャクチャな見た目になります。

+ +

a web page containing English and Japanese characters, with the character encoding set to latin. The Japanese characters don't display correctly

+ +
+

メモ: ブラウザーによっては (例 Chrome) 自動的に正しくないエンコーディングを修正しますので、お使いのブラウザーによっては、この問題が見られないこともあります。それでもなお、その他のブラウザーでの問題を避けるため、とにかくページに utf-8 エンコーディングを設定すべきです。

+
+ +

アクティブラーニング: 文字エンコーディングで実験する

+ +

これを試すには、<title> についての前の節で得たシンプルな HTML テンプレート (title-example.html page) をもう一度見てみて、 meta charset の値を ISO-8859-1 に変えて、日本語を追加してみます。私達の使ったコードは次のものです:

+ +
<p>Japanese example: ご飯が熱い。</p>
+ +

作成者と説明を追加する

+ +

多くの <meta> 要素は namecontent 属性が含まれます:

+ + + +

ページに入れるのが便利な 2 つのメタ要素は、ページの著者(author)を定義するものと、ページの説明(description)を与えるものです。例を見てみます:

+ +
<meta name="author" content="Chris Mills">
+<meta name="description" content="The MDN Web Docs Learning Area aims to provide
+complete beginners to the Web with all they need to know to get
+started with developing web sites and applications.">
+ +

著者 (author) の指定はいくつかの点で役立ちます。コンテンツに関する質問があって問い合わせしたい場合、誰がそのページを書いたのかに答えられます。 CMS (コンテンツ管理システム) によっては自動的にページの作者の情報を抽出して、このような目的で利用するための機能があります。

+ +

ページの内容に関連したキーワードを含む説明 (description) を指定すると、検索エンジンで行われる関連検索で、ページをより上位にできる可能性があるため役立ちます (この行為に対する用語は Search Engine Optimization (検索エンジン最適化) または {{glossary("SEO")}}といいます)。

+ +

アクティブラーニング:検索エンジンにおける description の扱い

+ +

description は検索エンジンの結果ページにも使われます。練習でこれを見ていきましょう。

+ +
    +
  1. Mozilla Developer Network のフロントページに移動します。
  2. +
  3. ページのソースを見ます (ページ上で右クリックまたは Ctrl を押しながらクリックして、コンテキストメニューからページのソースを表示を選びます)。
  4. +
  5. description の meta タグを見てみます。それはこのようなものです。 +
    <meta name="description" content="The MDN Web Docs site
    +  provides information about Open Web technologies
    +  including HTML, CSS, and APIs for both Web sites and
    +  progressive web apps.">
    +
  6. +
  7. ここでお好きな検索エンジンで "MDN Web Docs" を検索します (ここでは Google を使っています) 。 description の <meta><title> 要素のコンテンツが検索結果で使われています — 確かに値打ちがあります。 +

    A Yahoo search result for "Mozilla Developer Network"

    +
  8. +
+ +
+

メモ: Google ではメインの MDN ホームページリンクの下にいくつか MDN Web Docs のサブページが見えるでしょう— これはサイトリンクと呼ばれ、Google's webmaster tools で設定されます — これは Google 検索エンジンでサイトの検索結果を良くする方法です。

+
+ +
+

: 多くの <meta> 機能はもう使われていません。例えば、 keyword の <meta> 要素 (<meta name="keywords" content="fill, in, your, keywords, here">) — 検索エンジンが色々な検索用語と関連するページを決めるためのキーワードを与えると考えられています — は、スパマーが結果にバイアスをかける多数のキーワードを埋めるだけなので、検索エンジンから無視されます。

+
+ +

メタデータの他の種類

+ +

ウェブを旅するにつれ、他の種類のメタデータも見つかるでしょう。ウェブサイトで見る多くの機能はプロプライエタリな作成物で、使うことのできる特定の情報をあるサイト (例えば SNS) に与えます。

+ +

例えば、 Open Graph Data は Facebook が開発した、ウェブサイトに豊富なメタデータを与えるメタデータプロトコルです。 MDN Web Docs のソースコードでは、次のようなものがあります。

+ +
<meta property="og:image" content="https://developer.cdn.mozilla.net/static/img/opengraph-logo.dc4e08e2f6af.png">
+<meta property="og:description" content="The Mozilla Developer Network (MDN) provides
+information about Open Web technologies including HTML, CSS, and APIs for both Web sites
+and HTML5 Apps. It also documents Mozilla products, like Firefox OS.">
+<meta property="og:title" content="Mozilla Developer Network">
+ +

この効果として、 facebook で MDN Web Docs にリンクしたとき、リンクに画像と説明が表示されます。ユーザーにとってより便利になります。

+ +

Open graph protocol data from the MDN homepage as displayed on facebook, showing an image, title, and description.Twitter も同様のプロプラエタリなメタデータを持ちます。 URL が twitter.com で表示される時に同様な効果となります。例えば。

+ +
<meta name="twitter:title" content="Mozilla Developer Network">
+ +

サイトに自分の好きなアイコンをつける

+ +

もっとサイトデザインを豊かにするために、メタデータにカスタムアイコンを追加して、特定のコンテキストで表示されるようにすることができます。このうち最もよく使われるものが ファビコン (ブラウザーの「お気に入り」や「ブックマーク」の一覧を指すために使われる "favorites icon" の略) です。

+ +

つつましいファビコンは何年も使われてきています。16ピクセル四方のアイコンが最初の種類であり、様々な場所で使われました。各ページを開いているブラウザータブの中や、ブックマークパネル内のブックマークページの隣でファビコン表示が見られるでしょう。

+ +

ページにファビコンを追加するには:

+ +
    +
  1. サイトの index ページと同じディレクトリに、 .ico 形式で保存します (大半のブラウザーは .gif.png のような、より一般的な形式のファビコンにも対応していますが、 ICO 形式を使えば Internet Explorer 6 以降の古いブラウザでも動作することが保証されます)。
  2. +
  3. HTML の {{HTMLElement("head")}} ブロックに下記の行を入れて参照します。 +
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    +
  4. +
+ +

ブックマークパネルでファビコンが表示される例です。

+ +

The Firefox bookmarks panel, showing a bookmarked example with a favicon displayed next to it.

+ +

最近では考慮するべきアイコンの種類がほかにもたくさんあります。例えば、 MDN Web Docs ホームページのソースコードには以下の行があります。

+ +
<!-- third-generation iPad with high-resolution Retina display: -->
+<link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://developer.cdn.mozilla.net/static/img/favicon144.a6e4162070f4.png">
+<!-- iPhone with high-resolution Retina display: -->
+<link rel="apple-touch-icon-precomposed" sizes="114x114" href="https://developer.cdn.mozilla.net/static/img/favicon114.0e9fabd44f85.png">
+<!-- first- and second-generation iPad: -->
+<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://developer.cdn.mozilla.net/static/img/favicon72.8ff9d87c82a0.png">
+<!-- non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
+<link rel="apple-touch-icon-precomposed" href="https://developer.cdn.mozilla.net/static/img/favicon57.a2490b9a2d76.png">
+<!-- basic favicon -->
+<link rel="shortcut icon" href="https://developer.cdn.mozilla.net/static/img/favicon32.e02854fdcf73.png">
+ +

コメントはそれぞれのアイコンの用途を説明しています。 — この要素は、ウェブサイトが iPad のホーム画面に保存された時のすばらしい高解像度なアイコンの提供といったことをカバーしています。

+ +

こうした種類のアイコンをいますぐすべて実装することに心配しすぎないでください — これはかなり高度な機能で、このコースが進んでも分からないはずです。ここでの主な目的は、他のウェブサイトのソースコードを見た時に出くわした場合にこれらが何か知ることです。

+ +
+

メモ: もし、サイトがセキュリティを向上させるために Content Security Policy (CSP) を使用している場合、ポリシーがファビコンに適用されます。ファビコンが読み込まれないという問題に遭遇したら、 {{HTTPHeader("Content-Security-Policy")}} ヘッダーの img-src ディレクティブがアクセスを妨害していないかを確認してください。

+
+ +

HTML に CSS と JavaScript を追加する

+ +

最近のほとんどすべてのウェブサイトでは、格好よく見せるために {{glossary("CSS")}} や動画や地図、ゲームなどといったインタラクティブな機能を追加するために {{glossary("JavaScript")}} を用いています。これらは最も一般的に用いられ、それぞれ {{htmlelement("link")}} 要素、 {{htmlelement("script")}} 要素で表します。

+ + + +

アクティブラーニング: ページに CSS と JavaScript を追加する

+ +
    +
  1. アクティブラーニングを始めるにあたって、私たちの meta-example.html, script.js ,style.css をコピーしてローカルの同じフォルダに保存してください。ファイル名と拡張子が変わっていないことを確認してください。
  2. +
  3. HTML ファイルをブラウザとテキストエディタで開いてください。
  4. +
  5. 先に述べた情報に従って、 {{htmlelement("link")}} 要素と {{htmlelement("script")}} 要素を HTML に書き加えてください。すると CSS と JavaScript が HTML に適用されます。
  6. +
+ +

以上を正しく行い、 HTML を保存してブラウザを更新したら、変化がみられるでしょう。

+ +

Example showing a page with CSS and JavaScript applied to it. The CSS has made the page go green, whereas the JavaScript has added a dynamic list to the page.

+ + + +
+

メモ: この演習で行きづまって CSS/JS が適用できなくなってしまった場合は、 css-and-js.html サンプルページをチェックしてみてください。

+
+ +

文書の主要な言語の設定

+ +

最後に、ページの言語を設定することができること (そしてそうすべきこと) に言及する価値があるでしょう。これは、 lang 属性を開始 HTML タグに追加することで実現することができます (meta-example.html に表示され、以下に表示されています)。

+ +
<html lang="en-US">
+ +

これは様々なところで役に立ちます。言語が設定されていれば、 検索エンジンによるHTML 文書のタグ付けがより効果的になりますし (たとえば、言語固有の結果を正しく表示できるようになるなど)、読み上げソフトを使用している視覚障碍者にとっても有用です ("six" はフランス語と英語の両方に存在しますが、発音が異なります)。

+ +

文書のサブセクションを異なる言語として認識されるように設定することもできます。たとえば、次のようにすると日本語のセクションを日本語として認識されるように設定できます。

+ +
<p>Japanese example: <span lang="ja">ご飯が熱い。</span>.</p>
+ +

これらのコードは ISO 639-1 規格で定義されています。それらについての詳細は、 HTML と XML の言語タグにあります。

+ +

まとめ

+ +

これで HTML head の弾丸ツアーは終了します。ここでできることは他にもたくさんありますが、この段階では徹底的なツアーでは退屈で混乱を招くことになるでしょうから、もっとも一般的なことに関する考えだけを紹介したかったのです。たった今、そこに到達しました。次回の記事では、HTML テキストの基礎について説明します。

+ +

{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html b/files/ja/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html new file mode 100644 index 0000000000..3431a47258 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html @@ -0,0 +1,370 @@ +--- +title: ウェブにベクターグラフィックスを追加する +slug: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +tags: + - Beginner + - Graphics + - Guide + - HTML + - Images + - Learn + - Raster + - SVG + - Vector + - iframe + - img + - ガイド + - グラフィックス + - ベクター + - ラスター + - 初心者 + - 学習 + - 画像 +translation_of: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}
+ +
+

ベクターグラフィックは多くの状況でとても便利です。 — ファイルサイズは小さく、スケーラビリティが高いため、ズームイン (拡大表示) したり、大きなサイズに拡大したりしてもモザイクになりません。この記事では、ウェブページにそれを組み込む方法を説明します。

+
+ + + + + + + + + + + + +
前提条件:HTML の基本と、画像を文書に挿入する方法を理解しておく必要があります。
目的:SVG (ベクター) 画像をウェブページに埋め込む方法を学びます。
+ +
+

メモ: この記事は SVG を教えるためのものではありません。 SVG が何であるかと、ウェブページに追加する方法について説明します。

+
+ +

ベクターグラフィックとは何か?

+ +

ウェブ上では、ラスター画像とベクター画像の2種類の画像を扱います。

+ + + +

両者の違いを知るために、例を見てみましょう。この例は、 Github のリポジトリで vector-versus-raster.html として公開されています。 — これは、2つの一見同一の黒い影付きの赤い星の画像を並べて表示しています。違いは、左のものが PNG 画像であり、右のものが SVG 画像であるということです。

+ +

この違いは、ページをズームインすると明らかになります。 PNG 画像には、各ピクセルの位置(と色)に関する情報が含まれているため、ズームインするとピクセル化されます。 ズームインすると、各ピクセルのサイズが単純に拡大され、画面上の複数のピクセルが塗りつぶされるので、画像がギザギサに見えるようになります。 しかし、ベクター画像は大きさにかかわらず、アルゴリズムが画像内のシェイプを処理するために使用され、値が大きくなるにつれて単純に縮尺が変更されるため、きれいにくっきりと見えます。

+ +

2つの星の画像

+ +

2つの星の画像が拡大表示され、1つがくっきりになり、他の画像がギザギサになる

+ +
+

メモ: 上の画像は実際には全て PNG です — いずれの場合も、左の星はラスター画像を表し、右の星はベクター画像を表します。 実際の例については、vector-versus-raster.html デモを参照してください!

+
+ +

さらに、ベクター画像ファイルは、画像内のすべてのピクセルの情報ではなく、一握りのアルゴリズムを保持するだけで済むので、ラスター同等物よりもはるかに軽くなります。

+ +

SVG とは何か?

+ +

SVG は、ベクター画像を記述するための {{glossary("XML")}} ベースの言語です。これは基本的に HTML のようなマークアップですが、画像に表示するシェイプを定義するためのさまざまな要素と、それらのシェイプに適用する効果があります。 SVG は、コンテンツではなくグラフィックをマークアップするためのものです。最も単純なものとしては、 {{svgelement("circle")}} や {{svgelement("rect")}} のような単純なシェイプを作成するための要素があります。 {{svgelement("feColorMatrix")}} (変換行列を使用して色を変換)、 {{svgelement("animate")}} (ベクターグラフィックの一部をアニメーション化)、 {{svgelement("mask")}} (画像の上にマスクを適用する) など、より高度な SVG の機能もあります。

+ +

簡単な例として、次のコードは円形と長方形を作成します。

+ +
<svg version="1.1"
+     baseProfile="full"
+     width="300" height="200"
+     xmlns="http://www.w3.org/2000/svg">
+  <rect width="100%" height="100%" fill="black" />
+  <circle cx="150" cy="100" r="90" fill="blue" />
+</svg>
+ +

これにより、次の出力が生成されます。

+ +

{{ EmbedLiveSample('What_is_SVG', 300, 200, "", "", "hide-codepen-jsfiddle") }}

+ +

上記の例から、 SVG が手作業で簡単に書けるという印象を受けるかもしれません。実際、単純な SVG ならばテキストエディターで手作業で記述することはできますが、複雑な画像では、すぐにとても困難になり始めます。 SVG 画像を作成するには、ほとんどの人が InkscapeIllustrator のようなベクターグラフィックエディターを使用します。これらのパッケージでは、さまざまなグラフィックツールを使用してさまざまなイラストを作成したり、写真に近似したもの (たとえば、 Inkscape のトレースビットマップ機能) を作成したりすることができます。

+ +

SVG にはこれまで説明したもの以外にも、いくつかの長所があります。

+ + + +

では、なぜ誰もが SVG よりもラスターグラフィックを使いたがるのでしょうか?実際、SVG にはいくつかの短所があります。

+ + + +

ラスターグラフィックは、前述の理由から、写真などの複雑な高精度画像に対しては、ほぼ間違いなく優れています。

+ +
+

メモ: Inkscape では、スペースを節約するためにファイルを Plain SVG として保存します。 また、ウェブ用の SVG を作成する方法について説明しているこの記事 (英語) を参照してください。

+
+ +

ページへの SVG の追加

+ +

この節では、SVG ベクターグラフィックをウェブページに追加するさまざまな方法を説明します。

+ +

簡単な方法: {{htmlelement("img")}}

+ +

{{htmlelement("img")}} 要素を介して SVG を埋め込むには、予想通り、 src 属性で参照する必要があります。 height 属性または width 属性 (または SVG に固有のアスペクト比がない場合は両方) が必要です。まだHTML の画像を終了していない人は、こちらをお読みください。

+ +
<img
+    src="equilateral.svg"
+    alt="3辺がすべて等しい三角形"
+    height="87px"
+    width="100px" />
+ +

長所

+ + + +

短所

+ + + +

トラブルシューティングとクロスブラウザーの対応

+ +

SVG に対応していないブラウザー (IE 8 以前、Android 2.3 以前) では、 src 属性から PNG または JPG を参照し、 SVG を参照するために {{htmlattrxref("srcset", "img")}} 属性 (最近のブラウザーのみが認識する) を使用することができます。 この場合、対応しているブラウザーのみが SVG を読み込みます。 — 古いブラウザーは代わりに PNG を読み込みます。

+ +
<img src="equilateral.png" alt="辺が等しい三角形" srcset="equilateral.svg">
+ +

以下に示すように、 SVG を CSS の背景画像として使用することもできます。 以下のコードでは、古いブラウザーでは理解できる PNG を使用しますが、新しいブラウザーでは SVG を読み込みます。

+ +
background: url("fallback.png") no-repeat center;
+background-image: url("image.svg");
+background-size: contain;
+ +

上記の <img> 方式と同様に、 CSS 背景画像を使用して SVG を挿入すると、 SVG を JavaScript で操作することができず、同じ CSS の制限が適用されます。

+ +

SVG がまったく表示されない場合は、サーバーが正しく設定されていない可能性があります。 それが問題なら、この記事が正しい方向を指しています

+ +

HTML の中に SVG コードを組み込む方法

+ +

テキストエディターで SVG ファイルを開き、 SVG コードをコピーして HTML 文書に貼り付けることもできます。 これは、SVG をインラインにする、または SVG をインライン化するとも呼ばれます。 SVG コードスニペットは、{{svgelement("svg")}} タグで始まり、 <svg></svg> タグで終わることを確認してください (これら以外のものは含めないでください)。文書に貼り付けることのできる簡単な例を次に示します。

+ +
<svg width="300" height="200">
+    <rect width="100%" height="100%" fill="green" />
+</svg>
+
+ +

長所

+ + + +

短所

+ + + + + +

{{htmlelement("iframe")}} で SVG を埋め込む方法

+ +

SVG 画像は、ウェブページのようにブラウザーで開くことができます。 したがって、SVG 文書を <iframe> に埋め込むことは、<object> から <iframe> へ — その他の埋め込み技術で学んだように行われます。

+ +

ここで簡単なレビューです。

+ +
<iframe src="triangle.svg" width="500" height="500" sandbox>
+    <img src="triangle.png" alt="3つの不等辺の三角形" />
+</iframe>
+ +

これは間違いなく選択するには最良の方法ではありません。

+ +

短所

+ + + +

アクティブラーニング: SVG で遊ぶ

+ +

このアクティブラーニングの節では、 SVG をとても楽しく遊ぶことができます。 下の入力セクションでは、始めるためのサンプルをすでに提供していることがわかります。 また、SVG 要素のリファレンスにアクセスして、SVG で使用できる他のおもちゃの詳細を調べて、それらを試してみることもできます。 このセクションでは、あなたの研究スキルを鍛え、楽しく学びましょう。

+ +

コードが機能しなくなった場合は、[Reset] ボタンを使用していつでもリセットすることができます。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 500, "", "", "hide-codepen-jsfiddle") }}

+ +

まとめ

+ +

この記事では、ベクターグラフィックと SVG の概要、それらをなぜ知っておくと便利なのか、そして SVG をウェブページに組み込む方法について簡単に説明しました。 SVG を学ぶ上での完全なガイドとなることは決して考えられていませんでしたが、ウェブ上の旅行でそれに会っていれば、SVG が何であるかを知ることができます。 あなたがまだ SVG のエキスパートではないと感じたら心配しないでください。 もしそれがどう動くかについて詳しく知りたいなら助けになる以下のリンクを参考にしてください。

+ +

このモジュールの最後の記事では、レスポンシブ画像を詳細に調査し、さまざまなデバイス間で画像をより良く動作させるための HTML ツールについて説明します。

+ +

関連項目

+ + + +

{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/html/multimedia_and_embedding/images_in_html/index.html b/files/ja/learn/html/multimedia_and_embedding/images_in_html/index.html new file mode 100644 index 0000000000..4d5e14ae4f --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/images_in_html/index.html @@ -0,0 +1,521 @@ +--- +title: HTML の画像 +slug: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +tags: + - Beginner + - Guide + - HTML + - Image + - alt text + - captions + - figcaption + - figure + - img + - ガイド + - キャプション + - 代替テキスト + - 初心者 + - 図表 + - 画像 + - 記事 +translation_of: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}
+ +

最初は、Web は単なるテキストに過ぎず、とても退屈でした。幸運なことに、Web ページ内に画像 (および他のより興味深いタイプのコンテンツ) を埋め込む能力が追加されるまでにはあまり時間がかかりませんでした。考慮すべき他のタイプのマルチメディアもありますが、単純な画像を Web ページに埋め込むために使用される、慎ましい {{htmlelement("img")}} 要素から始めるのが理にかなっています。この記事では、基本的な使い方を含め、{{htmlelement("figure")}} を使ったキャプションの注釈付け、{{glossary("CSS")}} 背景画像との関連付けなど、詳細な使い方を見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータリテラシー、インストールされた基本ソフトウェアファイル操作の基本知識、HTML の基礎知識に精通していること (HTML の使い方を参照してください)。
目的:単純な画像を HTML に埋め込み、キャプションで注釈を付ける方法、および HTML 画像と CSS 背景画像との関連を学ぶ。
+ +

画像を Web ページにどのように置くのですか?

+ +

単に画像を Web ページに配置するには、{{htmlelement("img")}} 要素を使用します。これは有用であるために少なくとも1つの属性 — src (フルタイトルやソースと呼ばれることもあります) を必要とする {{glossary("empty element","空要素")}} (テキストコンテンツまたは終了タグがないことを意味する) です。src 属性には、{{htmlelement("a")}} 要素の href 属性値と同じように、ページに埋め込む画像を指すパスが含まれ、相対 URL または絶対 URL にすることができます。

+ +
+

メモ: 続行する前に、URL とパスに関する簡単な入門を読んで、相対 URLと絶対 URL のメモリを更新してください。

+
+ +

例えば、画像が dinosaur.jpg というファイル名で、HTML ページと同じディレクトリにある場合、画像を次のように埋め込むことができます。

+ +
<img src="dinosaur.jpg">
+ +

画像が HTML ページ (Google が {{glossary("SEO")}}/索引付けの目的で推奨するディレクトリ) 内の images サブディレクトリにあった場合は、次のように埋め込みます。

+ +
<img src="images/dinosaur.jpg">
+ +

等々。

+ +
+

メモ: 検索エンジンは画像ファイル名も読み込み、SEO に向けて数えます。したがって、画像にわかりやすいファイル名を付けてください。dinosaur.jpgimg835.png よりも優れています。

+
+ +

たとえば、絶対 URL を使用して画像を埋め込むことができます。

+ +
<img src="https://www.example.com/images/dinosaur.jpg">
+ +

しかし、これは無意味だけでなく、ブラウザが DNS サーバから IP アドレスを再度検索するなどより多くの作業をすることになります。ほとんどの場合、Web サイトの画像を HTML と同じサーバに保存します。

+ +
+

警告: ほとんどの画像は著作権で保護されています。次の場合を除き、Web ページに画像を表示しないでください。
+
+ 1) 画像を所有している
+ 2) 画像の所有者からの書面による明示的な許可を得ている、または
+ 3) 画像は、実際にパブリックドメインであるという十分な証拠がある。
+
+ 著作権侵害は違法で非倫理的です。加えて、あなたがリンクする権限を持たない他の誰かの Web サイトでホストされている画像へあなたの src 属性を向けないでください。これは「ホットリンク」と呼ばれます。さらに、誰かの帯域幅を盗むことは違法です。また、ページが遅くなり、画像が削除されたり、恥ずかしいものに置き換えられたりするかどうかを制御できません。

+
+ +

上のコードでは、次の結果が得られます。

+ +

恐竜の基本的な画像が、ブラウザに埋め込まれ、その上に "Images in HTML" が書かれています

+ +
+

メモ: {{htmlelement("img")}} や {{htmlelement("video")}} のような要素は、置き換えられた要素と呼ばれることがあります。これは、要素の内容とサイズが、要素自体の内容ではなく、外部リソース(画像ファイルや動画ファイルなど)によって定義されているためです。

+
+ +
+

メモ: 完成したサンプルは、このセクションの Github で実行するから見つけることができます (ソースコードも参照してください)。

+
+ +

代替テキスト

+ +

次の属性は alt です。その値は、画像が見えない/表示されない状況で使用するためにあり、画像のテキスト記述であると考えられる。たとえば、上記のコードは次のように変更できます。

+ +
<img src="images/dinosaur.jpg"
+     alt="恐竜の骨格の頭と胴体、
+          それは長い鋭い歯を持つ大きな頭を持っています">
+ +

alt テキストをテストする最も簡単な方法は、意図的にファイル名のスペルミスをすることです。たとえば、画像名のスペルが dinosooooor.jpg の場合、ブラウザは画像を表示せず、代わりに代替テキストを表示します。

+ +

Images in HTMLというタイトルですが、今回は恐竜の画像が表示されず、代替テキストが代わりに表示されます。

+ +

それでは、なぜ代替テキストを見たり、必要とするのでしょうか?  いくつかの理由から便利です。

+ + + +

alt 属性の中にぴったりの何を書きますか?  それは最初の場所に画像がある理由に依存します。言い換えれば、画像が表示されない場合に失うもの。

+ + + +

基本的には、画像が見えないときでも、実用的な体験を提供することが鍵です。これにより、すべてのユーザにコンテンツが欠落していないことが保証されます。ブラウザの画像をオフにして、どのように見えるかを確認してください。画像が見えない場合に、すぐに役立つ代替テキストがどれほどあるかをすぐに理解できます。

+ +
+

メモ: 詳細については、代替テキストのガイドを参照してください。

+
+ +

幅と高さ

+ +

width 属性と height 属性を使用して、画像の幅と高さを指定することができます。画像の幅と高さはさまざまな方法で確認できます。たとえば Mac では、Cmd + I を使用して画像ファイルの情報を表示することができます。例に戻ると、これをこのように行うことができます。

+ +
<img src="images/dinosaur.jpg"
+     alt="恐竜の骨格の頭と胴体、
+          それは長い鋭い歯を持つ大きな頭を持っています"
+     width="400"
+     height="341">
+ +

これは、通常の状況下では表示が大きく異なるものではありません。しかし、画像が表示されていない場合、たとえば、ユーザがページに移動して画像がまだ読み込まれていない場合、ブラウザには画像が表示されるスペースが残ります。

+ +

恐竜の代替テキストを含む Images in HTML タイトルは、幅と高さの設定の結果として大きなボックスの内側に表示されます

+ +

これは良いことです。その結果、ページの読み込みがより迅速かつスムーズに行われます。

+ +

ただし、HTML 属性を使用して画像のサイズを変更しないでください。画像のサイズを大きくしすぎると、ざらついて、ぼやけた画像になり、小さくしすぎると、帯域幅を無駄にしてユーザのニーズに合わない画像をダウンロードすることになります。正しいアスペクト比を維持しないと、画像が歪んで見えることもあります。画像エディタを使用して画像を正しいサイズにしてから、Webページに配置する必要があります。

+ +
+

メモ: 画像のサイズを変更する必要がある場合は、代わりに CSS を使用する必要があります。

+
+ +

画像のタイトル

+ +

リンクと同様に、画像に title 属性を追加して、必要に応じてさらにサポート情報を提供することもできます。この例では、これを行うことができます。

+ +
<img src="images/dinosaur.jpg"
+     alt="恐竜の骨格の頭と胴体、
+          それは長い鋭い歯を持つ大きな頭を持っています"
+     width="400"
+     height="341"
+     title="マンチェスター大学博物館に展示されている T-Rex">
+ +

これは、リンクのタイトルと同様に、マウスのホバーによるツールチップを提供します。

+ +

恐竜の画像に、A T-Rex on display at the Manchester University Museumというツールチップのタイトルが表示されます

+ +

しかし、これは推奨されていません — title には多くのアクセシビリティ上の問題があります。主に、スクリーンリーダーのサポートは予測不可能で、マウスを使用していない限り、ほとんどのブラウザーでは表示されません(例えば、キーボード ユーザ)。このことについてもっと知りたい場合は、Scott O'Hara のタイトル属性の試行錯誤 (英語) をお読みください。

+ +

画像に添付するのではなく、メインの記事のテキストにそのようなサポート情報を含める方が良いでしょう。

+ +

アクティブラーニング: 画像の埋め込み

+ +

今度はあなたの番です!  この能動的学習セクションでは、あなたに簡単な埋め込み練習をさせていただきます。基本的な {{htmlelement("img")}} タグが提供されています。次の URL の画像を埋め込むようにしてください。

+ +

https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg

+ +

以前は他のサーバ上の画像に絶対にホットリンクしないように言っていましたが、これは単なる学習目的のためのものです。

+ +

また、次のこともします。

+ + + +

間違えた場合は、[Reset] ボタンを使用してリセットすることができます。あなたが本当に立ち往生した場合は、[Show solution] ボタンを押して答えを表示してください。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 350, "", "", "hide-codepen-jsfiddle") }}

+ +

図表と図表のキャプションで画像に注釈を付ける

+ +

キャプションといえば、画像に付けるキャプションを追加する方法はいくつかあります。たとえば、これをやめさせることは何もありません。

+ +
<div class="figure">
+  <img src="images/dinosaur.jpg"
+       alt="恐竜の骨格の頭と胴体、
+            それは長い鋭い歯を持つ大きな頭を持っています"
+       width="400"
+       height="341">
+
+  <p>マンチェスター大学博物館に展示されている T-Rex。</p>
+</div>
+ +

これで結構です。それはあなたが必要とするコンテンツを含んでおり、CSS を使って素敵に書式設定できます。しかし、ここに問題があります。画像をキャプションに意味的にリンクするものは何もありません。スクリーンリーダーにとっては問題を引き起こす可能性があります。たとえば、50個の画像とキャプションがある場合、どのキャプションにどの画像が表示されますか?

+ +

より良い解決策は、HTML5 の {{htmlelement("figure")}} と {{htmlelement("figcaption")}} 要素を使用することです。図表のための意味的なコンテナを提供し、図表をキャプションに明確にリンクさせること。これはまさにこの目的のために作成されたものです。上記の例は次のように書き直すことができます。

+ +
<figure>
+  <img src="images/dinosaur.jpg"
+       alt="恐竜の骨格の頭と胴体、
+            それは長い鋭い歯を持つ大きな頭を持っています"
+       width="400"
+       height="341">
+
+  <figcaption>マンチェスター大学博物館に展示されている T-Rex。</figcaption>
+</figure>
+ +

{{htmlelement("figcaption")}} 要素は、キャプションが {{htmlelement("figure")}} 要素の他のコンテンツを説明していることをブラウザと支援技術に伝えます。

+ +
+

メモ: アクセシビリティの観点から、キャプションと {{htmlattrxref('alt','img')}} テキストには明確な役割があります。キャプションは画像を見ることができる人にも利益をもたらしますが、代替テキストは欠けている画像と同じ機能を提供します。したがって、キャプションと代替テキストは、画像がなくなったときに両方が表示されるため、同じことを言うべきではありません。ブラウザで画像をオフにして見た目を確認してみてください。

+
+ +

図表は画像である必要はありません。それは次のようにコンテンツの独立した単位です。

+ + + +

図表は、いくつかの画像、コードスニペット、音声、動画、方程式、表、または何か他のものであってもよい。

+ +

アクティブラーニング: 図表の作成

+ +

この能動的学習セクションでは、以前の能動的学習セクションで完成したコードを図表にします。

+ + + +

間違えた場合は、[Reset] ボタンを使用してリセットすることができます。あなたが本当に立ち往生した場合は、[Show solution] ボタンを押して答えを表示してください。

+ + + +

{{ EmbedLiveSample('Playable_code_2', 700, 350, "", "", "hide-codepen-jsfiddle") }}

+ +

CSS 背景画像

+ +

また、CSS を使用して画像をWebページに埋め込むこともできます(JavaScriptでもできますが、それはまったく別の話です)。CSS の {{cssxref("background-image")}} プロパティとその他の background-* プロパティは、背景画像の配置を制御するために使用されます。たとえば、ページ上の各段落に背景画像を配置するには、次のようにします。

+ +
p {
+  background-image: url("images/dinosaur.jpg");
+}
+ +

結果として得られる埋め込み画像は、HTML 画像よりも位置付けと制御が容易であることは間違いありません。それでは、なぜ HTML 画像を気にするのですか?  上記のとおり、CSS 背景画像は装飾用です。ビジュアルを向上させるためにページに何かを追加したいだけなら、これは問題ありません。しかし、そのような画像には意味論的な意味は全くありません。同等のテキストを持つことはできず、スクリーンリーダーには見えません。これは HTML 画像の輝く時です!

+ +

要約: 画像に意味がある場合は、コンテンツに関して、HTML 画像を使用する必要があります。画像が純粋に装飾である場合は、CSS 背景画像を使用する必要があります。

+ +
+

メモ: CSS 背景画像については、CSS のトピックで詳しく説明します。

+
+ +

それは今のところすべてです。画像とキャプションを詳細にカバーしています。次の記事では、HTML を使用してWebページに動画と音声を埋め込む方法を見ていきます。

+ +

{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/multimedia_and_embedding/index.html b/files/ja/learn/html/multimedia_and_embedding/index.html new file mode 100644 index 0000000000..3dc7f06753 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/index.html @@ -0,0 +1,78 @@ +--- +title: マルチメディアとその埋め込み方 +slug: Learn/HTML/Multimedia_and_embedding +tags: + - Assessment + - Audio + - Beginner + - CodingScripting + - Flash + - Guide + - HTML + - Images + - Landing + - Learn + - SVG + - Video + - iframes + - imagemaps + - responsive + - イメージマップ + - ガイド + - フラッシュ + - レスポンシブ + - 初心者 + - 動画 + - 学習 + - 画像 + - 着地ページ + - 評価試験 + - 音声 +translation_of: Learn/HTML/Multimedia_and_embedding +--- +

{{LearnSidebar}}

+ +

このコースではここまで多くのテキストを見てきましたが、ただテキストだけのWebでは面白くありません。Web が生き生きとして、面白いコンテンツがどんどんあふれるようにする方法を見ていきましょう! このモジュールでは、HTMLをどのように用いれば、あなたの Web ページにマルチメディアを含めることができるかについて学びます。 また、画像を挿入するためのさまざまな方法や、動画・音声、さらには他の Web ページ全体を挿入する方法についても触れます。

+ +

前提条件

+ +

このモジュールを開始する前に、HTML入門で述べられてきた、HTML の基本についてのある程度の知識が求められます。 このモジュール (や似たようなもの) を一通り終えていない場合、まずそちらを一通り終えてから戻ってきてください!

+ +
+

メモ: 自分自身のファイルを作れないコンピューター/タブレット/その他デバイスで作業している場合、JSBinThimble のようなオンラインコーティングプログラムにてコードの実例 (の大半) を試すことができます。

+
+ +

ガイド

+ +

このモジュールには下記の記事が含まれていて、そこではマルチメディアをWeb ページに埋め込むための基礎を学びます。

+ +
+
HTMLの画像
+
考慮すべき他のタイプのマルチメディアもありますが、単純な画像をWeb ページに埋め込むために使用される、慎ましい {{htmlelement("img")}} 要素から始めるのが理にかなっています。 この記事では、基本的な使い方を含め、 {{htmlelement("figure")}} を使ったキャプションによる注釈付け、CSS背景画像との関連の仕方など、画像をより深く使用する方法を見ていきます。
+
動画と音声のコンテンツ
+
次に、HTML5の {{htmlelement("video")}} 要素と {{htmlelement("audio")}} 要素を使用して、動画や音声をページに埋め込む方法を見ていきます。 それには、基本的な使い方を含め、さまざまなファイルフォーマットへのアクセスをさまざまなブラウザーに提供したり、キャプションや字幕の追加、古いブラウザーへの代替の追加などが含まれています。
+
<object> から <iframe> へ — その他の埋め込み技術
+
この時点では、{{htmlelement("iframe")}} 、{{htmlelement("embed")}}、{{htmlelement("object")}} 要素のような幅広い種類のコンテンツをWeb ページに埋め込むことができる要素をいくつか見ていきたいと考えています。 <iframe> は他のWeb ページを埋め込むためのもので、他の2つは PDF、SVG、さらには Flash を埋め込むことができます — 出口にある技術ですが、まだ半定期的に見かけるでしょう。
+
Webにベクターグラフィックスを追加する
+
ベクターグラフィックスは、特定の状況で非常に便利です。 PNG や JPG のような通常のフォーマットとは異なり、ズームインしてもゆがんだりピクセル化したりしません — 縮尺を変えても滑らかな状態を保つことができます。 この記事では、ベクターグラフィックスの概要と、ポピュラーな {{glossary("SVG")}} フォーマットをWeb ページに含める方法を紹介します。
+
レスポンシブ画像
+
携帯電話からデスクトップコンピュータに至るまで、Webを閲覧できるようになったさまざまな種類のデバイスで、現代のWeb世界を習得するために不可欠な概念は、レスポンシブデザインです。 これは、さまざまな画面サイズ、解像度などに合わせて機能を自動的に変更できるWeb ページの作成を指します。 これについては、後ほどCSSモジュールで詳しく見ていく予定ですが、ここでは、HTMLで {{htmlelement("picture")}} 要素を含むレスポンシブ画像を作成するためのツールを見ていきます。
+
+ +

評価試験

+ +

上記のガイドで説明されている HTML の基本について、以下の評価試験を行います。

+ +
+
Mozillaのスプラッシュページ
+
今回の評価試験では、このモジュールの記事で説明したいくつかの技術の知識をテストするために、Mozillaのすべてついてのファンキーなスプラッシュページに、いくつかの画像と動画を追加してもらいます!
+
+ +

関連情報

+ +
+
画像の上にヒットマップを追加する
+
イメージマップは、画像のさまざまな部分を別の場所にリンクするためのメカニズムを提供します(あなたがクリックしたそれぞれの国についての詳細情報にリンクしている地図を考えてみてください)。 この手法は時には便利なことがあります。
+
Webリテラシーの基礎 2 (英語)
+
優れたMozillaの基礎コースで、マルチメディアと埋め込みモジュールで説明されているスキルのいくつかを調べてテストします。 Web ページの作成、アクセシビリティの設計、リソースの共有、オンラインメディアの使用、オープンな作業 (コンテンツは自由に利用可能で、他の人が共有できることを意味します) の基礎を深く理解してください。
+
diff --git a/files/ja/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html b/files/ja/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html new file mode 100644 index 0000000000..b03f568d29 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html @@ -0,0 +1,129 @@ +--- +title: Mozilla のスプラッシュページ +slug: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +tags: + - Assessment + - Beginner + - CodingScripting + - Embedding + - HTML + - Multimedia + - Video + - iframe + - picture + - responsive + - sizes + - srcset + - マルチメディア + - レスポンシブ + - 初心者 + - 動画 + - 埋め込み + - 評価試験 +translation_of: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}
+ +

今回の評価試験では、このモジュールの記事で説明したいくつかの技術の知識をテストするために、Mozilla のすべてついてのファンキーなスプラッシュページに、いくつかの画像と動画を追加してもらいます!

+ + + + + + + + + + + + +
前提条件:この評価試験を試す前に、残りのマルチメディアとその埋め込み方のモジュールに既に取り組んでいる必要があります。
目的:ウェブページに画像と動画を埋め込むこと、フレーム、および HTML レスポンシブ画像技術に関する知識をテストすること。
+ +

出発点

+ +

この評価試験を開始するには、github の mdn-splash-page-start ディレクトリにある HTML とすべての画像を取得する必要があります。 index.html の内容をローカルドライブの新しいディレクトリの index.html というファイルに保存します。 それから、pattern.png を同じディレクトリに保存します(画像を右クリックして保存するオプションを選びます)。

+ +

originals ディレクトリの別の画像にアクセスし、同じ方法で保存します。 あなたはそれらを使用する準備が整う前に、グラフィックスエディタを使って(それらのいくつかを)操作する必要があるので、今は別のディレクトリに保存する必要があります。

+ +
+

メモ: 例の HTML ファイルには、ページのスタイルを設定するための CSS がかなり多く含まれています。 {{htmlelement("body")}} 要素内の HTML だけで、CSS に触れる必要はありません — 正しいマークアップを挿入する限り、スタイリングは正しく表示されます。

+
+ +

プロジェクトの概要

+ +

今回の評価試験では、ほとんど完成した Mozilla のスプラッシュページを紹介しています。 これは、Mozilla が何を意味しているかについて、何か素敵で興味深いことを言い、さらなるリソースへのリンクを提供することを目的としています。 残念ながら、画像や動画はまだ追加されていません — これがあなたの仕事です! ページの見栄えを良くし、もっと理にかなったものにするために、いくつかのメディアを追加する必要があります。 次のサブセクションでは、実行する必要があることを詳しく説明します。

+ +

画像の準備

+ +

お気に入りの画像エディタを使用して、次のものから 400px 幅と 120px 幅のバージョンを作成します。

+ + + +

たとえば、firefoxlogo400.pngfirefoxlogo120.png のように、それらを判りやすい名前にしてください。

+ +

mdn.svg に加えて、これらの画像は、further-info 領域内のさらなるリソースにリンクするアイコンになります。 また、サイトヘッダーの firefox ロゴにもリンクします。 これらすべてのコピーを index.html と同じディレクトリに保存します。

+ +

次に、red-panda.jpg の 1200 ピクセル幅のランドスケープバージョンと、パンダをより近くに見せてくれる 600 ピクセル幅のポートレートバージョンを作成します。 繰り返しますが、それらを簡単に識別できるように、判りやすい名前にしてください。 これらの両方のコピーを index.html と同じディレクトリに保存します。

+ +
+

メモ: JPG 画像と PNG 画像を最適化して、できるだけ小さくして、それでも見栄えを良くしてください。 tinypng.com は簡単にこれを行うための素晴らしいサービスです。

+
+ +

ヘッダーにロゴを追加する

+ +

{{htmlelement("header")}} 要素の中に、小さなバージョンの Firefox ロゴをヘッダーに埋め込む {{htmlelement("img")}} 要素を追加します。

+ +

主要記事のコンテンツに動画を追加する

+ +

{{htmlelement("article")}} 要素の内側(開始タグのすぐ下)に、 https://www.youtube.com/watch?v=ojcNcvb1olg にある YouTube 動画を適切な YouTube ツールを使用してコードを生成して埋め込みます。 動画の幅は 400 ピクセルです。

+ + + +

further-info クラスを持つ {{htmlelement("div")}} の中には、それぞれが興味深い Mozilla 関連のページにリンクする4つの {{htmlelement("a")}} 要素があります。 このセクションを完成させるには、適切な {{htmlattrxref("src", "img")}}、{{htmlattrxref("alt", "img")}}、{{htmlattrxref("srcset", "img")}}、{{htmlattrxref("sizes", "img")}} の各属性を含む {{htmlelement("img")}} 要素をそれぞれの内部に挿入する必要があります。

+ +

いずれの場合でも (1つを除く — どれが本質的にレスポンシブですか?)、ブラウザーにビューポートの幅が 500px 以下の場合は 120px 幅のバージョン、それ以外の場合は 400px 幅のバージョンを提供したい。

+ +

正しい画像と正しいリンクが一致していることを確認してください!

+ +
+

メモ: srcsetsizes の例を適切にテストするには、サイトをサーバーにアップロードする必要があります (Github ページを使用するのが簡単で無料の解決策です)。 そして、そこから Firefox の Network Monitor などのツールを使用して正しく動作しているかどうかをテストできます。

+
+ +

アートディレクションされたレッサーパンダ

+ +

red-panda クラスを持つ {{htmlelement("div")}} の中に、ビューポートの幅が 600px 以下の場合は小さなポートレートのパンダ画像を提供する {{htmlelement("picture")}} 要素を挿入し、それ以外の場合は大きなランドスケープ画像を挿入します。

+ +

+ +

以下のスクリーンショットは、広い画面と狭い画面で、スプラッシュページが正しくマークアップされた後にどのように見えるかを示しています。

+ +

サンプルのスプラッシュページの広い画面のショット

+ +

サンプルのスプラッシュページの狭い画面のショット

+ +

評価

+ +

組織的コースの一環としてこの評価に従っている場合は、採点のために作品を教師や指導者に渡すことができるはずです。 自己学習をしている場合は、この演習についてのディスカッションスレッドMozilla IRC#mdn IRC チャンネルで尋ねることで、かなり簡単に採点の手引きを得ることができます。 まず演習を試してみてください — 不正行為によって得られるものは何もありません!

+ +
+

メモ: 評価試験を Chrome ブラウザーのデベロッパーツールで行った場合、「レスポンシブビュー」でどんなに幅を狭く設定しても正しい画像が読み込めないことがあります。これは Chrome の特性のようです。 Firefox ブラウザーは (HTML が正しければ) 正しい画像を読み込みます。

+
+ +

{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html b/files/ja/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html new file mode 100644 index 0000000000..1623398dd0 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html @@ -0,0 +1,399 @@ +--- +title: object から iframe へ — その他の埋め込み技術 +slug: Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies +tags: + - Article + - Beginner + - CodingScripting + - Embedding + - Flash + - Guide + - HTML + - Learn + - Multimedia and embedding + - Object + - embed + - iframe +translation_of: Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}
+ +

そろそろ、画像、動画、音声など、ウェブページへの埋め込みのコツがつかめてきたはずです。ここでは、少し横道にそれて、ウェブページに様々な種類のコンテンツを埋め込むことができる要素、 {{htmlelement("iframe")}}、 {{htmlelement("embed")}}、 {{htmlelement("object")}} を見てみたいと思います。 <iframe> は他のウェブページを埋め込むためのもので、他の2つの要素は PDF、SVG、 さらに Flash — もうすぐなくなる技術ですが、まだ時々見かけるもの — も、埋め込むことができます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータリテラシー、インストールされた基本ソフトウェアファイルの操作に関する基本知識、HTML の基礎知識 (HTML の入門)、およびこのモジュールの前の記事
目的:Flash ムービーなどのウェブページのように、{{htmlelement("object")}}、{{htmlelement("embed")}}、{{htmlelement("iframe")}} を使用してアイテムをウェブページに埋め込む方法を学びます。
+ +

埋め込みの短い歴史

+ +

昔、ウェブ上では、フレームを使ってウェブサイトを作るのが一般的でした - ウェブサイトの小さな部分が個々の HTML ページに保存されていました。これらは、フレームセットと呼ばれるマスター文書に埋め込まれていました。これにより、テーブルの列と行のサイジングのように、各フレームが埋めた画面上の領域を指定することができました。これらは90年代半ばから後半にかけてのクールさの極みと考えられていました。このような小さな塊に分割されたウェブページを持っているとダウンロード速度が向上したという証拠がありました — 特にネットワーク接続が非常に遅いため、特に顕著です。それらは多くの問題を抱えていましたが、ネットワーク速度がより速くなるにつれて、これ以上の利点はなく、あなたはそれらがもう使用されているのを見ていません。

+ +

ちょっと後で(90年代後半、2000年代初頭)、{{Glossary("Java","Java アプレット")}}や {{Glossary("Adobe_Flash","Flash")}} などのプラグイン技術が普及しました。これにより、ウェブ開発者は動画やアニメーションなどのウェブページに豊富なコンテンツを埋め込むことができました。これらの技術を埋め込むことは、{{htmlelement("object")}} や、あまり使われていない {{htmlelement("embed")}} などの要素によって実現され、当時は非常に便利でした。アクセシビリティ、セキュリティ、ファイルサイズなど、多くの問題が発生して以来、それらは流行していませんでした。最近のモバイルデバイスのほとんどは、このようなプラグインをサポートしておらず、デスクトップのサポートは出口にあります。

+ +

最後に、{{htmlelement("iframe")}} 要素が現れました({{htmlelement("canvas")}}、{{htmlelement("video")}} などのコンテンツを埋め込む他の方法と一緒に)。これは、ウェブ文書全体を別のウェブ文書に埋め込む方法を提供し、あたかも {{htmlelement("img")}} か他の要素であるかのように、今日では普通に使用されています。

+ +

歴史の授業を終了して、これらのいくつかの使い方を見てみましょう。

+ +

アクティブラーニング: 従来の埋め込みを使う

+ +

この記事では、能動的学習セクションにまっすぐ飛び込んで、埋め込み技術が有用であるかどうかをすぐに知ることができます。オンラインの世界では Youtube はとてもよく知られていますが、多くの人は利用可能な共有施設については知らないのです。YouTube が {{htmlelement("iframe")}} を使って好きなページに動画を埋め込むことができる仕組みを見てみましょう。

+ +
    +
  1. まず、Youtube へ行き、あなたが好きな動画を見つけてください。
  2. +
  3. 動画の下に [共有] ボタンがあります。これを選択すると、共有オプションが表示されます。
  4. +
  5. [埋め込む] ボタンを選択すると、<iframe> コードがいくつか表示されます。これをコピーします。
  6. +
  7. 下の入力ボックスにそれを挿入し、結果が出力にあるかどうかを確認します。
  8. +
+ +

ボーナスポイントとして、例の中に Google マップを埋め込むこともできます。

+ +
    +
  1. Google マップへ行き、好きな地図を見つけます。
  2. +
  3. UI の左上にあるハンバーガーメニュー(3本の水平線)をクリックします。
  4. +
  5. [地図を共有または埋め込む] オプションを選択します。
  6. +
  7. [地図を埋め込む] オプションを選択します。これは、<iframe> コードをいくつか提供します。これをコピーします。
  8. +
  9. 下の入力ボックスにそれを挿入し、結果が出力にあるかどうかを確認します。
  10. +
+ +

間違えた場合は、[Reset] ボタンを使用してリセットすることができます。あなたが本当に立ち往生したら、[Show solution] ボタンを押して回答を見てください。

+ + + +

{{ EmbedLiveSample('Playable_code', 700, 600, "", "", "hide-codepen-jsfiddle") }}

+ +

iframe の詳細

+ +

それは簡単で楽しいものでしたか? {{htmlelement("iframe")}} 要素は、他のウェブ文書を現在の文書に埋め込むことができるように設計されています。これは、直接制御できない可能性のある第三者のコンテンツをウェブサイトに組み込むのに適していて、独自のバージョンを実装する必要はありません — オンライン動画プロバイダの動画、Disqus のようなコメントシステム、オンライン地図プロバイダの地図、広告バナーなど。このコースで使用しているライブ編集可能な例は、<iframe> を使用して実装されています。

+ +

<iframe> で検討すべき{{anch("Security concerns","セキュリティ上の懸念")}}がいくつかあり、これについては以下で説明しますが、あなたのウェブサイトで使用しないでください — ちょっとした知識と慎重な考えが必要です。コードを少し詳しく見てみましょう。あなたのウェブページの1つに MDN の用語集を含めることを考えていたら、次のようなことを試すことができます。

+ +
<iframe src="https://developer.mozilla.org/en-US/docs/Glossary"
+        width="100%" height="500" frameborder="0"
+        allowfullscreen sandbox>
+  <p>
+    <a href="https://developer.mozilla.org/en-US/docs/Glossary">
+    iframe をサポートしていないブラウザーのための代替リンク
+    </a>
+  </p>
+</iframe>
+ +

この例には、<iframe> の使用に必要な基本的な要素が含まれています。

+ +
+
{{htmlattrxref('allowfullscreen','iframe')}}
+
設定されている場合、<iframe> は、 Full Screen API を使用してフルスクリーンモードにすることができます(この記事の範囲外です)。
+
{{htmlattrxref('frameborder','iframe')}}
+
1 に設定すると、これはブラウザーにこのフレームと他のフレームとの境界を描画するように指示します。これは既定の動作です。0 は境界を取り去ります。{{Glossary('CSS')}} で {{cssxref('border')}}: none; を使用すると、同じ効果がより良く達成できるので、この属性を使用することはもうお勧めできません。
+
{{htmlattrxref('src','iframe')}}
+
この属性は、{{htmlelement("video")}} や {{htmlelement("img")}} と同様に、埋め込む文書の URL を指すパスを含んでいます。
+
{{htmlattrxref('width','iframe')}} と {{htmlattrxref('height','iframe')}}
+
これらの属性は、iframe の幅と高さを指定します。
+
代替コンテンツ
+
{{htmlelement("video")}} のような他の要素と同じように、 <iframe></iframe> のタグの間に、ブラウザーが <iframe> をサポートしていない場合に表示される代替コンテンツを含めることができます。この場合、代わりにページへのリンクが含まれています。最近では、<iframe> をサポートしていないブラウザーを見つけることはまずありません。
+
{{htmlattrxref('sandbox','iframe')}}
+
この属性は、他の <iframe> の機能よりも若干現代的なブラウザー(たとえば、IE 10 以上)で機能し、高度なセキュリティ設定を要求します。これについては、次のセクションで詳しく説明します。
+
+ +
+

メモ: 速度を向上させるためには、メインコンテンツの読み込みが完了した後に iframe の src 属性を JavaScript で設定することをお勧めします。これにより、ページがより早く使用できるようになり、公式ページの読み込み時間が短縮されます(重要な {{glossary("SEO")}} の測定基準)。

+
+ +

セキュリティ上の懸念

+ +

上ではセキュリティ上の懸念について言及しました。これについてもう少し詳しく説明しましょう。あなたはこのコンテンツのすべてを初めから完全に理解することを期待していません。この懸念を認識して、より経験豊かになり、あなたの実験や作業で <iframe> の使用を検討し始める参考にしてください。また、恐怖を感じ、<iframe> を使わない必要はありません — 注意するだけです。

+ +

ブラウザーメーカーやウェブ開発者は、iframe がウェブ上の悪意ある人物(しばしばハッカー、またはより正確にはクラッカーと呼ばれます)の共通のターゲット(公式の用語: 攻撃ベクター)であるということを苦労して学びました。悪意ある人物は、あなたのウェブページを悪意を持って改ざんすることや、ユーザ名やパスワードなどの機密情報を明らかにするなど、人を騙し望んでいないことを行います。このため、仕様技術者とブラウザー開発者は、<iframe> をより安全にするためのさまざまなセキュリティ・メカニズムを開発しました。また、考慮すべき最善の措置もあります — これらのいくつかを以下で説明します。

+ +
+

{{interwiki('wikipedia','クリックジャッキング')}}は、ハッカーが目に見えない iframe をあなたの文書に埋め込んだり(あなたの文書を自分の悪意のあるウェブサイトに埋め込んだり)して、ユーザの操作を乗っ取るための一般的な iframe 攻撃の一種です。これは、ユーザを誤解させたり機密データを盗む一般的な方法です。

+
+ +

簡単な例ですが、先ほど紹介した例をブラウザーに読み込んでみましょう。Github にライブが公開されています(ソースコードも参照してください)。実際にページに何も表示されませんが、ブラウザーの開発者ツールのコンソールに、理由を示すメッセージが表示されます。Firefox では、"Load denied by X-Frame-Options: https://developer.mozilla.org/en-US/docs/Glossary does not permit framing." (X-Frame-Optionsによって読み込みが拒否されました: https://developer.mozilla.org/en-US/docs/Glossary はフレーミングを許可していません。)というメッセージが表示されます。これは、MDN を作成した開発者が、<iframe> 内に埋め込まれないようにウェブサイトのページを提供する設定をサーバーに組み込んだためです(下記の {{anch("Configure CSP directives","CSP ディレクティブの設定")}}を参照してください)。これは、理にかなっています — あなたのサイトにそれらを埋め込んであなた自身のものと主張するようなことをしない限り、MDN のページ全体が他のページに埋め込まれるのは本当に意味がありません — または、クリックジャッキングを介してデータを盗み出そうとする。どちらも本当に悪いことです。さらに、誰もがこれをやり始めたら、すべての追加の帯域幅が Mozilla に多額の費用をかけるようになります。

+ +

必要なときにのみ埋め込みます

+ +

場合によっては、第三者のコンテンツを埋め込むことが理にかなっています — youtube 動画や地図のようなものですが、完全に必要なときに第三者のコンテンツだけを埋め込むのであれば、頭を悩ますことはありません。ウェブセキュリティのための良い経験則は、「慎重すぎることは決してありません。もしあなたがそれを作ったら、とにかくそれをもう一度チェックしてください。他の誰かがそれを作ったら、そうでないと証明されるまでそれは危険です。」ということです。

+ +
+

セキュリティのほかに、知的財産の問題にも注意する必要があります。ほとんどのコンテンツは著作権で保護されており、オフラインでもオンラインでも、予期していないコンテンツ(例えば、ウィキメディアコモンズのほとんどの画像)でさえもあります。あなたが所有しているか、または所有者があなたに書面による明白な許可を与えていない限り、ウェブページにコンテンツを表示しないでください。著作権侵害に対する罰則は厳しいものです。繰り返しますが、決して慎重すぎることはありません。

+ +

コンテンツにライセンスが付与されている場合は、ライセンス条項に従わなければなりません。たとえば、MDN のコンテンツは CC-BY-SA でライセンスされています。つまり、コンテンツを大幅に変更した場合でも、コンテンツを引用する際には、適切にクレジットを表示する(英語)必要があります。

+
+ +

HTTPS を使用する

+ +

{{Glossary("HTTPS")}} は {{Glossary("HTTP")}} の暗号化されたバージョンです。可能であれば、HTTPS を使用してウェブサイトを提供する必要があります。

+ +
    +
  1. HTTPS を使用すると、転送中にリモートコンテンツが改ざんされる可能性が減り、
  2. +
  3. HTTPS は、埋め込みコンテンツが親文書内のコンテンツにアクセスすることを防止し、逆も同様です。
  4. +
+ +

HTTPS を使用するには、高価なセキュリティ証明書が必要です(ただし、Let's Encrypt で簡単にできます) — 入手できない場合は、親文書を HTTP で配信できます。しかし、上記の HTTPS の2つ目の利点のため、コストにかかわらず、第三者のコンテンツを HTTP に埋め込むことは絶対にしないでください(最良の場合のシナリオでは、ユーザのウェブブラウザーは恐ろしい警告を表示します)。<iframe> を使用してコンテンツを埋め込むことができる評判の良い企業はすべて、HTTPS 経由で利用できるようになります — たとえば、Google マップや YouTube からコンテンツを埋め込む場合は、<iframe>src 属性内の URL を調べます。

+ +
+

メモ: Github のページでは、既定で HTTPS 経由でコンテンツを提供できるため、コンテンツのホスティングに便利です。異なるホスティングを使用していて、わからない場合は、ホスティングプロバイダに問い合わせてください。

+
+ +

常に sandbox 属性を使用する

+ +

攻撃者には、あなたのウェブサイトで悪いことを行うことができるような力を与えたくないので、埋め込みコンテンツには、その仕事を行うために必要な権限のみを与えるべきです。もちろん、これは自分のコンテンツにも当てはまります。適切に(またはテスト用に)使用できるが、コードベースの残りの部分に何らかの害(偶発的または悪意のある)を及ぼすことができないコード用のコンテナは、サンドボックスと呼ばれます。

+ +

サンドボックスにないコンテンツはあまりにも多くのことを行うことができます( JavaScript の実行、フォームの送信、ポップアップウィンドウなど)。既定では、前述の例に示すように、パラメーターなしの sandbox 属性を使用して、使用可能なすべての制限を課す必要があります。

+ +

絶対に必要な場合は、権限を1つずつ追加することができます(sandbox="" 属性値内に) — 使用可能なすべてのオプションについては、{{htmlattrxref('sandbox','iframe')}} のリファレンスのエントリを参照してください。重要な注意点の1つは、 sandbox 属性に allow-scriptsallow-same-origin の両方を追加しないことです。この場合、埋め込みコンテンツは、サイトのスクリプトの実行を停止する同一オリジン・セキュリティポリシーをバイパスし、JavaScript を使用してサンドボックスを完全に無効にします。

+ +
+

メモ: 攻撃者が欺いて悪意のあるコンテンツ(iframe 外にある)を直接訪問させることができれば、サンドボックスは保護を提供しません。特定のコンテンツが悪意のあるコンテンツ(ユーザ生成コンテンツなど)である可能性がある場合は、別の{{glossary("domain","ドメイン")}}からメインサイトへ配信してください。

+
+ +

CSP ディレクティブの設定

+ +

{{Glossary("CSP")}} はコンテンツセキュリティポリシーの略で、HTML 文書のセキュリティを強化するために設計された一連の HTTP ヘッダー(ウェブサーバーから配信されたときにウェブページとともに送信されるメタデータ)を提供します。<iframe> を保護する場合、適切な X-Frame-Options ヘッダーを送信するようにサーバーを構成できます。これにより、他のウェブサイトがそのウェブページにあなたのコンテンツを埋め込むのを防ぐことができます({{interwiki('wikipedia','クリックジャッキング')}}や他の攻撃のホストを可能にする)。以前に見たように、これはまさに MDN 開発者が行ったことです。

+ +
+

メモ: Frederik Braun 氏の投稿 X-Frame-Options セキュリティヘッダーについて(英語)で、このトピックの背景情報を読むことができます。明らかに、これは、この記事の詳述の範囲外です。

+
+ +

<embed> 要素と <object> 要素

+ +

{{htmlelement("embed")}} 要素と {{htmlelement("object")}} 要素は、{{htmlelement("iframe")}} とは異なる機能を果たします。これらの要素は、Java アプレットや Flash などのプラグイン技術、PDF(ブラウザーで PDF プラグインを使用して表示できる)、動画、SVG、画像などのコンテンツを含む、複数のタイプの外部コンテンツを埋め込む汎用埋め込みツールです!

+ +
+

メモ: プラグインは、ブラウザーがネイティブに読むことができないコンテンツへのアクセスを提供するソフトウェアです。

+
+ +

しかし、あなたはこれらの要素を大いに利用することはまずありません。アプレットは何年も使われておらず、Flash は多くの理由から人気がなくなりました (下記の{{anch("The case against plugins","プラグインに対するケース")}}を参照)。PDF は埋め込まれたものよりもリンクされている傾向があり、画像や動画などの他のコンテンツには、それらを扱うためのずっと優れた、より簡単な要素があります。プラグインとこれらの埋め込み方法は、従来の技術ですが、イントラネットやエンタープライズプロジェクトのような特定の状況でそれらを見かけた場合に備えて言及しています。

+ +

プラグインのコンテンツを埋め込む必要がある場合の最低限必要な情報です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{htmlelement("embed")}}{{htmlelement("object")}}
埋め込みコンテンツの {{glossary("URL")}}{{htmlattrxref('src','embed')}}{{htmlattrxref('data','object')}}
埋め込みコンテンツの正確な{{glossary("MIME type", 'メディアタイプ')}}{{htmlattrxref('type','embed')}}{{htmlattrxref('type','object')}}
プラグインによって制御されるボックスの高さと幅 (CSS ピクセル単位){{htmlattrxref('height','embed')}}
+ {{htmlattrxref('width','embed')}}
{{htmlattrxref('height','object')}}
+ {{htmlattrxref('width','object')}}
プラグインにパラメータとして供給するための名前と値それらの名前と値を持つ特別な属性<object> 内に含まれる単一タグの {{htmlelement("param")}} 要素
利用不可能なリソースに対する代替として独立した HTML コンテンツサポートされていません(<noembed> は廃止されました)<object> 内の、<param> 要素の後に含まれる
+ +
+

メモ: <object> には、data 属性、type 属性、またはその両方が必要です。両方を使用する場合は、{{htmlattrxref('typemustmatch','object')}} 属性を使用することもできます(この記事の執筆時点では、Firefox でのみ実装されています)。typemustmatch は、type 属性が正しいメディアタイプを提供していない限り、埋め込みファイルが実行されないようにします。typemustmatch は、異なる{{glossary("origin","オリジン")}}のコンテンツを埋め込んでいる場合に、大きなセキュリティ上の利点をもたらすことができます(攻撃者がプラグインを介して任意のスクリプトを実行することを防ぐことができます)。

+
+ +

次に、{{htmlelement("embed")}} 要素を使用して Flash ムービーを埋め込む例を示します(Github でライブを見て、ソースコードも確認してください)。

+ +
<embed src="whoosh.swf" quality="medium"
+       bgcolor="#ffffff" width="550" height="400"
+       name="whoosh" align="middle" allowScriptAccess="sameDomain"
+       allowFullScreen="false" type="application/x-shockwave-flash"
+       pluginspage="http://www.macromedia.com/go/getflashplayer">
+ +

かなり恐ろしいですね。Adobe Flash ツールで生成された HTML は、<embed> 要素が埋め込まれた <object> 要素を使用して、すべてのベースをカバーするために悪化する傾向がありました(例を参照してください)。Flash は、HTML5 動画の代替コンテンツとしても使用されていましたが、これは必要ではないと見られています。

+ +

次に、PDF をページに埋め込む <object> の例を見てみましょう(ライブのサンプルとソースコードを参照)。

+ +
<object data="mypdf.pdf" type="application/pdf"
+        width="800" height="1200" typemustmatch>
+  <p>PDF プラグインはありませんが、
+    <a href="mypdf.pdf">PDF ファイルをダウンロードできます。
+    </a>
+  </p>
+</object>
+ +

PDF は紙とデジタルの間の必要な足がかりでしたが、多くのアクセシビリティ上の課題(英語)があり、小さな画面では読みにくい場合があります。それらはまだいくつかのサークルで人気がある傾向がありますが、ウェブページに埋め込むのではなく、ダウンロードしたり、別のページで読むことができるように、リンクする方がはるかに優れています。

+ +

プラグインに対するケース

+ +

かつて、プラグインはウェブ上で不可欠でした。映画をオンラインで見るために Adobe Flash Player をインストールしなければならない時代を覚えていますか? そして、常に Flash Player と Java Runtime Environment のアップデートに関する迷惑な警告を受けていました。ウェブ技術はこれまでより堅牢に成長し、その時代は終わりを告げています。ほとんどのアプリケーションでは、プラグインに依存するコンテンツの配信をやめ、代わりにウェブテクノロジを活用し始めてください。

+ + + +
+

Note: その固有の問題点と Flash のサポート不足により、 Adobe は2020年末に Flash のサポートを終了すると発表しました。 2020年1月の時点で、ほとんどのブラウザーは既定で Flash コンテンツをブロックしており、2020年12月31日までにはすべてのブラウザーで Flash 機能が完全に削除されます。それ以降は、既存の Flash コンテンツにアクセスできなくなります。

+
+ +

だから何をすべきか? 双方向性が必要な場合、HTML と {{glossary("JavaScript")}} は、Java アプレットや旧式の ActiveX/BHO 技術を必要とせずに、簡単に仕事を完了させることができます。Adobe Flash に頼る代わりに、メディアの要求に合わせて HTML5 動画、ベクターグラフィックスに SVG、複雑な画像やアニメーションに Canvas を使用することができます。Peter Elst は、数年前にすでに、Adobe Flash が特殊なゲームやビジネスアプリケーションを除いて、仕事のための適切なツールではないことを書いていました(英語)。ActiveX に関しては、Microsoft の {{glossary("Microsoft Edge","Edge")}} ブラウザーでさえサポートされなくなりました。

+ +

スキルをテストしよう

+ +

この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストをいくつか見つけることができます — マルチメディアと埋め込みのスキルのテストを参照してください。

+ +

まとめ

+ +

ウェブ文書に他のコンテンツを埋め込むという話題は、すぐに非常に複雑になる可能性があるので、関連する技術のより高度な機能のいくつかを示唆しながらも、すぐに関連すると思われる単純で使い慣れた方法で紹介しようとしました。まず、あなたのページに地図や動画などの第三者のコンテンツを含めること以外に埋め込みを使用する可能性は低いです。しかし、経験が増すにつれて、より多くの用途を見つけることになるでしょう。

+ +

ここで説明したもの以外にも、外部コンテンツの埋め込みを含む他の多くの技術があります。以前の記事では {{htmlelement("video")}}、{{htmlelement("audio")}}、{{htmlelement("img")}} などいくつかを見ましたが、JavaScript で生成された 2D および 3D グラフィックスの場合は {{htmlelement("canvas")}}、ベクターグラフィックスを埋め込む場合は {{SVGElement("svg")}} など、他にも見い出されるものがあります。モジュールの次の記事では SVG を見ていきます。

+ +

{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/html/multimedia_and_embedding/responsive_images/index.html b/files/ja/learn/html/multimedia_and_embedding/responsive_images/index.html new file mode 100644 index 0000000000..80dfff9fc9 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/responsive_images/index.html @@ -0,0 +1,282 @@ +--- +title: レスポンシブ画像 +slug: Learn/HTML/Multimedia_and_embedding/Responsive_images +tags: + - Article + - Beginner + - CodingScripting + - Design + - Graphics + - Guide + - HTML + - Image + - Intermediate + - img + - picture + - sizes + - srcset + - ガイド + - グラフィックス + - デザイン + - 中級 + - 初心者 + - 画像 + - 記事 +translation_of: Learn/HTML/Multimedia_and_embedding/Responsive_images +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}
+ +
+

この記事では、レスポンシブ画像の概念 — 画面サイズ、解像度などの機能が大きく異なる機器で適切に動作する画像 — について学び、 HTML がそれを実装する上でどのような道具を提供しているかを見てみます。 レスポンシブ画像は、レスポンシブウェブデザインの一部にすぎませんが(そしてそれを実現する上で良いステージになりますが)、 CSS のトピックの将来のモジュールで多くのことを学ぶトピックです。

+
+ + + + + + + + + + + + +
前提:HTML の基本及びウェブページに静止画を追加する方法をすでに知っているものとします。
目的:{{htmlattrxref("srcset", "img")}} や {{htmlelement("picture")}} 要素のような機能を使って、ウェブサイトにレスポンシブ画像を実装する方法を学ぶこと。
+ +

なぜレスポンシブ画像なのか?

+ +

では、レスポンシブ画像でどのような問題を解決しようとしているのでしょうか。 典型的なシナリオを見てみましょう。 典型的なウェブサイトには、おそらく訪問者の印象を良くするためのヘッダー画像と、おそらくその下にはコンテンツ画像がいくつかあります。 おそらく、ヘッダー画像はヘッダーの幅全体にまたがるようにして、コンテンツ画像はコンテンツ列のどこかに合わせたいと思うでしょう。この簡単な例を見てみましょう。

+ +

広い画面で表示されているサイト例 - ここでは最初の画像はよく、中央で細部まで十分に見えます。

+ +

これは、ラップトップやデスクトップなどの広い画面のデバイスではうまく表示できます(ライブを見て、 Github でソースコードを見ることができます)。 以下の点を除けば CSS については詳しく説明しません。

+ + + +

これは問題ありませんが狭い画面のデバイスでサイトを表示するときには問題が発生します。 ヘッダーは正しく見えますが、モバイルデバイスの画面の高さ全体のうち多くの部分を占めるようになってきています。 最初のコンテンツ画像はひどく見えにくくなっています。 この寸法では、中の人物がほとんど見えていません。

+ +

狭い画面で見たサイト例。最初の画像は細部が分かりにくいところまで縮小しています。

+ +

改良点は、サイトを狭い画面で見たときに画像の重要なディティールを表示するため、切り取った画像を表示することです。 第2の切り取られた画像は、タブレットのような中幅の画面のデバイス用に表示することができます。 これは一般的にアートディレクションの問題として知られています。

+ +

さらに、小さなモバイル画面で見ている場合、このような大きな画像をページに埋め込む必要はありません。 これは解像度切り替えの問題と呼ばれています。 ラスター画像は、ベクターグラフィックスの所で見たように、幅のピクセルの集まりと、高さのピクセルの集まりです。 小さいラスター画像は、元のサイズよりも大きく表示されていると粒状に見え始めます(ベクターグラフィックスではそうなりません)。

+ +

逆に、意図した大きさよりもはるかに小さい画面に大きな画像を表示する必要はありません。 そうすることで帯域幅を無駄にすることがあります。 特に、モバイルユーザーは、小さな画像がデバイスに表示される時、デスクトップ向けの大きな画像をダウンロードすることによって帯域幅を無駄にしたくありません。 理想的な状況は、複数の解像度が利用可能で、ウェブサイト上のデータにアクセスするデバイスに応じて適切なサイズを提供することです。

+ +

状況をより複雑にしているのが、一部のデバイスは高い解像度の画面を持ち、きれいに表示するには、期待されるよりも大きい画像を必要としていることです。 これは本質的に同じ問題ですが、少し異なる状況のものです。

+ +

ベクター画像はある側面でこれらの問題を解決すると思うかもしれません。 — ファイルサイズが小さくて容易に縮尺変更でき、どこでも利用できるからです。 しかし、すべての種類の画像に適しているわけではありません。 — 単純な図形、パターン、インターフェイス要素などには適していますが、例えば写真のような、ディティールのものをベクターベースの画像で作成すると、とても複雑になります。  JPEG のようなラスター画像形式は、上記の例に見られるような種類の画像により適しています。

+ +

この種の問題は、ウェブが最初に登場したとき、90年代前半から中期の頃には存在しませんでした — ウェブをブラウズする唯一のデバイスはデスクトップとラップトップであったため、ブラウザーの技術者や仕様書の著者は解決策を実装することを考えませんでした。 レスポンシブ画像技術は上記のような問題を解決するために最近になって実装され、ブラウザーに様々な画像ファイル、どれも表示するものは同じですが、ピクセル数が異なる様々な画像(解像度の切り替え)、異なる領域の取り方が異なる様々な画像(アートディレクション)を含めることができます。

+ +
+

メモ: この記事で説明している新機能 — {{htmlattrxref("srcset", "img")}}/{{htmlattrxref("sizes", "img")}}/{{htmlelement("picture")}} — は、最近のデスクトップ及びモバイルのブラウザーのすべてが対応しています(Microsoft Edge ブラウザーも含みますが Internet Explorer は含みません)。

+
+ +

レスポンシブ画像の作り方

+ +

この節では、上で説明した二つの問題を踏まえ、 HTML のレスポンシブ機能を使用してそれらを解決する方法を示します。 なお、上記の例のコンテンツエリアに見られるように、この節では HTML の {{htmlelement("img")}} に注目します。 — サイトヘッダーの画像は単なる装飾なので、 CSS 背景画像を使用して実装します。 CSS はおそらく、 HTML よりもレスポンシブデザインのための優れたツールを持っています(英語)ので、これについては将来 CSS のモジュールで説明します。

+ +

解像度の切り替え: 様々な寸法

+ +

それでは、解像度切り替えで解決したい問題は何でしょうか? 同じ画像コンテンツを、機器に応じて大きくしたり小さくしたりして表示することです。 — これは、例の中の2番目のコンテンツ画像の状況です。 標準的な {{htmlelement("img")}} 要素は、伝統的にブラウザーにソースファイルを一つだけしか指定できません。

+ +
<img src="elva-fairy-800w.jpg" alt="妖精の衣装を着たエルバ">
+ +

しかし、複数の追加のソース画像と、ブラウザーが正しいものを選択する助けになるヒントを提供することができる、新しい2つの属性 — {{htmlattrxref("srcset", "img")}} 及び {{htmlattrxref("sizes", "img")}} — を使用することができます。 この例は、 Github の responsive.html で見ることができます(ソースコードも参照してください)。

+ +
<img srcset="elva-fairy-320w.jpg 320w,
+             elva-fairy-480w.jpg 480w,
+             elva-fairy-800w.jpg 800w"
+     sizes="(max-width: 320px) 280px,
+            (max-width: 480px) 440px,
+            800px"
+     src="elva-fairy-800w.jpg" alt="妖精の衣装を着たエルバ">
+ +

srcset 及び sizes 属性は複雑に見えますが、上記のように属性値のそれぞれの部分を別々の行に書けば、理解することは難しくありません。 それぞれの値にはコンマ区切りのリストが設定されており、それぞれのリストの部分は3つの部分からなっています。 それぞれの中身を見てみましょう。

+ +

srcset は、ブラウザーが選択することができる画像のセットと、それぞれの画像の寸法を定義します。 それぞれのコンマの前に書くものは以下の通りです。

+ +
    +
  1. 画像ファイル名(elva-fairy-480w.jpg)
  2. +
  3. 空白
  4. +
  5. 画像の本質的な幅のピクセル数(480w) — なお、これは単位に px ではなく w を使用します。 これは画像の実際の寸法で、これはコンピューターの画像ファイルを調べると分かります(例えば Mac では Finder で画像を選択して、 Cmd + I を押すと情報画面が出てきます)。
  6. +
+ +

sizes は、一連のメディア条件(例えば画面の幅)であり、特定のメディア条件が成立したときに、どの寸法の画像を選択するのが最適化を示します。 — これらは以前に説明したヒントです。 この場合、それぞれのコンマの前には次のようなものを書きます。

+ +
    +
  1. メディア条件((max-width:480px)) — これについては CSS の記事で詳しく学びますが、今はメディア条件とは画面がなることができる状態であるとだけ言っておきましょう。 この場合、「ビューポートの幅が 480 ピクセル以下であるとき」と言っています。
  2. +
  3. 空白
  4. +
  5. メディア条件が成立したときに埋めるスロットの幅(440px)
  6. +
+ +
+

メモ: スロットの幅については、絶対的な長さ(px, em)又は相対的な長さ(パーセント値など)で指定することができます。 最後のスロットの幅にはメディア条件がないことに気づいたかもしれません。 — これは成立するメディア条件がない場合に使用される既定値です。 ブラウザーは最初に一致した条件の後はすべて無視しますので、メディア条件の順序に注意してください。

+
+ +

したがって、これらの属性を使用すると、ブラウザーは次のようになります。

+ +
    +
  1. そのデバイスの幅を見る。
  2. +
  3. sizes リストの中のどのメディア条件が真であるかを確認する。
  4. +
  5. そのメディア照会で与えられたスロットサイズを見る。
  6. +
  7. 選択したスロットサイズに最も近い srcset リストで参照される画像を読み込みます。
  8. +
+ +

以上です!  この時点で、480px のビューポート幅を持つブラウザーがページを読み込むと、 (max-width: 480px) メディア条件が真となるため、440px スロットが選択されるので、その固有幅(480w)が 440px に最も近い elva-fairy-480w.jpg が読み込まれます。 800px の画像は 128KB ですが、480px の画像は 63KB で 65KB の節約になります。 今、これが多くの写真を持っているページだったと想像してみてください。 この技術を使用することで、モバイルユーザーは多くの帯域幅を節約できます。

+ +

これらの機能をサポートしていない古いブラウザーはそれを無視し、 {{htmlattrxref("src", "img")}} 属性で参照されている画像を通常の方法で読み込みます。

+ +
+

メモ: ドキュメントの {{htmlelement("head")}} には、 <meta name="viewport" content="width=device-width"> という行があります。  これは、モバイルブラウザーがウェブページを読み込むために実際のビューポート幅を使用するように強制します。  (一部のモバイルブラウザーでは、ビューポート幅について嘘をつき、大きなビューポート幅でページを読み込み、読み込んだページを縮小するため、レスポンシブ画像やデザインにはあまり役に立ちません。  これについては、今後のモジュールで詳しく説明します。)

+
+ +

便利な開発者ツール

+ +

ブラウザーには、必要なスロット幅などの作業に役立ついくつかの便利な開発者ツールがあります。 私がそれらを作業していたとき、私は最初にサンプルの非レスポンシブ版(not-responsive.html)を読み込んでからレスポンシブデザインモード(ツール → ウェブ開発 → レスポンシブデザインモード)に行きました。 まるでさまざまなデバイスの画面サイズで表示されているかのようにウェブページのレイアウトを見ることができます。

+ +

ビューポート幅を 320px から 480px に設定して、それぞれのために私はインスペクタへ行き、私たちが興味を持っている <img> 要素をクリックしてから、画面の右側にある [レイアウト] タブの [ボックスモデル] でそのサイズを調べました。 これはあなたが必要とする固有の画像幅を与えるはずです。

+ +

インスペクタで強調表示された画像要素を持つfirefox開発者ツールのスクリーンショット。サイズは440 x 293ピクセルです。次に、ビューポート幅を任意に設定して(たとえば、幅を狭く設定する)、ネットワークインスペクタ(ツール → ウェブ開発 → ネットワーク)を開き、ページを再読み込みすることで、srcset が機能しているかどうかを確認できます。 これにより、ウェブページを構成するためにダウンロードされた資産のリストが表示されます。 ここでダウンロード用に選択された画像ファイルを確認できます。

+ +
+

メモ: Chrome でテストするときは、[その他ツール] → [デベロッパー ツール] → [ネットワーク] タブの [Disable cache (when DevTools is open)] チェックボックスをオンにして、開発者ツールが開いているときにキャッシュを無効にします。  そうしないと、Chrome はキャッシュされた画像をより適切なものより優先します。

+
+ +

firefox開発者ツールのネットワークインスペクタのスクリーンショット。ページのHTMLがダウンロードされていることと、レスポンシブ画像の2つの800ワイドバージョンを含む3つの画像

+ +

解像度の切り替え: 同じサイズ、異なる解像度

+ +

複数の画面解像度をサポートしていても、誰もが画面上で同じ実世界サイズで画像を見る場合は、sizes を指定せずに x 記述子を指定した srcset を使用してブラウザーに適切な解像度の画像を選択させることができます — やや簡単な構文です! これは srcset-resolutions.html のようなものです(ソースコードも参照してください)。
+  

+ +
<img srcset="elva-fairy-320w.jpg,
+             elva-fairy-480w.jpg 1.5x,
+             elva-fairy-640w.jpg 2x"
+     src="elva-fairy-640w.jpg" alt="妖精の衣装を着たエルバ">
+
+ +

妖精の衣装を着た小さな女の子の絵、古いカメラのフィルム効果が画像に適用されるこの例では、次の CSS が画像に適用され、画面上に 320 ピクセルの幅が設定されます(CSS ピクセルとも呼ばれます)。

+ +
img {
+  width: 320px;
+}
+ +

この場合、sizes は必要ありません。ブラウザーは、表示されている画面がどの解像度であるかを単純に調べ、srcset で参照される最も適切な画像を提供します。 したがって、ページにアクセスするデバイスが標準解像度や低解像度の画面を持っていて、1つのデバイスピクセルが各 CSS ピクセルを表している場合、elva-fairy-320w.jpg の画像が読み込まれます(1x は暗黙のため、含める必要はありません)。 デバイスが CSS ピクセルあたり2つのデバイスピクセルの高解像度を持つ場合、elva-fairy-640w.jpg の画像が読み込まれます。 640px の画像は 93KB ですが、320px の画像は 39KB です。

+ +

アートディレクション

+ +

要約すると、アートディレクションの問題は、表示される画像を異なる画像表示サイズに合うように変更したいことを含みます。 たとえば、デスクトップブラウザーで見たときに中央に人がいる大きな風景をウェブサイトに表示している場合、モバイルブラウザーでウェブサイトを表示すると縮小され、人がとても小さくて見えにくいので格好悪くなります。 モバイルでは、人にズームインしたより小型のポートレイト画像を表示するほうがよいでしょう。  {{htmlelement("picture")}} 要素は、この種の解決法を実装することを可能にします。
+
+ オリジナルの not-responsive.html の例に戻ると、アートディレクションがひどく必要な画像があります。

+ +
<img src="elva-800w.jpg" alt="クリスは立って彼の娘エルバを保持します">
+ +

{{htmlelement("picture")}} でこれを修正しましょう!   <video><audio>と同様に、<picture> 要素はラッパーで、ブラウザーが選択できるいくつかの異なるソースを提供するいくつかの {{htmlelement("source")}} 要素を含み、次に極めて重要な {{htmlelement("img")}} 要素が続きます。 responsive.html のコードは次のようになります。

+ +
<picture>
+  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
+  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
+  <img src="elva-800w.jpg" alt="クリスは立って彼の娘エルバを保持します">
+</picture>
+
+ + + +

このコードでは、以下に示すように、広い画面と狭い画面の両方に適切な画像を表示することができます。

+ +

広い画面で表示された私たちのサンプルサイト - ここでは最初の画像は大丈夫です。中央のディティールを見るのに十分です。最初の画像をポートレートに切り替えるために使用されるpicture要素を使用した狭い画面で表示されたサンプルサイトは、ディティールをクローズアップし、狭い画面でより便利になりました

+ +
+

メモ: media 属性は、アートディレクションのシナリオでのみ使用してください。 media を使用する場合は、sizes 属性内でメディア条件も指定しないでください。

+
+ +

なぜ CSS や JavaScript を使ってこれを行うことができないのですか?

+ +

ブラウザーがページの読み込みを開始すると、メインのパーサーがページの CSS と JavaScript を読み込んで解釈する前に、画像のダウンロード(先読み)を開始します。 これは便利なテクニックで、平均してページ読み込み時間の 20% を削減します。 しかし、レスポンシブ画像では役に立ちません。 そのため、srcset のような解決法を実装する必要があります。 たとえば、 {{htmlelement("img")}} 要素を読み込んでから JavaScript でビューポートの幅を検出し、必要に応じて元の画像をより小さなものに動的に変更することはできません。 それまでには、元の画像が既に読み込まれていて、さらに小さい画像も読み込むことになります。 これは、レスポンシブ画像の条件ではさらに悪化します。

+ + + +

現代の画像フォーマットを大胆に使用する

+ +

小さなファイルサイズと高品質を同時に維持できる、エキサイティングな新しい画像フォーマット(WebP や PEG-2000 など)がいくつかあります。 しかし、ブラウザーのサポートにはむらがあります。

+ +

<picture> は、古いブラウザーにも対応しています。 MIME タイプを type 属性内に指定すると、ブラウザーはサポートしていないファイルタイプを直ちに拒否できます。

+ +
<picture>
+  <source type="image/svg+xml" srcset="pyramid.svg">
+  <source type="image/webp" srcset="pyramid.webp">
+  <img src="pyramid.png" alt="4つの正三角形から構築された通常のピラミッド">
+</picture>
+
+ + + +

能動的学習: あなた自身のレスポンシブ画像の実装

+ +

この能動的学習では、私たちはあなたが勇敢に(ほとんど)一人で行くことを期待しています。 <picture> を使って、あなた自身の適切なアートディレクションの狭い画面や広い画面と、srcset を使用する解像度切り替えの例を実装してください。

+ +
    +
  1. あなたのコードを格納するためのシンプルな HTML を書く(必要に応じて not-responsive.html を出発点として使用する)
  2. +
  3. どこかから細かいディテールが入った素晴らしい広い画面のランドスケープ画像を探してきましょう。 グラフィックスエディタを使用してウェブサイズの画像を作成し、それをトリミングしてディテールを拡大した小さな部分を表示し、2番目の画像を作成します(約 480px の幅がこれに適しています)。
  4. +
  5. <picture> 要素を使用して、アートディレクション画像切り替えを実装します。
  6. +
  7. サイズの異なる複数の画像ファイルを作成し、それぞれが同じ画像を表示します。
  8. +
  9. srcsetsizes を使用して、異なる解像度で同じサイズの画像を提供するか、異なるビューポートの幅で異なる画像サイズを提供するかのいずれかの解像度切り替えの例を作成します。
  10. +
+ +
+

メモ: 上記のように、ブラウザーの開発者ツールの助けを借りて、必要なサイズにしてください。

+
+ +

まとめ

+ +

それはレスポンシブ画像のラップです — あなたはこれらの新しいテクニックで遊ぶことを楽しんでください。 要約すると、私たちがここで議論してきた2つの明確な問題があります。

+ + + +

これはまた、マルチメディアと埋め込みのモジュール全体を閉じます!  先に進む前に行うべき唯一のことは、マルチメディアの評価を試み、あなたがどのように乗り出すかを見ることです。 楽しんでください。

+ +

関連項目

+ + + +
{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}
+ +
+

このモジュール

+ + +
diff --git a/files/ja/learn/html/multimedia_and_embedding/video_and_audio_content/index.html b/files/ja/learn/html/multimedia_and_embedding/video_and_audio_content/index.html new file mode 100644 index 0000000000..205d7b7027 --- /dev/null +++ b/files/ja/learn/html/multimedia_and_embedding/video_and_audio_content/index.html @@ -0,0 +1,307 @@ +--- +title: 動画と音声のコンテンツ +slug: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +tags: + - Article + - Audio + - Beginner + - Guide + - HTML + - Video + - captions + - subtitles + - track + - ガイド + - 初心者 + - 動画 + - 記事 + - 音声 +translation_of: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}
+ +

Webページに簡単な画像を追加するのができるようになったので、次のステップは HTML 文書に動画と音声のプレイヤーを追加することです!  この記事では {{htmlelement("video")}} と {{htmlelement("audio")}} 要素を使ってそうすることを見ていきます。それから動画にキャプションや字幕を追加する方法を見て完了します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータリテラシー、インストールされた基本ソフトウェアファイル操作の基本知識、HTML の基礎知識(HTML 入門)、および HTML の画像
目的:動画や音声のコンテンツをWebページに埋め込み、動画にキャプションや字幕を追加する方法を学びます。
+ +

Webでの動画と音声

+ +

Web 開発者は、あらゆる種類の動画 (動画ファイルはテキストや画像よりもはるかに大きい) をサポートするのに十分な速さがある帯域幅を使い始めた2000年代初頭以来、Web 上で動画や音声を長時間使用したいと考えていました。初期段階では、HTML などのネイティブな Web テクノロジーでは動画や音声を Web に埋め込むことができなかったため、Flash (および後で Silverlight) などの独自技術 (またはプラグインベース) が一般的になりました。この種の技術はうまくいきましたが、HTML/CSS の機能、セキュリティの問題、アクセシビリティの問題でうまく機能しないなど、さまざまな問題がありました。

+ +

もし正しく行っていれば、ネイティブな解決策はこれの多くを解決します。幸いにも、数年後、{{glossary("HTML5")}} 仕様には、{{htmlelement("video")}} 要素と {{htmlelement("audio")}} 要素、およびそれらを制御するためのいくつかのぴかぴかの新しい {{Glossary("JavaScript")}} {{Glossary("API")}} が追加されました。ここでは JavaScript を見ていません — HTML で実現できる基本的な基礎だけです。

+ +

音声や動画のファイルを作成する方法は教えません — 完全に異なる知識や技能が必要です。あなたが実験のための音声や動画のファイルとサンプルコードを手に入れることができない場合に備えて、それを提供しています。

+ +
+

メモ: ここから始める前に、YouTubeDailymotionVimeo のような {{glossary("OVP")}} (オンライン動画プロバイダ) と Soundcloud のようなオンライン音声プロバイダがあることも知っておく必要があります。そのような企業は、動画をホストして消費するための便利で簡単な方法を提供するので、莫大な帯域幅の消費を心配する必要はありません。OVP は通常、Web ページに動画や音声を埋め込むための既製コードを提供しています。その道を行くなら、この記事で取り上げるいくつかの困難を避けることができます。この種のサービスについては、次の記事でもう少し詳しく説明します。

+
+ +

<video> 要素

+ +

{{htmlelement("video")}} 要素を使用すると、動画を非常に簡単に埋め込むことができます。本当に簡単な例は次のようになります。

+ +
<video src="rabbit320.webm" controls>
+  <p>お使いのブラウザは HTML5 動画をサポートしていません。その代わりに<a href="rabbit320.webm">動画へのリンク</a>があります。</p>
+</video>
+ +

機能は次のとおりです。

+ +
+
{{htmlattrxref("src","video")}}
+
{{htmlelement("img")}} 要素と同じように、src (ソース) 属性には、埋め込みたい動画へのパスが含まれています。これは、まったく同じように動作します。
+
{{htmlattrxref("controls","video")}}
+
ユーザは、動画や音声の再生を制御できる必要があります (特にてんかんを患っている人にとっては重要です)。controls 属性を使用してブラウザ独自のコントロールインターフェイスを組み込むか、適切な JavaScript API を使用してインターフェイスを構築する必要があります。少なくとも、インターフェイスにはメディアの開始と停止、および音量の調整が含まれている必要があります。
+
<video> タグ内の段落
+
これは代替コンテンツと呼ばれ、ページにアクセスしているブラウザが <video> 要素をサポートしていない場合に表示され、古いブラウザでの代替手段となります。これはあなたが好きなことができます。この場合、動画ファイルへの直接リンクが提供されているため、使用しているブラウザに関係なく、ユーザは少なくとも何らかの方法でアクセスできます。
+
+ +

埋め込み動画は次のようになります。

+ +

小さな白いウサギの動画を表示するシンプルなビデオプレーヤー

+ +

ここでサンプルをライブで試すことができます(ソースコードも参照してください)。

+ +

複数のフォーマットをサポートする

+ +

上の例では、Safari や Internet Explorer などのブラウザで上記のライブのリンクにアクセスしたなら、すでに気づいているかもしれない問題があります。動画は再生されません!  これは、さまざまなブラウザが異なる動画 (および音声) のフォーマットをサポートしているためです。

+ +

用語をすばやく説明しましょう。MP3、MP4、WebM などの形式はコンテナフォーマットと呼ばれます。それらは、音声トラック、動画トラック (動画の場合)、および提示されるメディアを記述するメタデータなど、歌または動画全体を構成する異なる部分を含みます。

+ +

音声トラックと動画トラックもさまざまなフォーマットになっています。たとえば:

+ + + +

オーディオプレーヤーは、音声トラックを直接再生する傾向があります。たとえば、MP3 または Ogg ファイル。これらはコンテナを必要としません。

+ +
+

メモ: 音声と動画のコーデックの互換性表からわかるように、それほど単純ではありません。さらに、多くのモバイルプラットフォームのブラウザは、サポート対象のシステムのメディアプレーヤーに再生するためにそれを渡すことで、サポートされていないフォーマットを再生することができます。しかしこれは今のところできます。

+
+ +

上記のフォーマットは、動画と音声を管理可能なファイルに圧縮するために存在します (生の動画と音声は非常に大きい)。ブラウザには、Vorbis や H.264 などの{{Glossary("Codec","コーデック")}}が含まれています。これらのコーデックは、圧縮された音声と動画を2進数字に変換して戻すために使用されます。上記のように、残念ながらブラウザはすべて同じコーデックをサポートしているわけではないので、メディアの制作ごとに複数のファイルを用意する必要があります。メディアをデコードするために適切なコーデックがない場合、再生されません。

+ +
+

メモ: なぜこのような状況が存在するのだろうか。MP3 (音声用)と MP4/H.264 (動画用) はどちらも広くサポートされており、良質です。しかし、それらはまた、特許を握られている — 米国特許は、MP3 は2017年まで、H.264 は2027年までカバーしています。つまり、特許を保有していないブラウザは、これらのフォーマットをサポートするために膨大な金額を支払う必要があります。さらに、多くの人々は、制限されたソフトウェアを原則として避け、オープンフォーマットを支持しています。このため、さまざまなブラウザに複数のフォーマットを提供する必要があります。

+
+ +

だから私たちはこれをどうやってやるのか?  以下の更新された例を見てください (それをここでライブで試してみてください)。

+ +
<video controls>
+  <source src="rabbit320.mp4" type="video/mp4">
+  <source src="rabbit320.webm" type="video/webm">
+  <p>お使いのブラウザは HTML5 動画をサポートしていません。その代わりに<a href="rabbit320.mp4">動画へのリンク</a>があります。</p>
+</video>
+ +

ここでは実際の <video> タグから src 属性を取り出し、独自のソースを指す別々の {{htmlelement("source")}} 要素を追加しました。この場合、ブラウザは <source> 要素を通過し、サポートするコーデックがある最初の要素を再生します。WebM や MP4 のソースを含めれば、最近のほとんどのプラットフォームやブラウザで動画を再生できるはずです。

+ +

<source> 要素には type 属性もあります。これはオプションですが、動画ファイルの  {{glossary("MIME type","MIME タイプ")}}が含まれており、ブラウザがこれらを読み込んで理解できない動画をすぐにスキップすることができます。それらが含まれていない場合、ブラウザは各ファイルを読み込んで再生しようとしますが、より多くの時間とリソースを必要とします。

+ +
+

メモ: サポートされているメディアフォーマットの記事には、一般的な {{glossary("MIME type","MIME タイプ")}}がいくつか含まれています。

+
+ +

その他の <video> 機能

+ +

HTML5 動画に含めることができる他の多くの機能があります。以下の3番目の例を見てください。

+ +
<video controls width="400" height="400"
+       autoplay loop muted
+       poster="poster.png">
+  <source src="rabbit320.mp4" type="video/mp4">
+  <source src="rabbit320.webm" type="video/webm">
+  <p>お使いのブラウザは HTML5 動画をサポートしていません。その代わりに<a href="rabbit320.mp4">動画へのリンク</a>があります。</p>
+</video>
+
+ +

これにより、次のような出力が得られます。

+ +

再生する前にポスター画像を表示するビデオプレーヤー。 ポスター画像には "HTML5 video example, OMG hell yeah!" と書いてあります。新しい機能は次のとおりです。

+ +
+
{{htmlattrxref("width","video")}} と {{htmlattrxref("height","video")}}
+
これらの属性または {{Glossary("CSS")}} を使用して動画サイズを制御することができます。どちらの場合も、動画は元の縦横比 (アスペクト比) を維持します。アスペクト比が設定したサイズによって維持されない場合、動画は水平方向にスペースを埋めるように拡大し、デフォルトでは満たされていないスペースには無地の背景色が与えられます。
+
{{htmlattrxref("autoplay","video")}}
+
この属性は、ページの残りの部分がロードされている間に音声または動画の再生をすぐに開始します。ユーザに実際に迷惑をかけることがあるので、サイトで動画 (または音声) を自動再生することはお勧めしません。
+
{{htmlattrxref("loop","video")}}
+
この属性は、動画 (または音声) が終了するたびに再生を開始させます。これは迷惑になることもありますので、本当に必要な場合にのみ使用してください。
+
{{htmlattrxref("muted","video")}}
+
この属性を使用すると、デフォルトで音声をオフにしてメディアを再生します。
+
{{htmlattrxref("poster","video")}}
+
この属性は、動画の再生前に表示される画像の URL を値としてとります。これは、スプラッシュ画面または広告画面に使用するためのものです。
+
{{htmlattrxref("preload","video")}}
+
+

この属性は、大きなファイルをバッファリングする要素で使用されます。3つの値のいずれかを取ることができます。

+ +
    +
  • "none" はファイルをバッファリングしません
  • +
  • "auto" はメディアファイルをバッファリングする
  • +
  • "metadata" はファイルのメタデータのみをバッファリングする
  • +
+
+
+ +

上記の例は Github でライブで再生することができます (ソースコードも参照してください)。ライブバージョンには autoplay 属性は含まれていません — ページが読み込まれるとすぐに動画が再生され始めると、ポスターを見ることはできません!

+ +

<audio> 要素

+ +

{{htmlelement("audio")}} 要素は、{{htmlelement("video")}} 要素とまったく同じように動作しますが、以下に説明するように若干の違いがあります。典型的な例は次のようになります。

+ +
<audio controls>
+  <source src="viper.mp3" type="audio/mp3">
+  <source src="viper.ogg" type="audio/ogg">
+  <p>お使いのブラウザは HTML5 音声をサポートしていません。代わりに<a href="viper.mp3">音声へのリンク</a>があります。</p>
+</audio>
+ +

これはブラウザで次のようなものを生成します。

+ +

再生ボタン、タイマー、音量コントロール、および進行状況バーを備えたシンプルなオーディオプレーヤー

+ +
+

メモ: Github で音声デモをライブで実行することもできます (オーディオプレーヤーのソースコードも参照してください)。

+
+ +

ビジュアルコンポーネントがないため、ビデオプレーヤーよりもスペースが少なくなります — 音声を再生するコントロールを表示するだけで済みます。HTML5 動画とのその他の相違点は次のとおりです。

+ + + +

これ以外について <audio> は、<video> と同じ機能をすべてサポートしています。詳細については、上記のセクションを参照してください。

+ +

動画のテキストトラックを表示する

+ +

ここでは、もっと知りたいと思う、やや高度なコンセプトについて説明します。多くの人々は、少なくともある時点では、Web上で見つけた音声や動画のコンテンツを聞くことができない、または聞きたくない。たとえば:

+ + + +

音声や動画で話されている言葉の写しをこれらの人々に提供できるのはうれしいことではないでしょうか?  HTML5 動画のおかげで、WebVTT フォーマットと {{htmlelement("track")}} 要素を使用することができます。

+ +
+

メモ: "転記" と "写し" とは、話し言葉をテキストとして書き留めることを意味します。

+
+ +

WebVTT は、複数のテキスト文字列を含むテキストファイルを書くための形式です。動画内の何時に各テキスト文字列を表示するかや、限られたスタイリング/位置情報などのメタデータが一緒に含まれています。これらのテキスト文字列はキューと呼ばれ、さまざまな目的のためにさまざまなタイプを表示できます。最も一般的なものは次のとおりです。

+ +
+
字幕 (subtitles)
+
音声で話されている言葉を理解していない人々のための外国の翻訳材料。
+
キャプション (captions)
+
対話や重要な物音の描写の同期化で、音声を聞くことができない人が何が起こっているのかを理解できるようにする。
+
時限記述 (timed descriptions)
+
視覚障害者にサービスを提供するために、音声に変換するためのテキスト。
+
+ +

典型的な WebVTT ファイルは次のようになります。

+ +
WEBVTT
+
+1
+00:00:22.230 --> 00:00:24.606
+これが最初の字幕です。
+
+2
+00:00:30.739 --> 00:00:34.074
+これは二番目です。
+
+  ...
+
+ +

これを HTML メディアの再生と一緒に表示するには、以下を行う必要があります。

+ +
    +
  1. 適切な場所に .vtt ファイルとして保存します。
  2. +
  3. {{htmlelement("track")}} 要素で .vtt ファイルにリンクします。<track><audio> または <video> 内に配置する必要がありますが、すべての <source> 要素の後に配置する必要があります。{{htmlattrxref("kind","track")}} 属性を使用して、キューが subtitlescaptions、または descriptions のいずれであるかを指定します。さらに、{{htmlattrxref("srclang","track")}} 属性を使用して、字幕が書かれた言語をブラウザに伝えます。
  4. +
+ +

ここに例があります。

+ +
<video controls>
+    <source src="example.mp4" type="video/mp4">
+    <source src="example.webm" type="video/webm">
+    <track kind="subtitles" src="subtitles_en.vtt" srclang="en">
+</video>
+ +

これにより、字幕が表示された動画になります。これは次のようなものです。

+ +

再生、停止、音量、キャプションのオン/オフなどのスタンドコントロールを備えたビデオプレーヤー。 動画の再生には、槍のような武器を持つ男のシーンが表示され、キャプションには "Esta hoja tiene pasado oscuro." と表示されます。

+ +

詳しくは、HTML5 動画にキャプションと字幕を追加するをご覧ください。Github には Ian Devlin によって書かれたこの記事の例があります (ソースコードも参照してください)。この例では、JavaScript を使用してさまざまな字幕を選択できるようにしています。字幕をオンにするには、[CC] ボタンを押して、英語、ドイツ語、スペイン語のオプションを選択する必要があります。

+ +
+

メモ: テキストトラックは検索エンジンが特にテキスト上で成功するため、{{glossary("SEO")}} にも役立ちます。テキストトラックを使用すると、検索エンジンは動画の途中地点に直接リンクすることもできます。

+
+ +

アクティブラーニング: 自分の音声と動画を埋め込む

+ +

この能動的学習のために、(理想的には) あなたが世界に出て自分の動画や音声を録画するのが好ましいです — 最近の携帯電話では、音声や動画を非常に簡単に録音することができ、コンピュータに転送することができれば使用できます。動画の場合は WebM と MP4、音声の場合は MP3 と Ogg に行き着くには、変換する必要があるかもしれませんが、Miro Video ConverterAudacity など、あまり多くの手間をかけることなく、これを行うための十分なプログラムがあります。さあ、行ってください!

+ +

動画や音声を入手できない場合は、このサンプルを自由に使用してこの演習を行うことができます。サンプルコードを参照のために使用することもできます。

+ +

次のことをしましょう。

+ +
    +
  1. 音声と動画のファイルをコンピュータの新しいディレクトリに保存します。
  2. +
  3. 同じディレクトリに index.html と呼ばれる新しい HTML ファイルを作成します。
  4. +
  5. ページに <audio> 要素と <video> 要素を追加します。それらにデフォルトのブラウザコントロールを表示させます。
  6. +
  7. 両方の要素に <source> 要素を付けて、ブラウザが最もよくサポートするフォーマットを見つけて読み込むようにします。これらは type 属性を含むべきです。
  8. +
  9. <video> 要素に、動画が再生される前に表示されるポスターを指定します。自分のポスターのグラフィックを作成して楽しんでください。
  10. +
+ +

追加のボーナスとして、テキストトラックの研究や動画にキャプションを追加する方法などがあります。

+ +

まとめ

+ +

それはラップです。Web ページで動画や音声を楽しみながら楽しく遊びました!  次の記事では、{{htmlelement("iframe")}} や {{htmlelement("object")}} などの技術を使用して、Webにコンテンツを埋め込む他の方法について説明します。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}

+ +

このモジュール

+ + + +
+
+ + diff --git a/files/ja/learn/html/tables/advanced/index.html b/files/ja/learn/html/tables/advanced/index.html new file mode 100644 index 0000000000..bb33f6e292 --- /dev/null +++ b/files/ja/learn/html/tables/advanced/index.html @@ -0,0 +1,475 @@ +--- +title: HTML 表の高度な機能とアクセシビリティ +slug: Learn/HTML/Tables/Advanced +tags: + - Accessibility + - Advanced + - Article + - Beginner + - CodingScripting + - HTML + - Headers + - Learn + - caption + - scope + - sumary + - table + - tbody + - tfoot + - thead +translation_of: Learn/HTML/Tables/Advanced +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}
+ +

このモジュールの2番目の記事では、HTML テーブルのより高度な機能 (キャプション/要約、行をテーブルのヘッダー、本文、フッターのセクションにグループ化するなど) や、視覚障碍のあるユーザのためのテーブルのアクセシビリティについて調べます。

+ + + + + + + + + + + + +
前提知識:HTML の基礎 (HTML 入門を参照)。
目標:表のより高度な機能やアクセシビリティについて学ぶ
+ +

<caption> を用いて表にキャプションを追加する

+ +

テーブルにキャプションを付けるには、{{htmlelement("caption")}} 要素内に配置し、それを {{htmlelement("table")}} 要素内にネストします。これは <table> 要素の開始タグすぐ下に置くべきです。

+ +
<table>
+  <caption>ジュラ紀の恐竜</caption>
+
+  ...
+</table>
+ +

上記の簡単な例から推測できるように、キャプションには表の内容の説明が含まれています。 これは、ページに目を通して表が役に立つかどうかをすぐに把握したい全ての読者にとって便利ですが、特に盲目のユーザにとっては便利です。 スクリーンリーダーに表の内容を知るためだけに多くのセルの内容を読み上げさせるのではなく、キャプションを頼りにして表をより詳細に読み取るかどうかを決定できます。

+ +

キャプションは <table> タグのすぐ下に配置します。

+ +
+

: {{htmlattrxref("summary","table")}} 属性は、<table> 要素で説明を提供するためにも使用できます。 これはスクリーンリーダーによっても読み上げられます。 ただし、summary は HTML5 仕様では{{glossary("deprecated","推奨されておらず")}}、(ページには表示されないので)晴眼のユーザには読むことができないため、代わりに <caption> 要素を使用することをお勧めします。

+
+ +

アクティブラーニング: キャプションの追加

+ +

前の記事で最初に出会った例を再考しながら、これを試してみましょう。

+ +
    +
  1. HTML 表の基本の最後から語学教師の学校の時間割を開くか、または timetable-fixed.html ファイルのローカルコピーを作成してください。
  2. +
  3. 表に適切なキャプションを追加します。
  4. +
  5. コードを保存してブラウザで開くと、コードがどのように見えるかがわかります。
  6. +
+ +
+

: GitHub で私たちのバージョンを見つけることができます —  timetable-caption.html を見てください(ライブもご覧ください)。

+
+ +

<thead>、<tfoot>、<tbody> を用いて構造を追加する

+ +

表の構造がもう少し複雑になったら、それらにもっと構造的な定義を与えることは有用です。 これを行う明確な方法の1つは、{{htmlelement("thead")}}、{{htmlelement("tfoot")}}、および {{htmlelement("tbody")}} を使用することです。 これにより、表のヘッダー、フッター、および本体のセクションをマークアップできます。

+ +

これらの要素によって表がスクリーンリーダーのユーザにアクセスしやすくなることはなく、また視覚的な機能強化が生じることもありません。 ただし、これらはスタイリングやレイアウトに非常に役立ちます — CSS を表に追加するための便利なフックとして機能します。 いくつか興味深い例を挙げると、長い表の場合、全ての印刷ページで表のヘッダーとフッターを繰り返すようにしたり、表の本体を単一ページに表示して、上下にスクロールして内容を表示したりすることができます。

+ +

それらを使用するには、

+ + + +
+

: <tbody> は常に全ての表に含まれていて、コードで指定しない場合は暗黙的に含まれます。 これを確認するには、<tbody> を含まない以前の例の1つを開き、ブラウザ開発者ツールの HTML コードを調べます — ブラウザによってこのタグが追加されたことがわかります。 なぜそれを含まないのかと疑問に思うかもしれません — すべき、表の構造とスタイリングがより細かく制御できるためです。

+
+ +

アクティブラーニング: 表構造の追加

+ +

これらの新しい要素を実行してみましょう。

+ +
    +
  1. まず、新しいフォルダに spending-record.htmlminimal-table.css のローカルコピーを作成します。
  2. +
  3. ブラウザでそれを開いてみてください — あなたはそれが問題ないように見えますが、それは改善されることになるかもしれません。 支出額の合計を含む "SUM" 行は間違った場所にあるように思われ、コードから抜けている細部がいくつかあります。
  4. +
  5. 明白なヘッダー行を <thead> 要素内に、 "SUM" 行を <tfoot> 要素内に、そして残りの内容を <tbody> 要素内に配置します。
  6. +
  7. 保存して更新すると、<tfoot> 要素を追加すると "SUM" 行が表の一番下に移動していることがわかります。
  8. +
  9. 次に、{{htmlattrxref("colspan","td")}} 属性を追加して "SUM" セルを最初の4列にまたがるようにします。そのため、実際の数は "Cost" 列の下部に表示されます。
  10. +
  11. これらの要素が CSS を適用するためにどれほど有用であるかのアイデアをあなたに与えるために、表にいくつかの簡単な追加のスタイリングを追加しましょう。 HTML 文書の <head> の中には、空の {{htmlelement("style")}} 要素があります。 この要素内に、次の CSS コード行を追加します。 +
    tbody {
    +  font-size: 90%;
    +  font-style: italic;
    +}
    +
    +tfoot {
    +  font-weight: bold;
    +}
    +
    +
  12. +
  13. 保存して更新し、結果を確認します。 <tbody> 要素と <tfoot> 要素が適切に配置されていない場合は、同じスタイルを適用するためにはるかに複雑なセレクタ/規則を記述する必要があります。
  14. +
+ +
+

: 現時点で私たちはあなたが CSS を完全に理解しているとは思っていません。 あなたが私たちの CSS モジュールを一通り学ぶとき、これについてより多くを学ぶでしょう(CSS 入門は始めるのに良い場所です。 スタイリングされた表に関する具体的な記事もあります)。

+
+ +

完成した表は次のようになります。

+ + + +

{{ EmbedLiveSample('Hidden_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}

+ +
+

: Github では、それを spending-record-finished.html として見つけることもできます(ライブもご覧ください)。

+
+ +

ネストした表

+ +

<table> 要素を含む完全な構造を含める限り、表を別の表の中にネストすることは可能です。 そのマークアップがスクリーンリーダーのユーザにとって混乱を招きやすく、アクセスしにくくなるため、これは一般的にはあまり推奨されません。 多くの場合、既存の表に追加のセル/行/列を挿入することもできます。 ただし、他のソースからコンテンツを簡単にインポートしたい場合などは、時々必要になります。

+ +

次のマークアップは、単純なネストした表を示しています。

+ +
<table id="table1">
+  <tr>
+    <th>title1</th>
+    <th>title2</th>
+    <th>title3</th>
+  </tr>
+  <tr>
+    <td id="nested">
+      <table id="table2">
+        <tr>
+          <td>cell1</td>
+          <td>cell2</td>
+          <td>cell3</td>
+        </tr>
+      </table>
+    </td>
+    <td>cell2</td>
+    <td>cell3</td>
+  </tr>
+  <tr>
+    <td>cell4</td>
+    <td>cell5</td>
+    <td>cell6</td>
+  </tr>
+</table>
+ +

その出力は次のようになります。

+ + + + + + + + + + + + + + + + + + + +
title1title2title3
+ + + + + + + + +
cell1cell2cell3
+
cell2cell3
cell4cell5cell6
+ +

視覚障碍者向けの表

+ +

データ表の使用方法について簡単に説明しましょう。 表は、データにすばやくアクセスし、さまざまな値を検索できるようにするための便利なツールです。例えば、昨年8月に Gent で販売された指輪 (Rings) の数を確認するには、下の表を見てください。その情報を理解するために、この表内のデータとその列ヘッダーや行ヘッダーとの間の視覚的な関連付けを行います。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Items Sold August 2016
ClothesAccessories
TrousersSkirtsDressesBraceletsRings
BelgiumAntwerp5622437223
Gent4618506115
Brussels5127386928
The NetherlandsAmsterdam8934698538
Utrecht8012433619
+ +

しかし、あなたがそれらの視覚的な関連付けをすることができないならば、どうですか? では、どのようにして上記のような表を読むことができますか? 視覚障碍者は、Webページの情報を読み上げるスクリーンリーダーをよく使用します。 平文を読んでいるときはこれは問題ありませんが、表を解釈することは視覚障碍者にとっては非常に困難な場合があります。 それでも、適切なマークアップを使用して、視覚的な関連付けをプログラムによる関連付けに置き換えることができます。

+ +
+

: WHO のデータによると、2017年の視覚障碍者は約253百万人です。

+
+ +

記事のこのセクションでは、可能な限りアクセス可能な表にするためのその他の手法について説明します。

+ +

列ヘッダーと行ヘッダーを使用する

+ +

スクリーンリーダーは全てのヘッダーを識別し、それらを使用してそれらのヘッダーとそれらが関連するセルとの間のプログラムによる関連付けを行います。 列ヘッダーと行ヘッダーの組み合わせにより、各セル内のデータが識別および解釈されるため、スクリーンリーダーのユーザは、晴眼のユーザの場合と同様に表を解釈できます。

+ +

前の記事ですでにヘッダーについて説明しました — <th> 要素によるヘッダーの追加を参照してください。

+ +

scope 属性

+ +

この記事の新しい話題は {{htmlattrxref("scope","th")}} 属性です。 これは <th> 要素に追加して、ヘッダーがどのセルのヘッダーであるかをスクリーンリーダーに正確に伝えることができます — 例えば、それが入っているのは行のヘッダーなのか、それとも列のヘッダーなのか? 先ほどの支出記録の例を振り返ると、次のように列ヘッダーを列ヘッダーとして明確に定義できます。

+ +
<thead>
+  <tr>
+    <th scope="col">Purchase</th>
+    <th scope="col">Location</th>
+    <th scope="col">Date</th>
+    <th scope="col">Evaluation</th>
+    <th scope="col">Cost (€)</th>
+  </tr>
+</thead>
+ +

そして各行は次のように定義されたヘッダーを持つことができます(列ヘッダーと同様に行ヘッダーを追加した場合)。

+ +
<tr>
+  <th scope="row">Haircut</th>
+  <td>Hairdresser</td>
+  <td>12/09</td>
+  <td>Great idea</td>
+  <td>30</td>
+</tr>
+ +

スクリーンリーダーは、このように構成されたマークアップを認識し、例えば、ユーザが列全体または行全体を一度に読み上げることを可能にします。

+ +

scope には、さらに2つの可能な値、colgrouprowgroup があります。 これらは、複数列または複数行の上に位置する見出しに使用されます。 このセクションの最初にある "Items Sold August 2016" の表を見ると、"Clothes" セルが "Trousers"、"Skirts"、"Dresses" のセルの上に位置することがわかります。 これらのセルは全てヘッダー(<th>)としてマークアップするべきで、 "Clothes" はそれらの上に位置し、他の3つの小見出しを定義する見出しです。 従って、"Clothes" は scope="colgroup" の属性を得るべきですが、それ以外は scope="col" の属性を得ます。

+ +

id 属性と headers 属性

+ +

scope 属性を使用する代わりに、{{htmlattrxref("id")}} 属性と {{htmlattrxref("headers", "td")}} 属性を使用して、ヘッダーとセル間の関連付けを作成することもできます。 使い方は次のとおりです。

+ +
    +
  1. <th> 要素に一意の id を追加します。
  2. +
  3. <td> 要素に headers 属性を追加します。 各 headers 属性には、そのセルのヘッダーとして機能する全ての <th> 要素の id のリストを、スペースで区切って含める必要があります。
  4. +
+ +

これは HTML の表に、表内の各セルの位置の明示的な定義を与えます。 これは、それが属する各列と各行のヘッダーによって定義されます。 スプレッドシートのようなものです。 それがうまく機能するためには、表は本当に列と行の両方のヘッダーを必要とします。

+ +

支出コストの例に戻ると、前の2つのコードは次のように書き直すことができます。

+ +
<thead>
+  <tr>
+    <th id="purchase">Purchase</th>
+    <th id="location">Location</th>
+    <th id="date">Date</th>
+    <th id="evaluation">Evaluation</th>
+    <th id="cost">Cost (€)</th>
+  </tr>
+</thead>
+<tbody>
+<tr>
+  <th id="haircut">Haircut</th>
+  <td headers="location haircut">Hairdresser</td>
+  <td headers="date haircut">12/09</td>
+  <td headers="evaluation haircut">Great idea</td>
+  <td headers="cost haircut">30</td>
+</tr>
+
+  ...
+
+</tbody>
+ +
+

: この方法では、ヘッダーとデータセルの間に非常に正確な関連付けが作成されますが、マークアップがはるかに多くなり、エラーの余地がありません。 scope アプローチは通常ほとんどの表に十分です。

+
+ +

アクティブラーニング: scope と headers で遊ぶ

+ +
    +
  1. この最後の演習では、まず items-sold.htmlminimal-table.css のローカルコピーを新しいディレクトリに作成してください。
  2. +
  3. この表をより適切にするために適切な scope 属性を追加してみてください。
  4. +
  5. 最後に、最初のファイルの別のコピーを作成して、今度は、id 属性と headers 属性を使用して表にアクセスしやすくします。
  6. +
+ +
+

: 完成した例と照らし合わせて作業内容を確認できます — items-sold-scope.html(ライブもご覧ください)および items-sold-headers.html(ライブもご覧ください)。

+
+ +

まとめ

+ +

表の HTML について他にも学べることがいくつかありますが、現時点で知っておく必要があることは全てここで説明しました。 この時点で、HTML の表のスタイリングについて学びたいと思うかもしれません — スタイリングされた表を参照してください。

+ +
{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}
+ +
+

このモジュール

+ + +
diff --git a/files/ja/learn/html/tables/basics/index.html b/files/ja/learn/html/tables/basics/index.html new file mode 100644 index 0000000000..ec37b6ad39 --- /dev/null +++ b/files/ja/learn/html/tables/basics/index.html @@ -0,0 +1,569 @@ +--- +title: HTML の表の基本 +slug: Learn/HTML/Tables/Basics +tags: + - Beginner + - CodingScripting + - HTML + - Learn + - basics + - col + - colgroup + - colspan + - header + - row + - rowspan + - セル + - テーブル + - 記事 +translation_of: Learn/HTML/Tables/Basics +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}
+ +

この記事は、 HTML の表を始めるために、行やセルなどとても基本的なところから、見出し、複数列や行のセルの結合、スタイルを適用するためにセルの列をすべてグループ化する方法などを扱います。

+ + + + + + + + + + + + +
前提条件:HTML の基本 (HTML 入門を参照)。
目標:基本的に HTML 表に親しむこと。
+ +

テーブルとは何か

+ +

テーブルとは、行と列からなる構造化されたデータの集合 (表形式データ) です。テーブルを使用すると、さまざまな種類のデータ間のある種の関連性、たとえば人と年齢、1日または1週間、地元のプールの予定時刻などを示す値をすばやく簡単に検索できます。

+ +

A sample table showing names and ages of some people - Chris 38, Dennis 45, Sarah 29, Karen 47.

+ +

A swimming timetable showing a sample data table

+ +

1800 年以降のこの米国国勢調査文書で証明されているように、テーブルは人間社会で非常に一般的に使用されており、長い間使用されてきました。

+ +

A very old parchment document; the data is not easily readable, but it clearly shows a data table being used.

+ +

したがって、HTML の作成者が Web 上で表形式データを構造化して表示するための手段を提供したことは不思議ではありません。

+ +

テーブルはどのように動作するか

+ +

テーブルの特徴は、厳密だということです。 情報は、行と列ヘッダーを視覚的に関連付けることによって簡単に解釈されます。例えば下の表を見て、62個の衛星を持つ巨大ガス惑星である木星を見つけてください。関係する行と列との見出し部分を組み合わせて考えることで答えを見つけることができます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
太陽系の惑星のデータ (惑星の事実は「Nasa の惑星情報シート - メートル法」から引用)
名前質量 (1024kg)直径 (km)密度 (kg/m3)重力 (m/s2)一日の長さ (hours)太陽からの距離 (106km)平均気温 (°C)月の数備考
地球型惑星水星0.3304,87954273.74222.657.91670太陽に一番近い
金星4.8712,10452438.92802.0108.24640
地球5.9712,75655149.824.0149.6151私たちの世界
火星0.6426,79239333.724.7227.9-652赤い惑星
木星型惑星巨大ガス惑星木星1898142,984132623.19.9778.6-11067最大の惑星
土星568120,5366879.010.71433.5-14062
巨大氷惑星天王星86.851,11812718.717.22872.5-19527
海王星10249,528163811.016.14495.1-20014
矮星冥王星0.01462,37020950.7153.35906.4-22552006年に惑星として分類されなくなりましたが、これは物議を醸しています
+ +

正しく行われれば、盲目の人でも HTML テーブルの表形式データを解釈できます。HTML テーブルが成功すれば、晴眼者でも視覚障害者でも同様にユーザエクスペリエンスが向上するはずです。

+ +

表のスタイル付け

+ +

GitHub のライブサンプルもご覧ください。テーブルがもう少し読みやすくなっているということに気付くでしょう。これは、今までこのページで見てきたテーブルには最小限のスタイルしか施されていないからです。対して、GitHub バージョンではより特別な意味を持った CSS が適用されています。

+ +

幻想にふけってはいけません。テーブルを Web 上で有効にするには、CSS でスタイル情報を提供し、HTML でしっかりとした構造を提供する必要があります。このモジュールでは、HTML 部分に焦点を合わせています。CSS の部分については、ここを終えた後に表のスタイリングの記事を参照してください。

+ +

このモジュールでは CSS に焦点を当てませんが、スタイルを設定しなくてもデフォルトのテーブルより読みやすくなるように、最小限の CSS スタイルシートを使用できます。スタイルシートはここで、そしてスタイルシートを適用する HTML テンプレートも見つけることができます。これらを一緒にすると、HTML テーブルを試すための良い出発点になります。

+ +

HTML の表を使用するべきではない場面

+ +

HTML テーブルは表形式のデータに使用する必要があります - これがそれらが設計されているものです。残念ながら、HTML テーブルを使用して Web ページをレイアウトする人が多くいました。ヘッダーを含む1行、コンテンツ列を含む1行、フッターを含む1行などです。アクセシビリティ学習モジュールページレイアウトでより多くの詳細と例を見つけることができます。これは一般的に使用されていました。ブラウザ間での CSS サポートがひどいものだったからです。テーブルレイアウトは、現在ではあまり一般的ではありませんが、Web の一部の場所ではまだ見られることがあります。

+ +

つまり、CSS レイアウト手法ではなく、テーブルをレイアウトに使用するのは得策ではありません。主な理由は次のとおりです。

+ +
    +
  1. レイアウトテーブルは視覚障害のあるユーザのアクセシビリティを低下させます。視覚障害者が使用するスクリーンリーダーは、HTML ページに存在するタグを解釈し、その内容をユーザに読み上げます。テーブルはレイアウトに適したツールではなく、マークアップは CSS のレイアウト手法よりも複雑であるため、スクリーンリーダーの出力はユーザにとってわかりにくいものになります。
  2. +
  3. テーブルはタグスープを生成します。前述のように、テーブルレイアウトは通常、適切なレイアウト手法よりも複雑なマークアップ構造を含みます。これにより、コードの記述、保守、およびデバッグが困難になる可能性があります。
  4. +
  5. テーブルは自動的には応答しません。適切なレイアウトコンテナ ({{htmlelement("header")}}、{{htmlelement("section")}}、{{htmlelement("article")}}、{{htmlelement("div")}}など) を使用する場合、その幅はデフォルトで親要素の100%になります。一方、テーブルはデフォルトでは内容に応じてサイズが設定されているため、さまざまなデバイスで効果的に機能するようにテーブルレイアウトのスタイルを変更するには、追加の対策が必要です。
  6. +
+ +

アクティブラーニング: 最初の表の作成

+ +

テーブル理論については十分に説明したので、実用的な例に飛び込み、簡単なテーブルを作成しましょう。

+ +
    +
  1. まず最初に、ローカルマシンの新しいディレクトリに、blank-template.htmlminimal-table.css のローカルコピーを作成します。
  2. +
  3. すべてのテーブルの内容は、<table></table> という2つのタグで囲まれています。HTML のボディの中にこれらを追加してください。
  4. +
  5. テーブル内の最小のコンテナは、<td> 要素によって作成されるテーブルセルです ('td' は 'table data' を表します)。テーブルタグ内に次のコードを追加します。 +
    <td>Hi, I'm your first cell.</td>
    +
  6. +
  7. 4行のセルが必要な場合は、これらのタグを3回コピーする必要があります。テーブルの内容を次のように更新します。 +
    <td>Hi, I'm your first cell.</td>
    +<td>I'm your second cell.</td>
    +<td>I'm your third cell.</td>
    +<td>I'm your fourth cell.</td>
    +
  8. +
+ +

お分かりのように、セルは互いの下に配置されているのではなく、同じ行に配置されています。 各 <td> 要素は単一のセルを作成し、それらが一緒になって最初の行を構成します。 追加するセルごとに行が長くなります。

+ +

この行が大きくなるのを防ぎ、後続のセルを2行目に配置するには、<tr> 要素を使用する必要があります ('tr' は 'table row' を表します)。今これを調査しましょう。

+ +
    +
  1. 以下のように、既に作成した4つのセルを <tr> タグ内に配置します。 + +
    <tr>
    +  <td>Hi, I'm your first cell.</td>
    +  <td>I'm your second cell.</td>
    +  <td>I'm your third cell.</td>
    +  <td>I'm your fourth cell.</td>
    +</tr>
    +
  2. +
  3. 1行作成したら、あと1、2行作成してみましょう。各行は追加の <tr> 要素で囲み、各セルを <td> に含める必要があります。
  4. +
+ +

これにより、テーブルは次のようになります。

+ + + + + + + + + + + + + + + + +
Hi, I'm your first cell.I'm your second cell.I'm your third cell.I'm your fourth cell.
Second row, first cell.Cell 2.Cell 3.Cell 4.
+ +
+

メモ: GitHub では simple-table.html としても見つけることができます (こちらも参照してください)。

+
+ +

<th> 要素による見出しの追加

+ +

それでは表の見出し、つまり行または列の先頭に配置され、その行または列に含まれるデータの種類を定義する特別なセルに注目しましょう(例として、この記事の最初の例の「Person」セルと「Age」セルを参照してください)。それらがなぜ有用であるかを説明するために、次の表の例を見てください。まずはソースコードから:

+ +
<table>
+  <tr>
+    <td>&nbsp;</td>
+    <td>Knocky</td>
+    <td>Flor</td>
+    <td>Ella</td>
+    <td>Juan</td>
+  </tr>
+  <tr>
+    <td>Breed</td>
+    <td>Jack Russell</td>
+    <td>Poodle</td>
+    <td>Streetdog</td>
+    <td>Cocker Spaniel</td>
+  </tr>
+  <tr>
+    <td>Age</td>
+    <td>16</td>
+    <td>9</td>
+    <td>10</td>
+    <td>5</td>
+  </tr>
+  <tr>
+    <td>Owner</td>
+    <td>Mother-in-law</td>
+    <td>Me</td>
+    <td>Me</td>
+    <td>Sister-in-law</td>
+  </tr>
+  <tr>
+    <td>Eating Habits</td>
+    <td>Eats everyone's leftovers</td>
+    <td>Nibbles at food</td>
+    <td>Hearty eater</td>
+    <td>Will eat till he explodes</td>
+  </tr>
+</table>
+ +

実際にレンダリングされたテーブルは次のとおりです。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KnockyFlorEllaJuan
BreedJack RussellPoodleStreetdogCocker Spaniel
Age169105
OwnerMother-in-lawMeMeSister-in-law
Eating HabitsEats everyone's leftoversNibbles at foodHearty eaterWill eat till he explodes
+ +

ここで問題は、何が起こっているかを知ることはできますが、データを相互参照することができるほど簡単ではないことです。列と行の見出しが何らかの形で目立つ場合は、その方がはるかに良いでしょう。

+ +

アクティブラーニング: 表の見出し

+ +

このテーブルを改良してみましょう。

+ +
    +
  1. まず、あなたのローカルマシンの新しいディレクトリに dogs-table.htmlminimal-table.css ファイルのローカルコピーを作ります。HTML には、上で見たのと同じ Dogs の例が含まれています。
  2. +
  3. テーブルのヘッダを視覚的にも意味的にもヘッダとして認識させるには、<th> 要素を使用します ('th' は 'table header' を表します)。これは <td> とまったく同じように機能しますが、通常のセルではなくヘッダーを表す点が異なります。HTML を開き、テーブルのヘッダを囲む全ての <td> 要素を <th> 要素に変更してください。
  4. +
  5. HTML を保存してブラウザにロードすると、ヘッダーがヘッダーらしく見えます。
  6. +
+ +
+

メモ: 完成した例は GitHub の dogs-table-fixed.html にあります (こちらもご覧ください)。

+
+ +

なぜ見出しは便利なのか

+ +

私たちはすでにこの質問に部分的に答えました — ヘッダーがはっきり目立つときには探しているデータを見つけやすく、デザインは一般的に見栄えがよくなります。

+ +
+

メモ: テーブルの見出しにはデフォルトのスタイルがいくつかあります。テーブルに独自のスタイルを追加しなくても、目立つように太字で中央に配置されています。

+
+ +

テーブルヘッダには、scope 属性 (次の記事で学ぶことになります) とともに、追加の利点もあります。それらを使用すると、各ヘッダーを同じ行または列のすべてのデータに関連付けることで、テーブルをよりアクセスしやすくすることができます。これにより、スクリーンリーダーはデータの行全体または列全体を一度に読み取ることができます。これは非常に便利です。

+ +

セルを複数の行や列で結合できるようにする

+ +

セルを複数の行または列にまたがるようにしたい場合があるかもしれません。次の簡単な例を見てください。これは一般的な動物の名前を示しています。場合によっては、動物の名前の横にオスとメスの名前を表示したいことがあります。そうでない場合もあるでしょう。そのような場合は、動物の名前を表全体に広げたいだけです。

+ +

最初のマークアップは次のようになります。

+ +
<table>
+  <tr>
+    <th>Animals</th>
+  </tr>
+  <tr>
+    <th>Hippopotamus</th>
+  </tr>
+  <tr>
+    <th>Horse</th>
+    <td>Mare</td>
+  </tr>
+  <tr>
+    <td>Stallion</td>
+  </tr>
+  <tr>
+    <th>Crocodile</th>
+  </tr>
+  <tr>
+    <th>Chicken</th>
+    <td>Hen</td>
+  </tr>
+  <tr>
+    <td>Rooster</td>
+  </tr>
+</table>
+ +

しかし、出力結果は私たちが望むものではありません。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Animals
Hippopotamus
HorseMare
Stallion
Crocodile
ChickenHen
Rooster
+ +

"Animals"、"Hippopotamus"、および "Crocodile" を2列にまたがって作成し、"Horse" と "Chicken" を2列にまたがって作成する方法が必要です。幸いなことに、テーブルのヘッダーとセルには colspan 属性と rowspan 属性があり、それを使って実行できます。どちらも単位なしの数値を受け入れます。これはスパンする行数または列数と同じです。たとえば、colspan="2" を指定すると、セルは2列にまたがります。

+ +

このテーブルを改善するために colspanrowspan を使用しましょう。

+ +
    +
  1. まず、ご使用のローカルマシンの新しいディレクトリに、animals-table.html ファイルと minimal-table.css ファイルのローカルコピーを作成します。HTML には、上記と同じ動物の例が含まれています。
  2. +
  3. 次に、colspan を使用して "Animals"、"Hippopotamus"、および "Crocodile" を2列にまたがって作成します。
  4. +
  5. 最後に、rowspan を使用して "Horse" と "Chicken" を2行にまたがるようにします。
  6. +
  7. 改善を確認するには、ブラウザでコードを保存して開きます。
  8. +
+ +
+

メモ: 完成した例は GitHub の animals-table-fixed.html にあります (こちらもご覧ください)。

+
+ +

列への共通のスタイル付け

+ +

先に進む前に、この記事で最後に紹介する機能があります。
+ HTML では、データの列全体のスタイル情報を1か所にまとめて定義することができます
<col> 要素と <colgroup> 要素です。列にスタイルを指定するのは少々面倒で非効率的な場合があるためです。列内の <td> <th> ごとにスタイル情報を指定するか、{{cssxref(":nth-child()")}} などの複雑なセレクタを使用する必要があります。

+ +

次の簡単な例を見てください。

+ +
<table>
+  <tr>
+    <th>Data 1</th>
+    <th style="background-color: yellow">Data 2</th>
+  </tr>
+  <tr>
+    <td>Calcutta</td>
+    <td style="background-color: yellow">Orange</td>
+  </tr>
+  <tr>
+    <td>Robots</td>
+    <td style="background-color: yellow">Jazz</td>
+  </tr>
+</table>
+ +

これにより、次のような出力結果が得られます。

+ + + + + + + + + + + + + + + + +
Data 1Data 2
CalcuttaOrange
RobotsJazz
+ +

列内の3つすべてのセルにわたってスタイル情報を繰り返す必要があるため、これは理想的ではありません (実際のプロジェクトでは3つすべてに class を設定し、別のスタイルシートでスタイルを指定することになります)。これを行う代わりに、<col> 要素で情報を1回指定できます。<col> 要素は、開始 <table> タグのすぐ下の <colgroup> コンテナ内で指定されます。次のようにテーブルを指定することで、上と同じ効果を生み出すことができます。

+ +
<table>
+  <colgroup>
+    <col>
+    <col style="background-color: yellow">
+  </colgroup>
+  <tr>
+    <th>Data 1</th>
+    <th>Data 2</th>
+  </tr>
+  <tr>
+    <td>Calcutta</td>
+    <td>Orange</td>
+  </tr>
+  <tr>
+    <td>Robots</td>
+    <td>Jazz</td>
+  </tr>
+</table>
+ +

事実上、2つの "スタイル列" を定義しています。1つは各列のスタイル情報を指定しています。最初の列にはスタイルを設定していませんが、空白の <col> 要素を含める必要があります。そうでない場合、スタイルは最初の列にも適用されます。

+ +

両方の列にスタイル情報を適用する場合は、次のように span 属性を持つ1つの <col> 要素を含めるだけで済みます。

+ +
<colgroup>
+  <col style="background-color: yellow" span="2">
+</colgroup>
+ +

colspanrowspan と同じように、span はスタイルを適用したい列の数を指定する単位なしの数値を取ります。

+ +

アクティブラーニング: colgroup と col

+ +

今こそ自分でやってみるべき時です。

+ +

以下に言語教師のタイムテーブルを見ることができます。金曜日に、彼女は一日中オランダ語を教える新しいクラスを持っていますが、彼女はまた火曜日と木曜日に数期間ドイツ語を教えています。彼女は教えている日を含むコラムをハイライトしたいと思います。

+ +

{{EmbedGHLiveSample("learning-area/html/tables/basic/timetable-fixed.html", '100%', 320)}}

+ +

以下の手順に従ってテーブルを再作成してください。

+ +
    +
  1. まず、timetable.html ファイルのローカルコピーをあなたのローカルマシンの新しいディレクトリに作成してください。HTML には、上で見たのと同じ表から、列のスタイル情報を除いたものが含まれています。
  2. +
  3. <col> 要素を追加することができる <table> タグのすぐ下のテーブルの上部に <colgroup> 要素を追加します (以下の残りの手順を参照)。
  4. +
  5. 最初の2つの列はスタイルなしのままにする必要があります。
  6. +
  7. 3列目に背景色を追加します。style 属性の値はbackground-color:#97DB9A; です。
  8. +
  9. 4列目に別の幅を設定します。style 属性の値は width: 42px; です。
  10. +
  11. 5列目に背景色を追加します。style 属性の値は background-color: #97DB9A; です。
  12. +
  13. これは特別な日であり、彼女は新しいクラスを教えていることを示すために、6番目の列に異なる背景色と境界線を追加します。style 属性の値は background-color:#DCC48E; border:4px solid #C1437A; です。
  14. +
  15. The last two days are free days, so just set them to no background color but a set width; the value for the style attribute is width: 42px;
    + 最後の2日間は空き日なので、背景色を設定せずに幅を設定します。style 属性の値は width: 42px; です。
  16. +
+ +

例でどのようにして上手くいくかを見てください。どうしていいか分からなくなったり、作業をチェックしたい場合は、timetable-fixed.html として GitHub に私たちのバージョンを見つけることができます (それもライブを見てください)。

+ +

まとめ

+ +

HTML テーブルの基本はこれで終わりです。次の記事では、もう少し高度なテーブルの機能を見て、視覚障害者にとってそれらがどれほどアクセシブルであるかを考えます。

+ +

{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}

+ +
+

このモジュール

+ + +
diff --git a/files/ja/learn/html/tables/index.html b/files/ja/learn/html/tables/index.html new file mode 100644 index 0000000000..7f1a8c7fd2 --- /dev/null +++ b/files/ja/learn/html/tables/index.html @@ -0,0 +1,43 @@ +--- +title: HTML テーブル +slug: Learn/HTML/Tables +tags: + - Article + - Beginner + - CodingScripting + - Guide + - HTML + - Landing + - Module + - Tables +translation_of: Learn/HTML/Tables +--- +
{{LearnSidebar}}
+ +

HTML でのとてもよくある仕事はテーブルデータの構造化で、数々の要素と属性がこの目的のためにあります。スタイリング用の CSS と組み合わせて、HTML は Web 上に、学校の授業の計画や、水泳の時間割や、好きな恐竜やフットボールチームの統計情報といった、情報のテーブルを簡単に表示できます。このモジュールではHTMLを使ってテーブルデータを構造化するのに必要な知識を一通り案内します。

+ +

必要となる知識

+ +

このモジュールを学習する前に、HTMLの基本について既に理解している必要があります。もしまだ理解が足りていないと感じているならば HTML 入門を参照してください。

+ +
+

: もしあなたが自分のファイルを作成することのできないコンピュータ・タブレット端末そのほかのデバイスで作業をしているならば、 インターネット上の JSBinThimbleといったコーディングプログラムを用いてほとんどのコードの例を試してみることができます。

+
+ +

ガイド

+ +

このモジュールは以下の話題を含んでいます。:

+ +
+
HTML テーブルの基本
+
この記事を読めば、HTMLのテーブルについてのイロハを知ることができます。行や列、見出しやカラムと行を複数に分割するセルの作成を扱い、またいかにしてカラムにあるセルをまとめて見栄えを整えるかについて扱います。
+
HTML テーブルの高度な機能とアクセシビリティ
+
このモジュールの2つ目の記事では、 HTMLのもう少し発展的な機能について扱います。 たとえば、見出しや要約、そして行をまとめて表のhead,bodyそしてフッターのsectionにすることです。同時に視覚にハンディキャップを有する人びとのために表のアクセシビリティについても記事で扱います。
+
+ +

評価

+ +
+
惑星データの構造化
+
テーブルについての記事を理解できたかの評価として、太陽系の星についてのいくつかのデータを提供し、あなたにHTMLを用いて表にしてもらいます。
+
diff --git a/files/ja/learn/html/tables/structuring_planet_data/index.html b/files/ja/learn/html/tables/structuring_planet_data/index.html new file mode 100644 index 0000000000..625a34c151 --- /dev/null +++ b/files/ja/learn/html/tables/structuring_planet_data/index.html @@ -0,0 +1,87 @@ +--- +title: '評価: 太陽系の惑星のデータを構造化する' +slug: Learn/HTML/Tables/Structuring_planet_data +tags: + - Assessment + - Beginner + - CodingScripting + - HTML + - Learn + - テーブル +translation_of: Learn/HTML/Tables/Structuring_planet_data +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}
+ +

テーブルの評価では、太陽系の惑星に関するいくつかのデータを提供し、それを HTML テーブルに構造化しましょう。

+ + + + + + + + + + + + +
前提知識:この評価を行う前に、このモジュールのすべての記事について学んでいるべきです。
目標:HTML の表やそれに付随する機能に関する理解を確認する。
+ +

はじめに

+ +

この評価を開始するには、ローカルコンピュータの新しいディレクトリに、blank-template.htmlminimal-table.css、および planets-data.txt のローカルコピーを作成します。

+ +
+

メモ: 代わりとして、JSBinThimble のようなサイトを使って評価することもできます。HTML、CSS、および JavaScript をこれらのオンラインエディタのいずれかに貼り付けることができます。使用しているオンラインエディタに個別の JavaScript/CSS パネルがない場合は、それらを HTML ページ内に <script>/<style> 要素をインラインで配置してください。

+
+ +

やることの概要

+ +

あなたは学校で働いています。現在生徒たちは私たちの太陽系の惑星を研究しています、そしてあなたは彼らに惑星についての事実と数字を調べるために分かりやすいデータのセットを提供したいです。HTML データテーブルが理想的です — 利用可能な生データを取得し、それをテーブルに変換する必要があります。以下の手順に従ってください。

+ +

完成した表は次のような外観を備えているはずです:

+ +

+ +

また、ここに掲載されている例を見ることもできます (ソースコードを見ないでください — チートしないでください)。

+ + + +

手順

+ +

次の手順では、表の例を完成させるために必要な作業について説明します。必要なすべてのデータは planets-data.txt ファイルに含まれています。データをうまく視覚化できない場合は、上記の実際の例を見てみるか、図を描いてみてください。

+ +
    +
  1. blank-template.html のコピーを開き、外部コンテナ、テーブルヘッダー、およびテーブル本体を指定してテーブルを作成します。この例ではテーブルフッターは必要ありません。
  2. +
  3. 提供されたキャプションを自分のテーブルに追加します。
  4. +
  5. すべての列ヘッダーを含む行をテーブルヘッダーに追加します。
  6. +
  7. すべての行見出しを意味的に見出しにすることを忘れずに、テーブル本体内にすべてのコンテンツ行を作成します。
  8. +
  9. すべてのコンテンツが正しいセルに挿入されていることを確認してください — 生データでは、惑星データの各行が関連する惑星の隣に表示されます。
  10. +
  11. 行ヘッダーと列ヘッダーを、それらが見出しとして機能する行、列、または行グループと明確に関連付けられるように属性を追加します。
  12. +
  13. すべての惑星名行ヘッダーを含む列のすぐ周りに黒い枠線を追加します。
  14. +
+ +

ヒントとTIPS

+ + + +

評価

+ +

あなたが組織的コースの一環としてこの評価に従っている場合、採点のために作品を教師/メンターに渡すことができるはずです。もし自己学習しているのであれば、この練習問題についてのディスカッションスレッド、または Mozilla IRC#mdn IRC チャンネルで尋ねることで、非常に簡単にマーキングガイドを入手することができます。最初にエクササイズをしてみてください。不正をすることによって得られるものは何もありません!

+ +

{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/index.html b/files/ja/learn/index.html new file mode 100644 index 0000000000..2a218b21c6 --- /dev/null +++ b/files/ja/learn/index.html @@ -0,0 +1,131 @@ +--- +title: ウェブ開発を学ぶ +slug: Learn +tags: + - Intro + - Landing + - ウェブ + - 初心者 + - 学習 + - 索引 +translation_of: Learn +--- +

{{LearnSidebar}}

+ +

MDN 学習エリアへようこそ。この一連の記事では、ウェブ開発が全くの初心者にとって、シンプルなウェブサイトのコーディングを始めるのに必要な全てを提供することを目標とします。

+ +

MDN のこのエリアでは、あなたを「初心者」から「上級者」までのスキルアップでなく、「初心者」から「中級程度」までの支援となります。ウェブ開発において自分なりの方法を確立するためには、さらに、MDN のこのエリア以外の記事と、中・上級者用のウェブサイトを読み進めてください。その前提知識を身に付ける為に本、学習エリアがあります。

+ +

全くの初心者であれば、ウェブ開発は難しいものです - 私たちはあなたの手を握り、あなたが快適に感じ、適切にトピックを学ぶために十分な詳細を提供します。あなたがウェブ開発を学習している学生 (個人またはクラスの一部として)、クラスの教材を探している先生、趣味の人、ウェブ技術の仕組みをもっと理解したい人など、どのような人であっても、安心してください。

+ +

何が新しくなった?

+ +

学習エリアのコンテンツは定期的に追加されています。学習エリアのリリースノートには、何が変更されたかを記載しています。

+ +

カバーしてほしいトピックや不足していると感じたトピックについて質問がある場合は、Discourse フォーラムにメッセージを送ってください。

+ +
+

フロントエンドの Web 開発者になりたいですか?

+ +

目標に向かって頑張るために必要な情報をまとめたコースをご用意しました。

+ +

開始する

+
+ +

読み始める場所

+ + + +
+

メモ: 用語集にて、単語の定義が提供されています。

+
+ +

{{LearnBox({"title":"Random glossary entry"})}}

+ +

カバーするトピック

+ +

下記は MDN 学習エリアにてカバーしているすべてのトピック一覧です。

+ +
+
ウェブ入門
+
完全なウェブ開発初心者用の実用的な入門を提供します。
+
HTML — ウェブの構造化
+
HTML はコンテンツのいろいろな部分を構造化し、意味や目的を定義するのに使う言語です。このトピックでは HTML を詳細に教えます。
+
CSS — ウェブのスタイルづけ
+
CSS はウェブのコンテンツをスタイルづけしたりレイアウトしたり、アニメーションのような振る舞いを追加したりする言語です。このトピックでは CSS を包括的にカバーします。
+
JavaScript — 動的クライアントサイドスクリプティング
+
JavaScript はウェブページに動的な機能を追加するスクリプト言語です。このトピックでは JavaScript を書いたり理解するのに十分となるのに必要なすべての要点を教えます。
+
アクセシビリティ — ウェブをすべての人が利用できるようにする
+
アクセシビリティはウェブコンテンツをなるべく多くの人に利用できるようにする実践であり、それは障がいや、端末や、ロケールや、その他の分化させる要素に関係なく利用できるようにします。このトピックでは知る必要のあるすべてが与えられます。
+
ウェブの性能 — ウェブサイトを高速かつレスポンシブにする
+
ウェブの性能は、ウェブアプリケーションのダウンロードを確実に高速化し、ダウンロードを帯域幅、画面の寸法、ネットワーク、端末の能力にかかわらず、ユーザーの操作をレスポンシブにする技術です。
+
ツールとテスト
+
このトピックは開発者が作業をやり易くするツール、例えばクロスブラウザーテストツールなどについてカバーします。
+
サーバサイドのウェブサイトプログラミング
+
クライアントサイドのウェブ開発に集中していても、サーバとサーバサイドのコードがどう動くのかを知るのは有益です。このトピックではサーバサイドの動作の一般的な入門と、2 つの有名フレームワーク — Django (Python) and Express (node.js) を使ってサーバサイドアプリを作る方法の詳しいチュートリアルを提供します。
+
+ +

コードサンプルを入手する

+ +

学習エリアにあるコードの例はすべて GitHub で利用可能です。それらすべてをあなたのコンピュータにコピーしたいのなら、最も簡単な方法は最新の master コードブランチのZIPをダウンロードすることです。

+ +

自動更新を可能にするより柔軟な方法でリポジトリをコピーしたい場合は、より複雑な指示に従うことになります。

+ +
    +
  1. あなたのマシンに Git をインストールします。これは GitHub が動作している、その下にあるバージョン管理システムのソフトウェアです。
  2. +
  3. GitHub にサインアップします
  4. +
  5. サインアップが済んだら、ユーザー名/パスワードで github.com にログインします。
  6. +
  7. あなたのコンピューターでコマンドプロンプト (Windows) かターミナル (Linux, macOS) を開きます。
  8. +
  9.  learning area のリポジトリを、あなたのコマンドプロンプト/ターミナルの現在位置の learning-area と呼ぶフォルダーにコピーするには、下記のコマンドを使います。 +
    git clone https://github.com/mdn/learning-area
    +
  10. +
  11. そのディレクトリに入って、ファイルが (finder/エクスプローラーや、cd コマンドのいずれか) の後に見つかるでしょう。
  12. +
+ +

learning-area リポジトリを、GitHub の master バージョンになされたあらゆる変更で更新するには、以下の手順でできます。

+ +
    +
  1. コマンドプロンプト/ターミナルで、cd を使って learning-area ディレクトリの中に移動します。例えば、上位のディレクトリにいる場合は以下のようにします。 + +
    cd learning-area
    +
  2. +
  3. 下記のコマンドでリポジトリを更新します。 +
    git pull
    +
  4. +
+ +

連絡方法

+ +

何か連絡を取りたいことがある場合、learning area discourse スレッドIRC チャンネル でメッセージを投稿するのがもっともよい方法です。サイトの間違いや新しい学習トピックスの要望、理解できない項目についてのヘルプ要請などなんでも歓迎です。

+ +

コンテンツの開発、改善の手助けに興味がある場合、協力するには?を覗いて、始めてください!あなたが初心者でも、先生でも、熟練のウェブ開発者でも、その他学習体験の改善に興味がある人でも、誰でも歓迎です。

+ +

関連情報

+ +
+
Mozilla developer newsletter
+
我々のウェブ開発者向けニュースレターで、あらゆる経験レベル向けのすばらしいリソースです。
+
Web demystified
+
ウェブの基礎を説明するすばらしい動画シリーズで、ウェブ開発の完全な初心者に向けたもの。製作者は Jérémie Patonnier
+
Codecademy
+
最初からプログラミング言語を学ぶためのすばらしいインタラクティブサイト
+
BitDegree
+
ゲーミフィケーションされた学習プロセスによる基本的なコーディング理論です。主に初心者向けです。
+
Code.org
+
基本的なコーディング理論と実践で、主に子供や完全な初心者を目的としたもの。
+
EXLskills 
+
技術スキルを学ぶための、メンターシップやプロジェクトベースの学習があるフリーでオープンなコースです。
+
freeCodeCamp.org
+
ウェブ開発を学習するチュートリアルやプロジェクトのあるインタラクティブなサイト。
+
Web literacy map
+
エントリーレベルのウェブリテラシーや 21世紀のスキル向けのフレームワークで、カテゴリーごとにソートされた教科にもアクセスできます。
+
Teaching activities
+
Mozilla Foundation によって作成された教える(と学ぶ)ための教科シリーズで、ウェブリテラシーやプライバシーなどの基本から、JavaScript や Minecraft のハックまで、すべてカバーしています。
+
Edabit
+
数千のインタラクティブなJavaScriptチャレンジ。
+
diff --git a/files/ja/learn/index/index.html b/files/ja/learn/index/index.html new file mode 100644 index 0000000000..0c842ca444 --- /dev/null +++ b/files/ja/learn/index/index.html @@ -0,0 +1,10 @@ +--- +title: インデックス +slug: Learn/Index +tags: + - MDN Meta + - インデックス + - 学習 +translation_of: Learn/Index +--- +

{{Index("/ja/docs/Learn")}}

diff --git a/files/ja/learn/javascript/asynchronous/concepts/index.html b/files/ja/learn/javascript/asynchronous/concepts/index.html new file mode 100644 index 0000000000..b2baeaac4e --- /dev/null +++ b/files/ja/learn/javascript/asynchronous/concepts/index.html @@ -0,0 +1,162 @@ +--- +title: 非同期プログラミングの一般的概念 +slug: Learn/JavaScript/Asynchronous/Concepts +tags: + - JavaScript + - Learn + - Promises + - Threads + - asynchronous + - blocking +translation_of: Learn/JavaScript/Asynchronous/Concepts +--- +
{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
+ +

この記事では、非同期プログラミングに関するいくつかの重要な概念と、その概念がウェブブラウザーと JavaScript でどのように見えるのかをひと通り説明していきます。このモジュールの他の記事に取り組む前に、これらの概念を理解しておく必要があります。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーがあり、ある程度 JavaScript の基礎を理解していること
目的:非同期プログラミングの基本概念と、その概念がウェブブラウザーと JavaScript でどのように表現されるかを理解すること
+ +

非同期とは?

+ +

通常は、あるプログラムのコードは書かれた順に、一度にひとつのことだけが起こるように実行されます。もしある関数が別の関数の結果に依存するのであれば、その関数は他の関数の処理が完了して結果を返すまで待たなくてはならず、それまでは、ユーザー視点からはプログラム全体は止まっているのと本質的には同じです。

+ +

例えば、Mac ユーザーは回転する虹色のカーソル(よく「ビーチボール」と呼ばれます)としてこのことを経験することもあるでしょう。このカーソルによってオペレーティングシステムは「現在使用中のプログラムは何かが終わるのを待って停止しており、それが非常に長く掛かっているので何が起こっているのかとご心配をお掛けしているのではないでしょうか」と言っているのです。

+ +

Multi-colored macOS beachball busy spinner

+ +

これはいら立つような体験であり、コンピューターの処理能力の良い使い方ではありません――特に、マルチコアプロセッサーが利用できる時代においては。他のタスクを別のプロセッサーコアに処理させて、それが終わった時に知らせることができるのに、座って待っているのは意味がありません。このように合間に別の仕事を終わらせる、ということが非同期プログラミングの基本です。非同期にタスクを実行する API は、あなたが使用するプログラミング環境(ウェブ開発であればウェブブラウザー)によって提供されます。

+ +

ブロッキングコード

+ +

非同期のテクニックは、特にウェブプログラミングにおいて非常に有用です。ウェブアプリがブラウザー上で高負荷なコードを実行すると、ブラウザーは固まって見えるかもしれません。これをブロッキングといいます。ウェブアプリがプロセッサーの制御を返すまで、ブラウザーはユーザーからの入力を処理して他のタスクを実行し続けるのを妨げられているのです。

+ +

ブロッキングが意味するところを示す例をいくつか見てみましょう。

+ +

この simple-sync.html の例(デモ参照)では、ボタンをクリックすると時間の掛かる処理(日時を 1000 万回計算し、最後に計算された日時をコンソールに出力)を実行し、DOM に段落を 1 つ追加します。

+ +
const btn = document.querySelector('button');
+btn.addEventListener('click', () => {
+  let myDate;
+  for(let i = 0; i < 10000000; i++) {
+    let date = new Date();
+    myDate = date
+  }
+
+  console.log(myDate);
+
+  let pElem = document.createElement('p');
+  pElem.textContent = 'This is a newly-added paragraph.';
+  document.body.appendChild(pElem);
+});
+ +

この例を実行する際は、JavaScript コンソールを開き、その後にボタンをクリックしてください ― 日時の計算が終わり、コンソールにメッセージが出力されるまで段落が現れないことに気が付くでしょう。コードは順番に実行され、前の処理が終わるまで後の処理は実行されません。

+ +
+

: 先ほどの例はまったく非現実的です。現実のウェブアプリでは日時を 1000 万回計算することはないでしょう! しかしながら、基本的な考え方の理解には役立ちます。

+
+ +

2 つ目の例の simple-sync-ui-blocking.html では(デモ参照)、実際のページでも遭遇しうる、もう少し現実的な例をシミュレーションします。ユーザーインターフェイスのレンダリングによってユーザーの操作がブロックされるのです。この例では、ボタンは 2 つあります。

+ + + +
function expensiveOperation() {
+  for(let i = 0; i < 1000000; i++) {
+    ctx.fillStyle = 'rgba(0,0,255, 0.2)';
+    ctx.beginPath();
+    ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false);
+    ctx.fill()
+  }
+}
+
+fillBtn.addEventListener('click', expensiveOperation);
+
+alertBtn.addEventListener('click', () =>
+  alert('You clicked me!')
+);
+ +

もし1つ目のボタンを押し、その後素早く2つ目のボタンを押すと、円の描画が終わるまでアラートが表示されないことが分かるでしょう。1つ目の処理が完了するまで 2つ目の処理がブロックされています。

+ +
+

: ええ、この事例は見苦しく、ブロッキングの影響を真似ているものです。しかし、これは現実のアプリケーション開発者が軽減させようと常に戦っている、ありふれた問題です。

+
+ +

何故こうなるのでしょうか? その答えは、一般的に言えば JavaScript はシングルスレッドだからです。ここで、スレッドの概念を紹介する必要があります。

+ +

スレッド

+ +

スレッドとは、基本的にプログラムがタスクを完了させるのに使用できる、単一のプロセスです。各スレッドは 1 度に 1 つのタスクを実行することしかできません。

+ +
Task A --> Task B --> Task C
+ +

各タスクは順次実行されます。すなわち、あるタスクが完了しなければ、その次のタスクは開始されません。

+ +

先述のように、現在では多くのコンピューターは複数のコアを持つため、一度に複数のことをすることができます。マルチスレッドをサポートするプログラミング言語は、複数のコアを使用して同時に複数のタスクを完了させることができます。

+ +
Thread 1: Task A --> Task B
+Thread 2: Task C --> Task D
+ +

JavaScript はシングルスレッド

+ +

従来より JavaScript はシングルスレッドです。複数のコアを利用しても、メインスレッドと呼ばれる単一のスレッド上でタスクを実行できるだけでしょう。これまでの例は、次のように実行されます。

+ +
Main thread: Render circles to canvas --> Display alert()
+ +

少し経ってから、JavaScript はこういった問題に役立つ、いくつかのツールを手に入れました。Web workers によって worker と呼ばれる別個のスレッドに JavaScript の処理の一部を移すことが可能となり、そのことで複数の JavaScript のコードを同時に実行することができるようになります。一般的に worker は、ユーザーの操作がブロックされないように、高コストな処理をメインスレッドとは別のところで実行するために使用されます。

+ +
  Main thread: Task A --> Task C
+Worker thread: Expensive task B
+ +

このことを念頭に置いて、再び simple-sync-worker.htmlデモ参照)をブラウザーの JavaScript コンソールを開いた状態で見てみましょう。こちらは先ほどの 1000 万回の日時計算を行う例を別の worker スレッド上で行うよう書き換えたものです。今回はボタンをクリックすると、ブラウザーは日時の計算が完了する前に段落を表示することができます。1 つ目の処理は、もう 2 つ目の処理をブロックしていません。

+ +

非同期なコード

+ +

Web worker はかなり便利ですが、制限もあります。主要なものとして、Web worker は {{Glossary("DOM")}} にアクセスできません —— Worker に直接ユーザーインターフェイスを更新させるようなことはできません。100 万個の青い円を worker 内部で描画させることはできないのです。基本的にはただ計算ができる、ということです。

+ +

2 つ目の問題は、worker によって実行されるコードはブロックしないとは言え、根本的には依然として同期的であるということです。このことは、ある関数が先行する複数の関数の結果に頼っている場合に問題となります。次のスレッドの図について考えてみましょう。

+ +
Main thread: Task A --> Task B
+ +

このような場合、例えばタスク A は画像をサーバーから取得するような処理を、タスク B が次にその画像に対してフィルターを適用するような処理をしていると考えてみましょう。もしタスク A を実行し、その直後にタスク B を実行したとすれば、まだ画像が取得できていないためにエラーが発生するでしょう。

+ +
  Main thread: Task A --> Task B --> |Task D|
+Worker thread: Task C -----------> |      |
+ +

このような場合、例えばタスク D はタスク B と タスク C の両方の結果を利用していると考えてみましょう。もし両方の結果が同時に利用可能になることを保証できるのであれば、これで問題ないでしょうが、そのようなことはまれです。もしタスク D の入力のうち 1 つがまだ利用可能となっていない時にタスク D を実行しようとすれば、エラーが投げられるでしょう。

+ +

このような問題を解決するために、ブラウザーを利用して特定の処理を非同期に実行することができます。Promises のような機能を利用することで、ある処理(例:サーバーからの画像の取得)を実行し、その結果が返ってくるまで別の処理の実行を待たせることができるのです。

+ +
Main thread: Task A                   Task B
+    Promise:      |__async operation__|
+ +

この Promise の処理はどこか別の場所で行われるため、非同期処理が実行されている間にメインスレッドがブロックされることはありません。

+ +

次の記事では、どうすれば非同期処理を書けるのかを見ていきましょう。わくわくしますよね? 読み進めましょう!

+ +

結論

+ +

現代のソフトウェアデザインは、一度に複数のことをプログラムに実行させるために、ますます非同期処理を中心とした議論が行われています。より新しく、より強力な API を利用すればするほど、非同期処理が唯一の解決先であるような事例が見つかっていくでしょう。かつては非同期なコードを書くのは困難なことでした。慣れるにはまだ時間が掛かりますが、以前よりだいぶ楽になりました。このモジュールの残りの部分では、なぜ非同期なコードが重要なのか、そして上で説明した問題を回避するコードをどのようにして設計すればよいのかを掘り下げていきます。

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/asynchronous/index.html b/files/ja/learn/javascript/asynchronous/index.html new file mode 100644 index 0000000000..f3b1c62242 --- /dev/null +++ b/files/ja/learn/javascript/asynchronous/index.html @@ -0,0 +1,51 @@ +--- +title: 非同期 JavaScript +slug: Learn/JavaScript/Asynchronous +tags: + - JavaScript + - Promises + - async + - asynchronous + - await + - setInterval + - setTimeout +translation_of: Learn/JavaScript/Asynchronous +--- +
{{LearnSidebar}}
+ +

このモジュールでは、{{Glossary("asynchronous")}} {{Glossary("JavaScript")}} に触れ、なぜそれが重要なのか、そして、潜在的なブロッキング処理(例えばサーバからリソースを取得する)に効果的に対処するためにどうやって使うのかを見ていきます。

+ +

前提条件

+ +

非同期 JavaScript はとても高度なトピックなので、事前に JavaScript の第一歩JavaScript の構成要素のモジュールに取り組んでおくことをおすすめします。

+ +

非同期プログラミングの概念に慣れていない場合は、間違いなくこのモジュールの General asynchronous programming concepts から始めるべきです。慣れている場合は、Introducing asynchronous JavaScript まで飛ばしていただいてもかまいません。

+ +
+

注記: ファイルを作成する手段のないコンピュータ・タブレット・その他のデバイスをお使いの場合、(ほとんどの)コード例は JSBinThimble などのオンラインエディタでも試すことができます。

+
+ +

ガイド

+ +
+
General asynchronous programming concepts
+
+

この記事では、非同期プログラミングに関するいくつかの重要な概念を一通り確認し、それらがウェブブラウザや JavaScript でどう見えるかを確認します。このモジュールの他の記事に進む前に、それらの概念を理解しておいてください。

+
+
Introducing asynchronous JavaScript
+
この記事では、同期 JavaScript にまつわる問題をざっと振り返り、これから遭遇するであろう、今までとは異なる非同期 JavaScript のテクニックをいくつか見てみます。そして、それらのテクニックがいかにして同期 JavaScript の問題を解決するかを確認します。
+
Cooperative asynchronous JavaScript: Timeouts and intervals
+
ここでは、JavaScriptでコードを非同期〔一定時間が経過した時、もしくは、一定間隔(例えば1秒あたり何回)〕に実行する時に使う伝統的な手法を見てみます。そして、どんな場合に便利なのかを説明し、内在する問題を考察します。
+
Handling async operations gracefully with Promises
+
Promise は JavaScript の比較的新しい機能で、前の処理が完了するまでそれ以上の処理を先延ばしにしたり、その失敗に対処したりすることを可能にするものです。これは、一連の作業を正しく動作させるのに非常に便利です。この記事では、promise がどのように動作するか、WebAPIのどこで使われているか、そして、どうやって使うかを解説します。
+
Making asynchronous programming easier with async and await
+
Promise は構成したり理解したりするのにやや複雑であるため、モダンブラウザは async 関数と await 演算子を実装しています。前者は通常の関数が promise によって暗黙に非同期的に振る舞うことを可能にし、後者は async 関数内で処理が進む前に promise を待つことで、promise の連鎖を簡単にします。この記事では async/await を解説します。
+
Choosing the right approach
+
このモジュールの最後に、別のコーディングテクニックとこれまで議論してきた機能を考察します。そして、推奨事項とよくある落とし穴への注意とともに、どれを・いつ・どこで使うのが適切なのかを検討します。
+
+ +

関連情報

+ + diff --git a/files/ja/learn/javascript/building_blocks/build_your_own_function/index.html b/files/ja/learn/javascript/building_blocks/build_your_own_function/index.html new file mode 100644 index 0000000000..e12ce6f478 --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/build_your_own_function/index.html @@ -0,0 +1,262 @@ +--- +title: 独自の関数を作る +slug: Learn/JavaScript/Building_blocks/Build_your_own_function +tags: + - Article + - Beginner + - CodingScripting + - Functions + - Guide + - JavaScript + - Learn + - Tutorial + - build + - invoke + - 'l10n:priority' + - parameters +translation_of: Learn/JavaScript/Building_blocks/Build_your_own_function +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}
+ +

前の記事で扱った重要な理屈をたくさん使って、この記事では実践的な練習を行ないます。ここではあなたが自力で独自関数を作成するための練習を行なっていきます。同時に、関数を扱う上で役に立つ細々の説明もしていきます。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、HTML と CSS への理解、JavaScript の第一歩 関数 — 再利用可能なコードブロック
目的:独自の関数を作成する練習、役に立つ関連事項についてつっこんだ説明。
+ +

Active learning: 関数を作ってみよう

+ +

これから作ってみる独自の関数を displayMessage()。これは独自のメッセージボックスをウェブページ上に表示し、ブラウザー組込みの alert() 関数の特製の代替品として動作します。既に見たものですが、忘れた事にしましょう。以下をブラウザーの JavaScript コンソールから打ち込みます、どのページでも構いません:

+ +
alert('This is a message');
+ +

alert 関数は引数を一つ取ります — アラートボックスに表示される文字列です。文字列を色々変えてメッセージを変化させてみて下さい。

+ +

alert 関数には制限があります: メッセージを変更することはできますが、色やアイコンなど、それ以外の部分を簡単には変えられません。もっと楽しくできるやつを作りましょう。

+ +
+

注記: この例題は全てのモダンブラウザー上で問題なく動くはずですが、古いブラウザーではちょっとおかしな見た目になるかもしれません。この課題は Firefox、Opera、Chrome のようなモダンなブラウザー上で行なうのが推奨です。

+
+ +

基本的な関数

+ +

最初に、基本的な関数を組み立てていきましょう。

+ +
+

注記: 関数に名前を付ける方針としては、変数名に名前をつける方針と同じルールに従うべきです。問題はありません、すぐに見分けがつくからです — 関数ならすぐ後に括弧が付きますが、変数には付きません。

+
+ +
    +
  1. function-start.html ファイルにアクセスして、ローカルコピーを作成するところから初めます。HTML は単純です — body にはボタン一つしかありません。特製メッセージボックス用の基本的な CSS スタイルと、JavaScript を追加していく用の空の {{htmlelement("script")}} 要素が含まれています。
  2. +
  3. 次に、<script> 要素の中に以下を追加して下さい: +
    function displayMessage() {
    +
    +}
    + キーワード function から始めますが、これは関数を定義するという意味です。この後には、関数につけたい名前、カッ括弧の組、中括弧の組と続きます。関数に渡したい引数は括弧の中に、関数を呼び出したときに走らせたいコードは中括弧の中に書きます。
  4. +
  5. 最後に、以下のコードを中括弧の中に追加します: +
    const html = document.querySelector('html');
    +
    +const panel = document.createElement('div');
    +panel.setAttribute('class', 'msgBox');
    +html.appendChild(panel);
    +
    +const msg = document.createElement('p');
    +msg.textContent = 'This is a message box';
    +panel.appendChild(msg);
    +
    +const closeBtn = document.createElement('button');
    +closeBtn.textContent = 'x';
    +panel.appendChild(closeBtn);
    +
    +closeBtn.onclick = function() {
    +  panel.parentNode.removeChild(panel);
    +}
    +
  6. +
+ +

これは見ていくにはそこそこの量のコードですから、一つ一ついっしょに進んでいく事にしましょう。

+ +

最初の行では {{domxref("document.querySelector()")}} と呼ばれる DOM API 関数を使って {{htmlelement("html")}} 要素を選択し、html という名前の定数に要素への参照を保存したので、これを使っていろいろやっていきます:

+ +
const html = document.querySelector('html');
+ +

次の部分では別の DOM API 関数 {{domxref("document.createElement()")}} を使い、{{htmlelement("div")}} 要素を作成、これへの参照を panel という定数に保存しています。この要素は我々のメッセージボックスの外枠となっていきます。

+ +

次にまた別の DOM API 関数 {{domxref("Element.setAttribute()")}} を使って、我々のパネルの class 属性とその値 msgBox を設定します。これは要素のスタイルを指定しやすくするためです — ページの CSS を見ると、メッセージボックスとその中身に適用するスタイルとして .msgBox クラスセレクターがあるのがわかるでしょう。

+ +

最後に、前に保存した html 変数の DOM 関数 {{domxref("Node.appendChild()")}} を呼んでいますが、この関数は一つの要素を別の要素の子として組み入れる働きをします。panel という<div> 要素を子として、<html> 要素の中に追加したいのです。作成した要素は作成したページにぽんと現われたりはしません — どこに置くのかも指定しなければなりません。なのでこのようにする必要があります。

+ +
const panel = document.createElement('div');
+panel.setAttribute('class', 'msgBox');
+html.appendChild(panel);
+ +

次の 2 つのセクションでは既に見た同じ createElement()appendChild() 関数を使用して、2 つの新しい要素、つまり {{htmlelement("p")}} と {{htmlelement("button")}} を作成し、<div> パネルの子要素としてページに挿入します。段落の中にメッセージを挿入する {{domxref("Node.textContent")}} プロパティ (要素のテキスト内容を表す) とボタンの中に 'x' を使います。このボタンは、ユーザーがメッセージボックスを閉じるときにクリック/アクティブ化する必要があります。

+ +
const msg = document.createElement('p');
+msg.textContent = 'This is a message box';
+panel.appendChild(msg);
+
+const closeBtn = document.createElement('button');
+closeBtn.textContent = 'x';
+panel.appendChild(closeBtn);
+ +

最後に、{{domxref("GlobalEventHandlers.onclick")}} イベントハンドラーを使用して、ボタンをクリックするとパネル全体をパネルから削除してメッセージボックスを閉じるようにします。
+
+ 簡単に説明すると、onclick ハンドラーはボタン (または実際にはページ上の任意の要素) で使用できるプロパティで、ボタンをクリックしたときに実行するコードを指定する関数に設定できます。後のイベントの記事で、これらについてさらに詳しく学びます。onclick ハンドラーは、ボタンがクリックされたときに実行されるコードを含む無名関数と等しくなります。関数内の行は {{domxref("Node.removeChild()")}} DOM API関数を使用して、HTML要素の特定の子要素 (この場合は <div> パネル) を削除することを指定します。

+ +
closeBtn.onclick = function() {
+  panel.parentNode.removeChild(panel);
+}
+ +

基本的には、このコードブロック全体が HTML のブロックを生成してページに挿入しています。

+ +
<div class="msgBox">
+  <p>This is a message box</p>
+  <button>x</button>
+</div>
+ +

作業するコードがたくさんありました。今のところどのように動作しているか正確に覚えていないことをあまり心配しないでください! ここでは、関数の構造と使用法を中心に説明しますが、この例では何か面白いことを示したかったのです。

+ +

関数の呼び出し

+ +

これで、<script> 要素に書かれた関数定義がうまくいきましたが、それは何もしません。

+ +
    +
  1. 関数の下に次の行を含めて呼び出してみてください: +
    displayMessage();
    + この行は関数を呼び出し、すぐに実行させます。コードを保存してブラウザーを再読み込みすると、小さなメッセージボックスがすぐに 1 回だけ表示されます。それを一度呼ぶだけです。
  2. +
  3. +

    サンプルページでブラウザーの開発者ツールを開き、JavaScript コンソールに移動してもう一度その行を入力すると、もう一度表示されます。これは楽しいことです - 私たちは今好きな時に呼び出すことができる再利用可能な関数を持っています。

    + +

    しかし、ユーザーとシステムのアクションに応じて表示されるようにすることをお勧めします。実際のアプリケーションでは、このようなメッセージボックスは、新しいデータが利用可能であること、エラーが発生したこと、ユーザーがプロファイルを削除しようとしている (「これは本当ですか?」)、またはユーザーが 新しい連絡先や操作が正常に終了しました...などが起こったときに呼び出されるでしょう。

    + +

    このデモでは、ユーザーがボタンをクリックするとメッセージボックスが表示されます。

    +
  4. +
  5. 追加した前の行を削除します。
  6. +
  7. 次に、ボタンを選択し、そのボタンへの参照を定数に格納します。関数定義の上のコードに次の行を追加します: +
    const btn = document.querySelector('button');
    +
  8. +
  9. 最後に、前の行の下に次の行を追加します: +
    btn.onclick = displayMessage;
    + 関数内の closeBtn.onclick... 行と同様に、ここではボタンがクリックされたことに応答してコードを呼び出します。しかしこの場合、コードを含む無名関数を呼び出す代わりに、関数名を直接呼び出しています。
  10. +
  11. ページを保存して再表示してみてください。ボタンをクリックするとメッセージボックスが表示されるはずです。
  12. +
+ +

関数名の後ろに括弧が含まれていないのはなぜでしょうか。これは、ボタンがクリックされた後にのみ、関数をすぐに呼びたくないからです。行を次の行に変更しようとすると

+ +
btn.onclick = displayMessage();
+ +

保存して再読み込みすると、ボタンをクリックせずにメッセージボックスが表示されます。このコンテキストの括弧は「関数呼び出し演算子」と呼ばれることがあります。現在のスコープですぐに関数を実行する場合にのみ使用します。同様の点で、匿名関数内のコードは関数スコープ内にあるため、すぐには実行されません。
+
+ 最後の実験を試した場合は、最後の変更を取り消してから実行してください。

+ +

パラメーターを使用して関数を改善する

+ +

その機能はそれほど便利ではありません — 毎回同じ既定のメッセージを表示したくはないのです。いくつかのパラメーターを追加して機能を改善し、いくつかの異なるオプションで呼び出すことができるようにしましょう。

+ +
    +
  1. まず、関数の最初の行を更新します。 +
    function displayMessage() {
    + +
    このようになります:
    + +
    function displayMessage(msgText, msgType) {
    + 関数を呼び出すと、括弧内に 2 つの変数値を指定して、メッセージボックスに表示するメッセージとそのメッセージのタイプを指定できます。
  2. +
  3. 最初のパラメーターを使用するには、関数内の次の行を更新します: +
    msg.textContent = 'This is a message box';
    + +
    このようになります
    + +
    msg.textContent = msgText;
    +
  4. +
  5. 最後に関数呼び出しを更新して、更新されたメッセージテキストを追加する必要があります。次の行を変更します。 +
    btn.onclick = displayMessage;
    + +
    このブロックのようになります:
    + +
    btn.onclick = function() {
    +  displayMessage('Woo, this is a different message!');
    +};
    + 私たちが呼び出している関数の括弧内にパラメーターを指定したい場合、直接呼び出すことはできません - 直接のスコープにないため、すぐに呼び出されないように無名関数の中に入れる必要があります。ボタンがクリックされるまで呼び出されません。
  6. +
  7. 再読み込みしてコードをもう一度試してみてください。それでもパラメーター内のメッセージを変えてボックスに表示されるメッセージを変えることができます。
  8. +
+ +

より複雑なパラメーター

+ +

次のパラメーターに移りましょう。これにはもう少し作業が必要です。msgType パラメーターの設定によって、別のアイコンと異なる背景色が表示されるように設定していきます。

+ +
    +
  1. まず始めに、この演習に必要なアイコン (warningchat) を GitHub からダウンロードしてください。HTML ファイルと同じ場所にある icons という新しいフォルダーに保存します + +
    メモ: iconfinder.com にある warning と chat のアイコンは Nazarrudin Ansyari によってデザインされたものです。ありがとう! (実際のアイコンのページは移動か削除されています。)
    +
  2. +
  3. 次に、HTML ファイル内の CSS を探します。私たちは、アイコンの道を作るためにいくつかの変更を行います。まず .msgBox の幅を次のように更新します +
    width: 200px;
    + このようにします + +
    width: 242px;
    +
  4. +
  5. 次に、.msgBox p { ... } ルール内に次の行を追加します +
    padding-left: 82px;
    +background-position: 25px center;
    +background-repeat: no-repeat;
    +
  6. +
  7. これでアイコンの表示を処理するために、displayMessage() 関数にコードを追加する必要があります。関数の終了中括弧 (}) のすぐ上に次のブロックを追加します。 +
    if (msgType === 'warning') {
    +  msg.style.backgroundImage = 'url(icons/warning.png)';
    +  panel.style.backgroundColor = 'red';
    +} else if (msgType === 'chat') {
    +  msg.style.backgroundImage = 'url(icons/chat.png)';
    +  panel.style.backgroundColor = 'aqua';
    +} else {
    +  msg.style.paddingLeft = '20px';
    +}
    + ここで、msgType パラメーターが 'warning' に設定されている場合、警告アイコンが表示され、パネルの背景色は赤に設定されます。'chat'に設定されている場合、チャットアイコンが表示され、パネルの背景色が青色に設定されます。msgType パラメーターがまったく設定されていない (または別のものに変更されている) 場合、コードの else { ... } 部分が有効になり、段落には単にデフォルトのパディングが与えられ、背景パネルの色もしくはアイコンのどちらかが未設定の状態となります。これは msgType パラメーターが指定されていない場合、省略可能なパラメーターであることを意味するデフォルトの状態を提供します。
  8. +
  9. 更新された関数をテストしましょう。この displayMessage() 呼び出しを更新して: +
    displayMessage('Woo, this is a different message!');
    + これらのうちの 1 つにしましょう。 + +
    displayMessage('Your inbox is almost full — delete some mails', 'warning');
    +displayMessage('Brian: Hi there, how are you today?','chat');
    + 私たちの (今はそうではない) 小さな機能がどのように役立つかがわかります。
  10. +
+ +
+

メモ: サンプルをうまく動作させることができない場合は、コードを GitHub の完成バージョンと比較して (see it running live もみて) チェックしてください。もしくは私たちにヘルプを依頼してください。

+
+ +

スキルをテストしよう!

+ +

この記事の最後まで到達しましたが、最も大事な情報を覚えていますか?移動する前に、この情報を維持しているか検証するテストを見ることができます— Test your skills: Functions. を見てください。このテストは次の記事でカバーするスキルが必要ですので、試す前にこれを読んでおくとよいでしょう。

+ +

まとめ

+ +

最後までたどり着きました。おめでとうございます!この記事では、実用的なカスタム関数を構築するプロセス全体を紹介しました。もう少し動けば、実際のプロジェクトに移植することができます。次の記事では、別の重要な関連概念である戻り値を説明して関数をまとめます。

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/conditionals/index.html b/files/ja/learn/javascript/building_blocks/conditionals/index.html new file mode 100644 index 0000000000..70d662df26 --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/conditionals/index.html @@ -0,0 +1,782 @@ +--- +title: コードでの意思決定 — 条件文 +slug: Learn/JavaScript/Building_blocks/conditionals +tags: + - Article + - Beginner + - CodingScripting + - Conditionals + - JavaScript + - Learn + - Switch + - conditions + - else + - if + - 'l10n:priority' + - ternary +translation_of: Learn/JavaScript/Building_blocks/conditionals +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}
+ +

どのプログラミング言語でも、コードは様々な入力に応じた決定を迫られ、その結果として動作を起こします。例えば、ゲームではプレイヤーの残機が 0 になった場合、ゲームオーバーとなります。天気アプリは朝に起動された場合は日の出の画像を表示し、夜に起動された場合は星や月の画像を表示します。この記事では、JavaScript において、条件文と呼ばれるものがどのように動作するかを説明します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターの知識および HTML と CSS への理解、JavaScript の第一歩
目的:JavaScript における条件分岐構造をどのように使用するかを理解する。
+ +

すべては条件次第..

+ +

人類 (と他の動物たち)は 小さいもの (「クッキーを 1 つ食べるべきか、2 つ食べるべきか...。」) から大きいもの (「故郷に残って親父の農場を継ぐべきか、アメリカで宇宙物理学を学ぶべきか...。」) まで、生活に関わるすべての決定を下します。

+ +

JavaScript では、条件文を使ってそのような決定を下すことが可能です。条件文は、選ばなければならない選択肢 (例えば「クッキーを 1 つまたは 2 つ食べる」) からそれを選んだ場合の結果を導き出します (おそらく「1 つクッキーを食べる」を選んだら、「まだちょっとお腹が空いている」という結果となるでしょうし、「2 つクッキーを食べる」を選んだら「お腹いっぱい。だけどクッキーを全部食べてママに怒られる」という結果となってしまうでしょう。)

+ +

+ +

if ... else ステートメント

+ +

それでは、JavaScript で最もよく使われる条件文から始めましょう。それは if ... else ステートメントです。

+ +

if ... else の基本的な構文

+ +

if...else の基本的な構文は以下の{{glossary("pseudocode", "擬似コード")}}のようになっています。

+ +
if (条件式) {
+  条件式が true の場合に実行されるコード
+} else {
+  それ以外の場合に実行されるコード
+}
+ +

ここでは...

+ +
    +
  1. if キーワードの後ろに括弧が並んでいます。
  2. +
  3. 判断に用いる条件式はその括弧の中にあります (たいていの場合は「この値はもう一方より大きい」や、「この値は存在する」などです)。この条件には、前回のモジュールで習った比較演算子を使用し、true または false を返します。
  4. +
  5. 中にコードが書いてある (実際のコードはどんなものでも構いません) 中括弧のペアは、条件式が true の場合に実行されます。
  6. +
  7. 続いて else キーワードがあります。
  8. +
  9. さらに他のコードが書いてある (こちらもどんなコードでも構いません) 中括弧のペアは条件式が true ではない場合に実行されます。
  10. +
+ +

このコードは (英語を使う人には) とても読みやすいものになっています。このコードは「もし ( if ) 条件式 ( condition ) が true を返したら A のコードを実行し、それ以外ならば ( else ) B のコードを実行する」と読めます。

+ +

else とそれに続く中括弧は必ずしも書く必要がないことを覚えておきましょう。次のコードも全く問題のないコードです。

+ +
if (条件式) {
+  条件式が true の場合に実行されるコード
+}
+
+普通に実行されるコード
+ +

ここで注意しておかなければならないことがあります。それは 2 つ目のコードブロックは、条件分岐の管理下になく、条件式が truefalse かに関係なく、常に実行されることです。これはまったく悪いことではないのですが、条件に応じてどちらか一方のみ動かしたいと思っている場合には、気を付けておかないと思った通りの動作をしないでしょう。

+ +

最後の確認点として、if...else ステートメントが中括弧なしで書かれているのを見ることがあります。以下のような省略した書き方です。

+ +
if (条件式) 条件式が true の場合に実行されるコード
+else それ以外の場合に実行されるコード
+ +

これは正常なコードですが、あまり推奨されません。中括弧でコードブロックを分割して、複数の行とインデントを使って書いたほうが読みやすく、コードがどうなっているかを把握しやすいためです。

+ +

実際の例

+ +

構文をもっとよく理解するため、実際の例を考えてみましょう。例えば両親にお使いを頼まれた子供を想像してください。「欲しがってたおもちゃがあるよね。お使いを頼まれてくれたら、お小遣いを追加であげるよ。」と親が頼みます。JavaScript では以下のようなコードで表現できます。

+ +
let shoppingDone = false;
+
+if (shoppingDone === true) {
+  let childsAllowance = 10;
+} else {
+  let childsAllowance = 5;
+}
+ +

このコードは常に shoppingDone 変数が false なので、かわいそうな子供は追加のお小遣いを受け取れません。両親が子供がお使いを完了した場合に shoppingDone 変数を true にセットしてあげるかどうかはプログラム次第です (つまり私たち次第です。)

+ +
+

: GitHub で上記のコードの完全なバージョンが公開されています (ライブ実行でも確認できます。)

+
+ +

else if

+ +

先ほどの例では実行結果は 2 つだけでしたが、もっと選択肢がある場合はどうでしょうか?

+ +

else if を使って、追加の選択肢を if...else に繋ぐ方法があります。追加の選択肢は if() { ... } と else { ... } の間に、コードブロックを続けて追加する必要があります。具体的な例として、天気予報のアプリケーションの一部を見てみましょう。

+ +
<label for="weather">今日の天気を選択してください: </label>
+<select id="weather">
+  <option value="">--選択してください--</option>
+  <option value="sunny">晴れ</option>
+  <option value="rainy">雨</option>
+  <option value="snowing">雪</option>
+  <option value="overcast">曇り</option>
+</select>
+
+<p></p>
+ +
const select = document.querySelector('select');
+const para = document.querySelector('p');
+
+select.addEventListener('change', setWeather);
+
+function setWeather() {
+  const choice = select.value;
+
+  if (choice === 'sunny') {
+    para.textContent = '今日はとてもいい天気です。短いパンツをはいて、砂浜や公園に出かけ、アイスクリームを食べましょう!';
+  } else if (choice === 'rainy') {
+    para.textContent = '雨が降っています。レインコートと傘を忘れないようにして、できる限り室内で過ごしましょう。';
+  } else if (choice === 'snowing') {
+    para.textContent = '雪が降ってとても寒いです!室内でホットチョコレートを飲むか、雪だるまを作るのがよいでしょう。';
+  } else if (choice === 'overcast') {
+    para.textContent = '雨は降っていませんが、空はとても暗くなっています。万が一に備えレインコートを持ちましょう。';
+  } else {
+    para.textContent = '';
+  }
+}
+
+
+ +

{{ EmbedLiveSample('else_if', '100%', 100, "", "", "hide-codepen-jsfiddle") }}

+ +
    +
  1. HTML に、天気を選ぶことが可能な {{htmlelement("select")}} 要素があり、1 つの段落がありますね。
  2. +
  3. JavaScript では、{{htmlelement("select")}} と {{htmlelement("p")}} の各要素について、参照を取得して保持し、<select> 要素にはイベントリスナーを設定しています。もし、要素の値が変わったら setWeather() 関数が動きます。
  4. +
  5. この関数が実行されると、まずは choice という変数に、<select> 要素の現在選択されている値を入れます。そして、条件文を使い、choice の値に応じた文字列が段落に設定されます。最初の if() {...} のブロックを除いて、どのように else if() {...} のブロックで判定しているか注目してください。
  6. +
  7. 一番下の else {...} 選択肢は、「最後の手段」となるオプションで、この中のコードは、どの条件にも一致しなかった場合 (true とならなかった場合) に実行されます。今回の場合選択されていない場合に、段落を空にしています。何も選択されていない場合というのは、ユーザーが再度最初に表示されていた「--選択してください--」というオプションを選んだ場合です。
  8. +
+ +
+

: GitHub で上記のコードの完全なバージョンが公開されています (ライブ実行でも確認できます。)

+
+ +

比較演算子に関するメモ

+ +

比較演算子は条件文の中で使われます。JavaScript での数学入門 — 数値と演算子についてで初めて出てきましたね。演算子には以下のようなものがありました。

+ + + +
+

: もし記憶があいまいならば、上記のリンク先を見て復習しましょう。

+
+ +

真偽 (true/false) の値を判定する場合には少しの配慮が必要であることを付け加えさせてください。おそらく何度か躓くであろう、よくあるパターンです。falseundefinednull0NaN、空文字列 ('') 以外の値は条件文で使った場合に true となります。ですから、その値が true であるか判定したい場合や、その値が存在するか (例えば、undefined ではないこと) 判定したい場合は単に変数名を使用するだけです。

+ +
let cheese = 'チェダー';
+
+if (cheese) {
+  console.log('やった!チーズトーストを作るチーズがあるよ。');
+} else {
+  console.log('今日はチーズトーストのチーズがないよ。');
+}
+ +

先ほどの子供のお使いの例に戻ると、以下のようにも書くことができます。

+ +
let shoppingDone = false;
+
+if (shoppingDone) { // '=== true' を明示的に指定する必要はありません
+  let childsAllowance = 10;
+} else {
+  let childsAllowance = 5;
+}
+ +

入れ子の if ... else

+ +

if...else ステートメントを入れ子にして、他の if...else ステートメントの中で使用することは全く問題ありません。例えば、天気予報アプリケーションで気温に応じて表示する内容を切り替えたい場合以下のように書くことができます。

+ +
if (choice === 'sunny') {
+  if (temperature < 86) {
+    para.textContent = '外の気温は ' + temperature + ' 度です — とてもいい天気です。海水浴や、公園に出かけてアイスクリームを食べましょう';
+  } else if (temperature >= 86) {
+    para.textContent = '外の気温は ' + temperature + ' 度です — かなり暑いです!外出する場合にはアイスクリームを持って出かけましょう。';
+  }
+}
+ +

内側の if...else ステートメントは、外側の if ステートメントとは完全に独立して作用します。

+ +

論理演算子: AND と OR と NOT

+ +

複数の条件を入れ子の if...else ステートメントを書かずに判定したいなら、論理演算子の出番です。条件文の中で使用する場合、AND と OR は以下の作用をもたらすでしょう。

+ + + +

AND の例を示すため、先ほどのコードを書き直すと以下のようになります。

+ +
if (choice === 'sunny' && temperature < 86) {
+  para.textContent = '外の気温は ' + temperature + ' 度です — とてもいい天気です。海水浴や、公園に出かけてアイスクリームを食べましょう';
+} else if (choice === 'sunny' && temperature >= 86) {
+  para.textContent = '外の気温は ' + temperature + ' 度です — かなり暑いです!外出する場合にはアイスクリームを持って出かけましょう。';
+}
+ +

例では、最初のブロックは choice === 'sunny' temperature < 86 のどちらも true となった場合にのみ実行されます。

+ +

今度は OR の例を見てみましょう。

+ +
if (iceCreamCarOutside || houseStatus === '火事') {
+  console.log('すぐに家から出ましょう。');
+} else {
+  console.log('それでは家にいましょう。');
+}
+ +

論理演算子の最後は NOT です。! 演算子で表され、式を否定するのに使用します。それでは先ほどの OR と組み合わせてみましょう。

+ +
if (!(iceCreamVanOutside || houseStatus === '火事')) {
+  console.log('それでは家にいましょう。');
+} else {
+  console.log('すぐに家から出ましょう。');
+}
+ +

このコード例では、OR ステートメントが true となれば、NOT 演算子がそれを否定します。そのため、式全体は false となります。

+ +

論理ステートメントは思うがままに、いくつでも繋げることが可能です。次の例では両方の OR ステートメントが真を返した場合に AND ステートメントが真となり、if の中のコードが実行されます。

+ +
if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'スティーブ')) {
+  // コードを実行
+}
+ +

論理 OR 演算子を使用するうえでよくある間違いは、判定しようとしている変数を一度だけ書いて、その後に判定したい値を || (OR) 演算子で区切って指定する誤りです。次のような例です。

+ +
if (x === 5 || 7 || 10 || 20) {
+  // コードを実行する
+}
+ +

この場合、if(...)  の条件式は常に真となります。なぜなら 7 (もしくはその他 0 以外の数値) が常に true と評価されるためです。この条件式は「もし x が 5 であるか 7 が真であるならば (7 は常に真です)」となります。これは求めているものではありませんよね!このコードの誤りを修正するためには、OR 演算子の隣に常に完全な条件を書かなければなりません。

+ +
if (x === 5 || x === 7 || x === 10 ||x === 20) {
+  // コードを実行する
+}
+ +

switch ステートメント

+ +

if...else ステートメントは条件の判定を上手くこなしていましたが、欠点がないわけではありません。いくつかの選択肢しかない場合には申し分ないのですが、AND / OR の条件が複雑になるにつれて (例えば、複数の論理演算子を使ったりする場合など)、相当量のコードを書かなければなりません。ある選択肢に応じて値を変数に設定したり、特定の条件に応じて何かを表示したりするとき、選択肢がたくさんあると、if...else ステートメントを書くのは面倒です。

+ +

switch ステートメントはそんなときの味方です。switch ステートメントは一つの式または値を受け取り、それに合致する値が見つかるまで選択肢を探します。そして合致した選択肢に対応するコードを実行します。まずは擬似コードを見て、雰囲気をつかみましょう。

+ +
switch ( 式 ) {
+  case 選択肢1:
+    このコードを実行する
+    break;
+
+  case 選択肢2:
+    代わりにこのコードを実行する
+    break;
+
+  // 以下に選択肢を好きなだけ並べる
+
+  default:
+    既定でこのコードを実行する
+}
+ +

上記のコードには...

+ +
    +
  1. switch キーワードに続き、一組の括弧があります。
  2. +
  3. 括弧の中には、式または値があります。
  4. +
  5. case キーワードに続き、選択肢となる式または値、それにコロン (:) が並んでいます。
  6. +
  7. もしその選択肢にマッチすれば、コードが実行されます。
  8. +
  9. break ステートメントとセミコロン (;) があります。もし前の選択肢にマッチして入ればブラウザーはコードの実行をここでやめ、switch ステートメントの後ろにあるコードに移動します。
  10. +
  11. case 節 (上記 3. から 5. ) は好きなだけ書くことができます。
  12. +
  13. 上記 3. から 5.の case 節と全く同じコードパターンで書かれている default キーワードがあります。違いは default の後ろに選択肢が書かれていないことです。また、後ろに続くコードがないので、ここには break ステートメントが必要ありません。もし、選択肢のどれにもマッチするものがない場合に既定のオプションとして実行されます。
  14. +
+ +
+

: 評価する式の値が不明な値にならないのであれば、default 節は書く必要はありません。しかし、式が不明な値となり、それに対処する必要があるのなら、default 節を書くことで対応が可能です。

+
+ +

switch を使用する例

+ +

それでは実際の例を見てみましょう。先ほどの天気予報アプリを switch ステートメントを使用して書き直してみました。

+ +
<label for="weather">今日の天気を選択してください: </label>
+<select id="weather">
+  <option value="">--選択してください--</option>
+  <option value="sunny">晴れ</option>
+  <option value="rainy">雨</option>
+  <option value="snowing">雪</option>
+  <option value="overcast">曇り</option>
+</select>
+
+<p></p>
+ +
const select = document.querySelector('select');
+const para = document.querySelector('p');
+
+select.addEventListener('change', setWeather);
+
+
+function setWeather() {
+  const choice = select.value;
+
+  switch (choice) {
+    case 'sunny':
+      para.textContent = '今日はとてもいい天気です。短いパンツをはいて、砂浜や公園に出かけ、アイスクリームを食べましょう!';
+      break;
+    case 'rainy':
+      para.textContent = '雨が降っています。レインコートと傘を忘れないようにしましょう。';
+      break;
+    case 'snowing':
+      para.textContent = '雪が降ってとても寒いです!室内でホットチョコレートを飲むか、雪だるまを作るのがよいでしょう。';
+      break;
+    case 'overcast':
+      para.textContent = '雨は降っていませんが、空はとても暗くなっています。万が一に備えレインコートを持ちましょう。';
+      break;
+    default:
+      para.textContent = '';
+  }
+}
+ +

{{ EmbedLiveSample('A_switch_example', '100%', 100, "", "", "hide-codepen-jsfiddle") }}

+ +
+

: このサンプルを GitHub で見ることができます。(実行可能なデモもあります。)

+
+ +

三項演算子

+ +

例題に進む前に、ちょっとした構文をご紹介しましょう。三項演算子 (もしくは条件演算子) は条件式を判定し、その結果に応じて 2 つの値または式のうち、どちらか一方を返します。これはある状況においてはとても便利です。単純に true/false で判定可能な 2 つの選択肢のうちより片方を選ぶという場合には、if...else ブロックを書くよりも多くのコードを節約できます。この擬似コードは以下のようなものになります。

+ +
( 条件式 ) ? こちらのコードを実行する : 代わりにこちらのコードを実行する
+ +

それでは実際に例を見て見ましょう。

+ +
let greeting = ( isBirthday ) ? 'スミスさん、誕生日おめでとうございます!良い一日を。' : 'スミスさんおはようございます。';
+ +

この例では isBirthday という変数があり、この変数が true の場合、お客に誕生日を祝福するメッセージを送ります。そうでなければ、通常の挨拶を送ります。

+ +

三項演算子を使用する例

+ +

三項演算子を変数の代入にのみ使用する必要はありません。関数や、複数行に渡るコードを実行する場合にも (それ以外にも好きなように) 使用できます。次の例は三項演算子を使用してサイトにテーマを適用しています。

+ +
<label for="theme">テーマを選んでください: </label>
+<select id="theme">
+  <option value="white">白</option>
+  <option value="black">黒</option>
+</select>
+
+<h1>私のウェブサイト</h1>
+ +
const select = document.querySelector('select');
+const html = document.querySelector('html');
+document.body.style.padding = '10px';
+
+function update(bgColor, textColor) {
+  html.style.backgroundColor = bgColor;
+  html.style.color = textColor;
+}
+
+select.onchange = function() {
+  ( select.value === 'black' ) ? update('black','white') : update('white','black');
+}
+
+ +

{{ EmbedLiveSample('Ternary_operator_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}

+ +

上記の例では、テーマ (黒または白) を選択することができる {{htmlelement('select')}} 要素と、サイトのタイトルが書かれた単純な {{htmlelement('h1')}} 要素があります。さらに update() という関数があり、その関数は引数 (入力値) として 2 つの色を取ります。この関数が呼ばれると、ウェブサイトの背景色は 1 つ目の引数に、文字の色は 2 つの目の引数に設定されます。

+ +

さらに、三項演算子を含む onchange イベントリスナーがあります。select.value === 'black' という条件式で始まっています。この式が true であるならば、update() 関数を引数に 'black''white' を指定して実行します (つまり、背景色を黒、文字色を白に設定します)。この式が false であるならば、update() 関数を引数に 'white''black' を指定して実行します (つまり、背景色を逆にします)。

+ +
+

: この例は GitHub でも公開しています (または、動くデモもあります。)

+
+ +

アクティブ学習: 単純なカレンダー

+ +

この例では、単純なカレンダーアプリケーションの作成を手伝ってもらいます。現在、以下の内容がコードに書かれています。

+ + + +

あなたには、onchange ハンドラーの内部に条件式を書いてもらいます。// 条件式をここに書く というコメントのすぐ下に...

+ +
    +
  1. 選択されている月を取得します (これは choice 変数に格納されています。この値は <select> 要素で選択された後の値で、例えば 1 月なら、"1" といった値です。)
  2. +
  3. days という変数に、選択された月の日数を設定します。そのためには、1年の各月の日数を調べる必要があるでしょう。うるう年はこの例題の目的から外れるため、無視してください。
  4. +
+ +

ヒント:

+ + + +

もし間違ってしまっても、「リセット」ボタンを押すことでいつでも元に戻せます。詰まってしまったら、「答えを見る」ボタンで答えが見られます。

+ + + +

{{ EmbedLiveSample('Playable_code', '100%', 1110, "", "", "hide-codepen-jsfiddle") }}

+ +

アクティブ学習: もっとたくさんの色から選ぶ!

+ +

この例では、先ほどの三項演算子の例を switch ステートメントに変換し、単純なウェブサイトに、より多くの選択肢を与えます。{{htmlelement("select")}} 要素を見てください。今回は先ほどの 2 つではなく、5 つの選択肢があります。// ここに SWITCH ステートメントを書く というコメントの真下に switch ステートメントを追加してください。

+ + + +

もし間違ってしまっても、「リセット」ボタンを押すことでいつでも元に戻せます。詰まってしまったら、「答えを見る」ボタンで答えが見られます。

+ + + +

{{ EmbedLiveSample('Playable_code_2', '100%', 950, "", "", "hide-codepen-jsfiddle") }}

+ +

スキルをテストしましょう!

+ +

この記事の最後まで来ましたが、最も大事な情報を覚えていますか?先に進む前に、この情報を保持しているか検証するテストがあります — Test your skills: Conditionals を見てください。

+ +

まとめ

+ +

これで JavaScript での条件構造について今知っておくべきことはすべてです!簡単な例を通してそのコンセプトが理解できたと思います。もし理解できないことがあれば、何度も記事を読み返しましょう。私たちに連絡をしても構いません。

+ +

関連情報

+ + + +

{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/events/index.html b/files/ja/learn/javascript/building_blocks/events/index.html new file mode 100644 index 0000000000..7c40419c10 --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/events/index.html @@ -0,0 +1,597 @@ +--- +title: イベントへの入門 +slug: Learn/JavaScript/Building_blocks/Events +tags: + - Beginner + - CodingScripting + - JavaScript + - イベント + - イベントハンドラー + - ガイド + - 学習 + - 記事 +translation_of: Learn/JavaScript/Building_blocks/Events +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
+ +

イベントは、あなたがプログラムを書いているシステムで生じた動作、出来事を指します。システムからあなたへ、イベントとして何かあった事を知らせてくるので、必要であればそれに何らかの反応を返す事ができます。例えば、ユーザーがウェブページ上でボタンを押したとき、ある情報を表示するように反応させたいと思うかもしれません。この記事では、イベントに関する重要な概念を取り上げ、ブラウザーの中でのイベントの振る舞いを見ていきます。ここでは、全てを説明するのではなく、この段階で知っておくべき内容を取り上げます。

+ + + + + + + + + + + + +
前提条件:コンピューターに関する基本的な知識があること。HTML と CSS について理解していて、JavaScript の第一歩の記事を理解していること。
目的:イベントの基本的な理論を理解すること。ブラウザーでの振る舞いを理解し、プログラミング環境が変わると、イベントの振る舞いが変わることを理解すること。
+ +

運命的なイベントの連続

+ +

先ほど説明しましたが、イベントはあなたがプログラムしているシステムの中で生じた動作や出来事です。つまり、あるイベントが起きたときに、システムはある種の信号を発します。さらに、ある種のアクションが自動的に実行されるためのメカニズムも提供します。例えば、空港では、飛行機が離陸するために滑走路がクリアになった時に、信号がパイロットに送られます。その結果、パイロットは飛行機の操縦を開始します。

+ +

+ +

ウェブの場合は、イベントは、ブラウザーのウィンドウの中で発火されます、そしてその中に属する特定の項目に紐付く傾向にあります — これは単一の要素、要素の集合、現在のタブでロードされた HTML 文書、ブラウザー画面全体といったものです。発生するイベントはたくさんの異なる種類があります。例をあげると。

+ + + +

ここや MDN Event リファレンスを覗いてみれば、とてもたくさんの応答可能なイベントがあるのが判るでしょう。

+ +

それぞれの利用可能なイベントにはイベントハンドラーがあり、これはイベントに発火した時に実行される (通常はユーザー定義の JavaScript 関数) コードのブロックのことです。イベントの発火に対する応答としてコードのブロックが実行されるように定義する事を、イベントハンドラーを登録すると言います。イベントハンドラーは時にイベントリスナー と呼ばれる事を付記しておきます—我々の目的から見ると言い変えてもほとんど問題ないのですが、厳密に言えば一緒に動作する別のものです。イベントリスナーはイベントの発生を監視し、イベントハンドラーは発生したイベントの応答として動作するコードです。

+ +
+

メモ: 大事な事ですがウェブのイベントは JavaScript 言語の主要部分の一部ではありません — ブラウザーに組み込まれた JavaScript API の一部として定義されたものです。

+
+ +

簡単な例

+ +

ここで何を言ってるのか説明するため、簡単な例を見てみましょう。このコースでこれまでに例の多くに使われているイベントやイベントハンドラーを見てきました、しかし、知識を固めるために整理をしましょう。続く例では、押すと背景色がランダムに変化する {{htmlelement("button")}} が一つあります:

+ +
<button>Change color</button>
+ + + +

JavaScript はこのようになります:

+ +
const btn = document.querySelector('button');
+
+function random(number) {
+  return Math.floor(Math.random() * (number+1));
+}
+
+btn.onclick = function() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+}
+ +

このコードでは、btn という変数に {{domxref("Document.querySelector()")}} 関数を使って取得したボタンへの参照を格納しています。それとは別にランダムな数値を返す関数も定義しています。コードの 3 つ目の部分はイベントハンドラーです。btn 変数は<button>要素を指していますが、この種のオブジェクトにはたくさん発火し得るイベントがあるので、色々なイベントハンドラーが使えます。onclick イベントハンドラプロパティに、ランダムな RGB色を生成し <body>background-color を設定するコードを抱えた匿名関数を代入する事で、click イベントが発火されるのを待ちかまえます。

+ +

このコードは <button> 要素でクリックイベントが発火すれば常に実行されます、要はユーザーがクリックしたらいつでも。

+ +

この例の出力は以下のようになります:

+ +

{{ EmbedLiveSample('A_simple_example', '100%', 200, "", "", "hide-codepen-jsfiddle") }}

+ +

ただのウェブページではありません

+ +

ここで言及しておくべき事は、イベントは JavaScript 固有のものではないという事です — ほとんどのプログラミング言語はいくつかのイベントモデルを持ち、その動作する方法はしばしは JavaScript の方式とは異なっています。実際、ウェブページの JavaScript のイベントモデルは他の環境で用いられている JavaScript のイベントモデルと異なっています。

+ +

例えば、Node.js は開発者に JavaScript でネットワークとサーバーサイドのアプリケーションを構築することを可能にするとても有名な JavaScript ランタイムです。Node.js event model はイベントを待ち受けるリスナー、イベントを定期的に発生させるエミッターに依拠しています —たいして違ってないように聞こえますが、コードは極めて異なっていて、イベントリスナーを登録する on() や、一度実行したら登録を解除するイベントリスナーを登録するための once() のような関数を使っていきます。HTTP connect event docs が使い方の良い例を教えてくれます。

+ +

その他の例として、WebExtensions と呼ばれる技術を使って、クロスブラウザーアドオン (ブラウザーの機能拡張) を JavaScript で作成できます。イベントモデルは Web イベントモデルと似ていますが、ほんの少し違いがあります (イベントリスナーのプロパティはキャメルケース (例 onmessage でなく onMessage) で命名されていて、addListener 関数で結び付ける必要があります。例として runtime.onMessage page を確認してください。

+ +

学習の今の段階で、そのような他の環境について何か理解する必要はありません。イベントは異なるプログラミング環境では異なることがあるとだけ認識してください。

+ +

ウェブイベントの使用方法

+ +

関連づけたいイベントが発火した時に走らせたいイベントリスナーコードを ウェブページに追加する方法はいろいろあります。このセクションでは様々なメカニズムを見ていき、どれを使うべきなのか議論していきます。

+ +

イベントハンドラープロパティ

+ +

イベントハンドラーコードを代入するためのいろいろなプロパティがあり、そういったものをここまでのコースで最もたくさん見てきました。上記の例に戻りましょう。

+ +
const btn = document.querySelector('button');
+
+btn.onclick = function() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+}
+ +

onclick プロパティがこの例で使用されているイベントハンドラープロパティです。ボタンで利用可能なプロパティ(例えば btn.textContentbtn.style)のうちの 1 プロパティに過ぎませんが、特別な種類のものです(コードを代入すると、そのコードはボタンでイベントが発火した際に実行される)。

+ +

ハンドラープロパティには、名前付き関数の関数名 (Build your own function でみられるような) を設定することもできます。こう書いても動作は同じです:

+ +
const btn = document.querySelector('button');
+
+function bgChange() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+}
+
+btn.onclick = bgChange;
+ +

利用できるイベントハンドラープロパティにはとてもたくさんの種類があります。実験してみましょう。

+ +

まずは、random-color-eventhandlerproperty.html のローカルコピーを作成し、ブラウザーで開いてくださいこれはこの記事ですでに遊んだ簡単なランダム色のサンプルです。さて、btn.onclick のところを以下の異なる値に変えてみて、結果を順に見てみてください:

+ + + +

いくつかのイベントはとても汎用的なのでほとんどどこでも使えます(例えば onlick ハンドラはほぼ全ての要素に登録できます)が、いくつかはもっと限定的で、特定の状況でしか使えません(例えば onplay  は{{htmlelement("video")}}のような特定の要素でのみ意味を持ちます)。

+ +

インラインイベントハンドラー — 使っちゃだめ

+ +

あなたのコードでこんな形を見た事があるかもしれません:

+ +
<button onclick="bgChange()">Press me</button>
+
+ +
function bgChange() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+}
+ +
+

メモ: こちらに GitHub上のサンプルがあります (また、こちらで実際に動くところを見られます)。

+
+ +

Web 上で見かける最初期のイベントハンドラー登録方法には、上の例のようなイベントハンドラーHTML属性(インラインイベントハンドラーとも言う)があります — 属性値がイベント発生時に実行したい JavaScript コードそのものです。上の例では{{htmlelement("script")}}要素の中で定義された関数を起動していますが、直接JavsScript そのものを属性の中に入れる事もできます。例えば:

+ +
<button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button>
+ +

多くのイベントハンドラープロパティと等価な HTML属性を見付けるでしょうが、使うべきではありません — こういうのは悪い方法とみなされています。ちょっとした事を手早く片づけたい時、イベントハンドラー属性を使うのが簡単に思えるかもしれませんが、あっという間に手がつけられない、効率の悪いものになってしまいます。

+ +

そもそも、あなたの HTML と JavaScript を混在させると、読みにくくなってしまうため、良いアイデアではありません — あなたの JavaScript は一ヶ所にまとめる方が良いです。別の一つのファイルになっていれば、それを複数の HTML ドキュメントに適用できますから。

+ +

(HTML と JavaScript が)一つのファイルになっているとしても、インラインイベントハンドラーは良いアイデアではありません。ボタン一つならいいですが、ボタンが 100 あったら? ファイルに 100 の属性を追加したならば、あっという間に管理していくのは悪夢と化す事でしょう。JavaScript を使えば、ページにボタンがいくつあろうが、全部のボタンにイベントハンドラーを追加するのは簡単です、こんな具合です:

+ +
const buttons = document.querySelectorAll('button');
+
+for (let i = 0; i < buttons.length; i++) {
+  buttons[i].onclick = bgChange;
+}
+ +

ここにある他のオプションは NodeList オブジェクトの組み込みメソッドの forEach() で使えることに注意してください:

+ +
buttons.forEach(function(button) {
+  button.onclick = bgChange;
+});
+ +
+

: プログラムロジックをコンテンツから分離しておくと、あなたのサイトはサーチエンジンにとってより好ましいものになります。

+
+ +

addEventListener() と removeEventListener()

+ +

最新のイベント機構は Document Object Model (DOM) Level 2 Events 仕様で規定されていて、ブラウザーに新しい関数が追加されました — addEventListener()です。この関数はイベントハンドラープロパティと同じ方向性ですが、文法は明確に異なります。ランダム色の例をこんな風に書き換える事ができます:

+ +
const btn = document.querySelector('button');
+
+function bgChange() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+}
+
+btn.addEventListener('click', bgChange);
+ +
+

メモ: こちらに GitHub上のサンプルがあります (また、こちらで実際に動くところが見られます)。

+
+ +

addEventListener() 関数のカッコの中で、二つの引数を指定しています — ハンドラーを登録したいイベントの名前と、それに反応して実行させたいコードを含んだ関数です。匿名関数を使って、実行したいコードを全部 addEventListener() 関数の引数に書いてしまっても全く問題ありません。こんな具合です:

+ +
btn.addEventListener('click', function() {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  document.body.style.backgroundColor = rndCol;
+});
+ +

この方式は、ここまでで見てきた古い方式に勝る点がいくつかあります。まず第一に、逆を行なう関数 removeEventListener()があり、以前に追加したリスナーを削除できます。例えばこうすると、このセクションの最初のコード部で追加したリスナーを削除します:

+ +
btn.removeEventListener('click', bgChange);
+ +

単純で小さなプログラムではたいした事ありませんが、大きくて複雑なプログラムでは、古く使われないイベントハンドラーを除去しておくと効率が良くなります。さらに、これは例えば同じボタンに状況の違いによって異なる動作をさせる事ができるようになります — ただ適切なイベントハンドラーを追加したり削除するだけで良いのです。

+ +

第二に、同じリスナーに複数のハンドラーを登録できます。
+ 次では二つのハンドラの両方は適用されません:

+ +
myElement.onclick = functionA;
+myElement.onclick = functionB;
+ +

二行目で最初に設定した onclick の値が上書きされるからです。
+ ですがこれなら動きます:

+ +
myElement.addEventListener('click', functionA);
+myElement.addEventListener('click', functionB);
+ +

要素がクリックされると、どちらの関数も走ります。

+ +

さらには、この方式ではもっとたくさんのパワフルな機能やオプションが使えます。それらはこの記事の範疇を少しばかり超えているので、知りたければ addEventListener()removeEventListener() のリファレンスページを見てください

+ +

どの方式を使えば良い?

+ +

三つの方式のうち、イベントハンドラーHTML属性は絶対使うべきではありません — 前に書いたように、時代遅れで悪いやり方です。

+ +

他の二つはまあまあどっちでも良いです、少なくとも単純な用途では:

+ + + +

三番目の方式の最大の利点は、必要なときに removeEventListener() 関数でイベントハンドラーコードを削除できる事、必要なときは要素に同種のリスナーを複数追加できる事です。例えば、ある要素に対して addEventListener('click', function() { ... }) を別の関数を第二引数に指定して何回か呼ぶ事ができます。これはイベントハンドラープロパティでは、プロパティは後からセットした値で上書きされてしまうので、できません。e.g.:

+ +
element.onclick = function1;
+element.onclick = function2;
+etc.
+ +
+

: もし仕事で IE8 より古いブラウザーをサポートするよう言われているなら、そのような古代のブラウザーは新しいものとは違ったイベントモデルを使っているため、困難にぶつかるかもしれません。でも怖がらないで。大半の JavaScript ライブラリ(例えば jQuery)には、ブラウザー間の差異をとっぱらえる関数が備わっています。勉強中のあなたがこの点について心配しすぎる必要はありません。

+
+ +

その他、イベントに関する概念

+ +

このセクションでは、イベントに関連するより進んだ概念について軽くさらっていきます。今の時点で完全に理解する必要があるほど重要ではありませんが、ときどき見かけることになるであろうコードのパターンがなぜそうなっているのか、理解する助けになるかもしれません。

+ +

Event objects

+ +

ときどきイベントハンドラー関数内で event、evt、単に e などと名付けられた引数を見かけるかもしれません。
+ これらはイベントオブジェクトと呼ばれ、イベントの追加機能や情報を提供する目的でイベントハンドラーに自動的に渡されます。例えば、またランダム色の例をちょっと書き換えてみましょう:

+ +
function bgChange(e) {
+  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
+  e.target.style.backgroundColor = rndCol;
+  console.log(e);
+}
+
+btn.addEventListener('click', bgChange);
+ +
+

: こちら に GitHub上のサンプルがあります (また、こちらで実際に動くところが見れらます)。

+
+ +

イベントオブジェクト e が関数に含まれていて、関数内で e.target — これはボタンそのもの — の背景色スタイルを設定しているのがわかるでしょう。イベントオブジェクトの target プロパティは、常にイベントが生じた要素への参照となっています。ですからこの例ではページではなくボタンの背景色がランダムに変わります。

+ +
+

: イベントオブジェクトには好きな名前を使えます — イベントハンドラー関数のカッコの中に使いたい名前を書くだけです。e/evt/event が開発者の間でとても良く使われていますが、これらが短くて覚えやすいからです。標準に従うのはいつだって良いやり方です。

+
+ +

複数の要素に同じイベントハンドラを割り当てて、どれかでイベントがあったときに何かさせたいような場合、e.target はとてつもなく有用なものです。複数の要素に同じイベントハンドラーを割り当てて、どれかでイベントがあったときに何かさせたいような場合、e.target はとてつもなく有用なものです。例えばクリックすると見えなくなるタイルが 16 個あるとします。e.target を使ってそれをただ消せるなら、もっと難解な手段で選びだすのよりも使いすいでしょう。続く例では (完全なソースコードは useful-eventtarget.html を見てください; ここで ライブ実行 も見られます)、16 個の {{htmlelement("div")}} 要素を JavaScript で生成します。そしてこれらを全部 {{domxref("document.querySelectorAll()")}}を使って選択し、ループで一つ一つに onclick ハンドラを追加して、それぞれがクリックされた時にランダムな色が表われるようにしています:

+ +
const divs = document.querySelectorAll('div');
+
+for (let i = 0; i < divs.length; i++) {
+  divs[i].onclick = function(e) {
+    e.target.style.backgroundColor = bgChange();
+  }
+}
+ +

結果はこうです(クリックして遊んでみてください):

+ + + +

{{ EmbedLiveSample('Hidden_example', '100%', 400) }}

+ +

あなたが使うであろうイベントハンドラーのほとんどでは、イベントオブジェクトには標準的なプロパティと関数(メソッド)({{domxref("Event")}}を参照してください)だけがあります。もっと上級者向けハンドラーでは、動作に必要な追加データを保持するために特殊なプロパティを付与するものもあります。例えば Media Recorder API には dataavailable イベントがあり、オーディオやビデオの録音や再生が終わって何か(保存したり再生したり)する準備ができたところで発火します。これに紐付く ondataavailable ハンドラーのイベントオブジェクトには録音・録画データを保持する data プロパティがあり、これを使って何かしらを行なえます。

+ +

標準の動作を抑制する

+ +

ときにはイベントに付随する標準動作を止めたい場合があるでしょう。一番よくあるのは、ウェブのフォーム、例えばカスタマイズした登録フォームです。詳細を入力し終えてサブミットボタンを押した時、普通の動作ではデータがサーバーの指定のページに送られて処理され、ブラウザーは"成功しました"ページ(や他に指定されていない場合、同様なページ)にリダイレクトされたりなんやらします。

+ +

ユーザーが適切なデータを送信しなかった場合に問題が発生します — 開発者としてあなたはサーバーへのデータ送信を抑止し、どこに問題があってデータを適切なものにするにはどうすればいいのか示す、ユーザーへのエラーメッセージを表示したいことでしょう。ブラウザーの中にはフォームデータの自検証機能を備えたものもありますが、多くはないので、それには頼らず自前の検証機能を実装すべきです。簡単な例を見てみましょう。

+ +

まず、あなたにあなたの姓と名を入力させる単純な HTML フォームです。

+ +
<form>
+  <div>
+    <label for="fname">First name: </label>
+    <input id="fname" type="text">
+  </div>
+  <div>
+    <label for="lname">Last name: </label>
+    <input id="lname" type="text">
+  </div>
+  <div>
+     <input id="submit" type="submit">
+  </div>
+</form>
+<p></p>
+ + + +

 さあちょっとした JavaScript です — ここでは onsubmit イベントハンドラー(フォームがサブミットされるとサブミットイベントが発火します)の中で、テキストフィールドが空かどうかテストするだけのとても簡単なチェックを実装します。もし空なら、イベントオブジェクトの preventDefault() 関数— これでフォームの送信を抑制します — を呼び、それからフォームの下にあるパラグラフに、何が問題なのかユーザーに伝えるためのエラーメッセージを表示します:

+ +
const form = document.querySelector('form');
+const fname = document.getElementById('fname');
+const lname = document.getElementById('lname');
+const para = document.querySelector('p');
+
+form.onsubmit = function(e) {
+  if (fname.value === '' || lname.value === '') {
+    e.preventDefault();
+    para.textContent = 'You need to fill in both names!';
+  }
+}
+ +

言うまでもなく弱っちいフォームの検証です — 例えばフォームに空白や数字が入っていても止められません — が、例としては十分です。結果はこうなります。

+ +

{{ EmbedLiveSample('Preventing_default_behavior', '100%', 140, "", "", "hide-codepen-jsfiddle") }}

+ +
+

メモ: ソースコード全体については、preventdefault-validation.html (及び ライブ実行も) をご覧ください。

+
+ +

イベントのバブリングとキャプチャリング

+ +

ここで最後に説明していくのは、滅多には遭遇しませんが、理解できていないととても苦痛になるかもしれない事柄です。ある一つの要素で同じイベントに紐付く二つのハンドラが活性化された時に何が起きるのかを説明するのが、イベントのバブリングとキャプチャリングという二種類のメカニズムです。わかりやすくするために次の例を見てください — show-video-box.html 例を新しいタブで開いてください (ソースコード もまた別のタブに)。ライブでも下で見られます:

+ + + +

{{ EmbedLiveSample('Hidden_video_example', '100%', 500, "", "", "hide-codepen-jsfiddle") }}

+ +

これは内に {{htmlelement("video")}} 要素を含む {{htmlelement("div")}} を表示したり隠したりするとても簡単な例です。

+ +
<button>Display video</button>
+
+<div class="hidden">
+  <video>
+    <source src="rabbit320.mp4" type="video/mp4">
+    <source src="rabbit320.webm" type="video/webm">
+    <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
+  </video>
+</div>
+ +

{{htmlelement("button")}} がクリックされると、<div> のクラス属性を hidden から showing に変更するので、ビデオが表示されます(例の CSS にこの二つのクラスが含まれており、それぞれはボックスの位置をスクリーンの外、内にします)。

+ +
btn.onclick = function() {
+  videoBox.setAttribute('class', 'showing');
+}
+ +

では二つばかり onclick イベントハンドラーを追加します — 最初のは <div> に、二つ目は <video>にです。ビデオの外側の <div> 領域がクリックされた時にはボックスがまた隠れるようにし、ビデオそのものがクリックされたらビデオが再生されるようにしたいというわけです。

+ +
videoBox.onclick = function() {
+  videoBox.setAttribute('class', 'hidden');
+};
+
+video.onclick = function() {
+  video.play();
+};
+ +

が、ここで問題が — 今度はビデオをクリックすると再生が始まりますが、それと同時に<div>が隠されるようになってしまいました。ビデオが <div> の中にあるので(ビデオは div の一部ですから)、ビデオのクリックは上に挙げた両方のイベントハンドラーを実際に動かします。

+ +

バブリングとキャプチャリングの説明

+ +

親要素を持つ要素 (このケースでは {{htmlelement("video")}} です) においてイベントが発火すると、モダンブラウザーは二つの異なる段階に分けて動作します — キャプチャリングする段階とバブリングする段階です。

+ +

キャプチャリングの段階で行われることは……

+ + + +

バブリングの段階では、全く逆の事が起きます。

+ + + +

+ +

(大きな図を見るにはクリックしてください)

+ +

モダンブラウザーのデフォルトでは、全てのイベントハンドラーはバブリング段階に登録されます。ですのでこの例の場合では、ビデオをクリックするとクリックイベントは <video> 要素から外側の <html> 要素に進んで (バブリングして) いきます。従って:

+ + + +
+

: 両方のイベントハンドラーが存在する場合バブリングとキャプチャリングでは、キャプチャフェーズが最初に走り、バブリングフェーズが続きます。

+
+ +

stopPropagation()で問題を解決する

+ +

困った動作ですが、解決する方法があります! 標準的なイベントオブジェクトには stopPropagation()という関数があって、ハンドラーのイベントオブジェクトで起動されると、このハンドラーは実行されますが、イベントが上位に伝播しないようにするので、これ以上のハンドラーは実行されなくなります。

+ +

よって我々の今の問題は、先のコードブロック、第二のハンドラー関数をこのように変更して解決できます:

+ +
video.onclick = function(e) {
+  e.stopPropagation();
+  video.play();
+};
+ +

show-video-box.html ソースコードのローカルコピーを作成してみて、自分で修正してみるか、修正された結果は show-video-box-fixed.html で見ることができます (こちらでソースコードも見られます)。

+ +
+

メモ: なんだってキャプチャリングとバブリングなんてあるのか? それはね、むかーしむかしの悪き時代、ブラウザーに今ほど互換性がなかった頃、ネットスケープはキャプチャリングだけを、IE はバブリングだけを使っていたのさ。W3C が動作について標準化と合意を作ろうと決めた時、結局どっちもシステムに入れることにし、モダンブラウザーはそのように実装されたのさ。

+
+ +
+

メモ: 上で述べたように、デフォルトでイベントハンドラーはバブリング段階に登録され、そしてほとんどの場合はこれが妥当です。もし本当にイベントをキャプチャリング段階の方に登録したいのであれば、addEventListener()を使って、省略可能な第三引数に true を指定すれば実現できます。

+
+ +

イベントの移譲

+ +

バブリングではイベント移譲という機能も活用できます — イベント移譲という概念は、たくさんある子要素のどれかしらがクリックされた際に何らかのコードを実行したいという場合に、個々の子要素一つ一つにイベントリスナーを設定するのではなく、親要素のイベントリスナーを設定すれば子要素のイベントリスナーからバブリングしてくるという事実に依拠しています。

+ +

良い例としては、一連のリストアイテムです — どれかがクリックされたらメッセージをポップアップさせたいときには、親の <ul> 要素の click イベントリスナーに設定すれば、イベントはリストアイテムからバブリングしてきます。

+ +

この概念はより深く David Walsh のブログで、たくさんの例とともに解説されています。— How JavaScript Event Delegation Works を見てください

+ +

スキルをテストしよう!

+ +

この記事の最後に来ましたが、最も大事な情報を覚えていますか? 次に移動する前に、さらなるテストでこの情報を保持しているか検証できます — Test your skills: Events を見てください。

+ +

結論

+ +

ウェブイベントについて、今の学習初期段階で知るべき事は全部わかったはずです。上で述べたように、実のところイベントは JavaScript のコアには属しません — それらはブラウザーの Web API に属するものです。

+ +

また重要な事は、JavaScript の使われ方によって異なるイベントモデルがありうる事も理解しておいてください — Web API とブラウザーの WebExtension や Node.js (サーバーサイド JavaScript) のような領域とでは。今あなたがそれらの領域について理解しなくてよいと思っていますが、ウェブ開発の事を学んでいくのにイベントの基礎を理解するのが役立つのは確かです。

+ +

理解できない事があれば、気楽にまた記事を読み返したり、私達 に質問してください

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/functions/index.html b/files/ja/learn/javascript/building_blocks/functions/index.html new file mode 100644 index 0000000000..636278ee2e --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/functions/index.html @@ -0,0 +1,407 @@ +--- +title: 関数 — 再利用可能なコードブロック +slug: Learn/JavaScript/Building_blocks/Functions +tags: + - API + - Article + - Beginner + - Browser + - CodingScripting + - Custom + - Functions + - Guide + - JavaScript + - Learn + - Method + - anonymous + - invoke + - 'l10n:priority' + - parameters +translation_of: Learn/JavaScript/Building_blocks/Functions +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}
+ +

コーディングにおいて、不可欠なコンセプトが関数です。関数を使用することで、特定のタスクをこなすコードを定義し、保持しておいて、いつでも簡単なコマンドで呼び出すことを可能にしてくれます。同じコードを何度も打たなければならないよりとっても簡単です。この記事では関数の書き方や、関数を実行する方法、定義の仕方、スコープ、引数といった関数に関する基礎を学びます。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターの知識、HTML と CSS への理解、JavaScript の第一歩
目的:JavaScript の関数についての基礎を理解する。
+ +

関数はどこにありますか?

+ +

JavaScript の中で、関数はあらゆるところに見つかるでしょう。実際、これまでのところすべての場面で関数を使用してきました。これについてはあまり触れてきませんでした。しかし、今こそ明確に関数について話し始め、本当に構文を探索する時期です。

+ +

一対のかっこ — () — の機能である JavaScript の構造を使用するほとんどの場合、そして for ループwhile と do ... while ループ、または if..else 文のような一般的な組み込みの言語構造を使用していない場合、あなたは関数を使用していることになります。

+ +

ブラウザー組み込み関数

+ +

このコースではブラウザーに組込まれた関数をたくさん使ってきました。毎回テキスト文字列を操作したときには、こんな風に:

+ +
let myText = 'I am a string';
+let newString = myText.replace('string', 'sausage');
+console.log(newString);
+// the replace() string function takes a string,
+// replaces one substring with another, and returns
+// a new string with the replacement made
+ +

あるいは毎回配列を操作したときには:

+ +
let myArray = ['I', 'love', 'chocolate', 'frogs'];
+let madeAString = myArray.join(' ');
+console.log(madeAString);
+// the join() function takes an array, joins
+// all the array items together into a single
+// string, and returns this new string
+ +

また毎回乱数を作成したときには:

+ +
let myNumber = Math.random();
+// the random() function generates a random
+// number between 0 and 1, and returns that
+// number
+ +

...関数を使っていたのです!

+ +
+

メモ: これらの機能に慣れるために、必要なときにはこういった行をあなたのブラウザーの JavaScript コンソールにいつでも入力してみてください。

+
+ +

JavaScript言語にはたくさんの組込み関数があるので、いろいろあるあなたのやりたい事を、全部をあなた自身で書かなくてもすみます。実は、あなたが呼び出して起動(走らせたり実行する事の別の言い方)するコードのいくつかは、JavaScript では書けない、ブラウザー組込み関数です — こういった関数の多くは背後のブラウザーのコードを呼び出していて、これらは JavaScript のようなウェブ言語ではなく、大半が C++のような低レベルのシステム言語で書かれています。

+ +

ブラウザー関数のいくつかは JavaScript言語の核に含まれない事を心に留めておいてください — いくつかはブラウザー API の一部として定義されていて、もっと多くの機能を提供すべくデフォルトの言語の上で構築されています(詳しくは私たちのコースのこの以前のセクションを見てください)。ブラウザー API のもっと詳しい使い方については、後の方のモジュールで見ていく事になるでしょう。

+ +

関数とメソッド

+ +

オブジェクトのメソッドの一部を、プログラマーは関数として呼び出します。構成された JavaScript オブジェクト内部の働きについては、まだ知る必要はありません — この後のモジュールで、オブジェクト内部の働きや自分でオブジェクトを作る方法について教える段階になってから覚えれば大丈夫です。今のところは、ウェブのあちこちにある関連したリソースを見ていると、メソッドと関数が混在している事があるとわかってもらいたいだけです。

+ +

これまで利用してきた組込み関数は両方です: 関数でありメソッドでもあります。組み込みオブジェクトとそのメソッドと同様に、組み込み関数の一覧をこちらで確認できます。

+ +

このコースのここまででもたくさんのカスタム関数を見てきました — ブラウザーの内部でではなくあなたのコードの中で定義された関数です。独自の名前の直後にカッコがついてるものを見かけたら、それはカスタム関数を使っているという事です。繰返しの記事で出てきた random-canvas-circles.html の例(ソースコードはこちら)では、独自に作った draw() 関数が含まれていました。こんなやつです:

+ +
function draw() {
+  ctx.clearRect(0,0,WIDTH,HEIGHT);
+  for (let i = 0; i < 100; i++) {
+    ctx.beginPath();
+    ctx.fillStyle = 'rgba(255,0,0,0.5)';
+    ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
+    ctx.fill();
+  }
+}
+ +

この関数は、{{htmlelement("canvas")}} 要素の内にランダムな円を 100描きます。同じ事をやりたい時には、いつでもこんな具合に関数を起動するだけです

+ +
draw();
+ +

繰り返しをする毎に何度も同じコードを書き上げるのではなく。関数にはあなたが書きたいどんなコードでも含められます — 関数の中から他の関数を呼ぶことだってできます。例に挙げた上の関数では、random()関数を 3 回呼んでいて、random関数は以下のコードで定義されています:

+ +
function random(number) {
+  return Math.floor(Math.random()*number);
+}
+ +

ブラウザー組込みの Math.random() は 0 から 1 までの間の 10進数の乱数を作成するだけなので、私たちにはこの関数が必要でした。私たちは 0 から指定した数にわたる乱数が欲しかったのです。

+ +

関数の呼び出し

+ +

もうよくご存知でしょう、でも念のため … 定義した後で実際に関数を使うには、関数を走らせ — あるいは起動し — なければなりません。これはコードのどこかに関数の名前、直後にカッコの組を書けばできます。

+ +
function myFunction() {
+  alert('hello');
+}
+
+myFunction();
+// calls the function once
+ +

匿名関数

+ +

ちょっと違う形式で定義されて起動される関数を見かける事があるでしょう。ここまでは関数をこのように作ってきました:

+ +
function myFunction() {
+  alert('hello');
+}
+ +

でも名前のない関数を作る事もできます:

+ +
function() {
+  alert('hello');
+}
+ +

これは匿名関数と呼ばれます — 名前がないんです! それだけでは何もしません。匿名関数はよくイベントハンドラで使われていて、例えば以下では関連づけられたボタンがクリックされるたび、関数の中のコードが走ります:

+ +
const myButton = document.querySelector('button');
+
+myButton.onclick = function() {
+  alert('hello');
+}
+ +

上の例では、ページの中に選択してクリックするための{{htmlelement("button")}}要素が存在しなければならないでしょう。あなたはこのような例をここまでのコースで見てきましたし、ここから先の記事でもっと学習し、使い方を見ていく事になります。

+ +

匿名関数を変数の値として代入する事もできます:

+ +
const myGreeting = function() {
+  alert('hello');
+}
+ +

この関数は次のように起動できます:

+ +
myGreeting();
+
+ +

関数に名前をつけたような効果があります。また関数を複数の変数の値として代入する事もできます:

+ +
let anotherGreeting = myGreeting;
+ +

結果、この関数はどちらの方法でも起動できます

+ +
myGreeting();
+anotherGreeting();
+ +

ですがこれは混乱するだけなので、やらないように! 関数を作成するときはこの形式でやった方が良いです:

+ +
function myGreeting() {
+  alert('hello');
+}
+ +

匿名関数は主にイベント発火 — ボタンがクリックされたとか — のレスポンスとして、一連のコードを走らせるだけのような場合に、イベントハンドラとして使われます。くりかえしですが、こんな具合です:

+ +
myButton.onclick = function() {
+  alert('hello');
+  // I can put as much code
+  // inside here as I want
+}
+ +

関数の引数

+ +

関数には実行する時に引数が必要なものがあります — 関数のカッコとカッコの間に書かなければならない値で、関数が正しい仕事をするのに必要とされます。

+ +
+

メモ: 引数は、パラメーター、プロパティ、アトリビュート(属性)などと呼ばれる場合もあります。

+
+ +

例えばブラウザー組込み関数 Math.random() は引数を必要としません。呼ばれるといつも 0 から 1 までの乱数を返します:

+ +
let myNumber = Math.random();
+ +

ですがブラウザー組込みの文字列関数 replace() は二つの引数が必要です — 主文字列から探すべき部分文字列と、部分文字列を置換する文字列です:

+ +
let myText = 'I am a string';
+let newString = myText.replace('string', 'sausage');
+ +
+

メモ: 複数の引数を指定するときは、カンマで区切って書きます

+
+ +

引数には省略可能 — 書かなくても良い — なものもある事に触れておくべきでしょう。省略された場合、関数はだいたいデフォルトに規定された動作を行ないます。例えば、配列の join() 関数のパラメータは省略可能です:

+ +
let myArray = ['I', 'love', 'chocolate', 'frogs'];
+let madeAString = myArray.join(' ');
+// returns 'I love chocolate frogs'
+let madeAString = myArray.join();
+// returns 'I,love,chocolate,frogs'
+ +

もし結合/区切り文字を指定する引数が省略された場合、デフォルトとしてカンマが使われます。

+ +

関数のスコープと競合

+ +

{{glossary("スコープ")}}という言葉について説明しておきましょう — 関数を扱う際にはとても大切な概念です。関数を作成するとき、関数の中で定義されている変数や関数は、内部でそれぞれ独自のスコープというものを持ちます。これはそれぞれが独自の小部屋に閉じ込められていて、別の関数の内部から、あるいはこの関数の外部のコードから触れられくなる事を意味しています。

+ +

あなたのすべての関数の外側、一番の外側を、グローバルスコープと呼びます。グローバルスコープで定義された値はすべて、コードのどこからでもアクセスできます。

+ +

JavaScript がこう作られているのにはいくつも理由があります — が、主な理由はセキュリティと組織化のためです。時には変数にコードのどこからでもアクセスされないようにしたい場合もあるでしょう — どこかから呼び込んだ外部スクリプトが、あなたのコードをおかしくして問題を起す場合があるかもしれません。別の場所でたまたま同じ名前の変数を使っていて、衝突していたために。これは悪意をもってわざとやっている場合や、単なる偶然の場合もあります。

+ +

そうですね、例えばある HTML ファイルが二つの外部 JavaScript ファイルを呼び出しているとして、そのどちらも同じ名前の変数と関数を定義しているとします:

+ +
<!-- Excerpt from my HTML -->
+<script src="first.js"></script>
+<script src="second.js"></script>
+<script>
+  greeting();
+</script>
+ +
// first.js
+let name = 'Chris';
+function greeting() {
+  alert('Hello ' + name + ': welcome to our company.');
+}
+ +
// second.js
+let name = 'Zaptec';
+function greeting() {
+  alert('Our company is called ' + name + '.');
+}
+ +

あなたが呼び出したいのはどっちも greeting()関数ですが、あなたには first.js ファイルの greeting() 関数しかアクセスできません(2 つ目は無視されます)。加えて、second.js ファイルで let キーワードで name 変数に 2度目の定義をしようとするとエラーになります。

+ +
+

: この例を GitHub でライブ実行 できます(ソースコードはこちら).

+
+ +

あなたのコードの部品を関数の中に隔離するとこのような問題を避けられるので、これが一番良いやりかたと考えられています。

+ +

これは動物園みたいなものです。ライオン、シマウマ、トラ、ペンギンはそれぞれの檻の中にいて、それぞれの檻の中のものにしか触れられません — 関数のスコープと同じ事です。もし彼等が他の檻の中に侵入できたら問題が起きることでしょう。良くて、知らない住人に囲まれて気まずい思いをする — 寒くて水だらけのペンギンの檻に入ったライオンやトラは酷い気分になるでしょう。最悪の場合、ライオンやトラはペンギンを食べてみようとするかも!

+ +

+ +

動物園の管理人はグローバルスコープみたいなものです — 管理人はすべての檻の鍵を持っていて、エサを補充し、動物にうんざりし、などなど。

+ +

アクティブラーニング:  スコープで遊んでみよう

+ +

スコープを示すための実際の例を見てみましょう。

+ +
    +
  1. まず function-scope.html の例のローカルコピーを作成します。これには a()b() という 2 つの関数と、xyz の 3 つの変数が含まれます。これらの変数のうち 2 つは関数内で定義され、もう 1 つはグローバルスコープ内で定義されます。また output() という 3番目の関数も含まれています。この関数は単一のパラメータを取り、ページの段落に出力します
  2. +
  3. ブラウザーとテキストエディターでサンプルを開きます
  4. +
  5. ブラウザーの開発者ツールで JavaScript コンソールを開きます。JavaScript コンソールで、次のコマンドを入力します。 +
    output(x);
    + 変数x の出力値が画面に表示されるはずです。
  6. +
  7. コンソールに次のように入力してみてください +
    output(y);
    +output(z);
    + どちらも、"ReferenceError: y is not defined"の一行のエラーが返されるはずです。なぜでしょうか? 関数スコープのため、つまり yza()b() 関数の中でロックされているので、global スコープから呼び出されたときには output() はそれらにアクセスできません。
  8. +
  9. しかし、別の関数の中から呼び出されたときはどうでしょうか? a()b() を次のように編集してみてください: +
    function a() {
    +  let y = 2;
    +  output(y);
    +}
    +
    +function b() {
    +  let z = 3;
    +  output(z);
    +}
    + コードを保存してブラウザーに再ロードしてから、JavaScript コンソールから a()b() 関数を呼び出してみてください。 + +
    a();
    +b();
    + ページに yz の値の出力が表示されます。output() 関数が他の関数の中、つまり表示される変数が定義されているのと同じスコープでそれぞれ呼び出されているので、これはうまくいきます。output() 自体はグローバルスコープで定義されているので、どこからでも利用できます。
  10. +
  11. 今度は次のようにコードを更新してみてください: +
    function a() {
    +  let y = 2;
    +  output(x);
    +}
    +
    +function b() {
    +  let z = 3;
    +  output(x);
    +}
    + 保存してもう一度読み込み、JavaScript コンソールでもう一度試してみてください:
  12. +
  13. +
    a();
    +b();
    + a()b() の両方の呼び出しは x の値、つまり 1 が出力されます。これは x がグローバル変数であり、すべてのコード内どこでも利用可能であるため、output() の呼び出しが x と同じスコープではなくてもうまく動きます。
  14. +
  15. 最後に、次のようにコードを更新してみてください: +
    function a() {
    +  let y = 2;
    +  output(z);
    +}
    +
    +function b() {
    +  let z = 3;
    +  output(y);
    +}
    + 保存してもう一度読み込み、JavaScript コンソールでもう一度試してみてください:
  16. +
  17. +
    a();
    +b();
    + 今度は a()b() の両方の呼び出しで、迷惑な "ReferenceError: variable name is not defined" エラーが返されます — これは output() 呼び出しと、出力しようとしている変数が同じ関数のスコープにない、つまりこれらの関数呼び出しからは変数が参照できない状態だからです。
  18. +
+ +
+

: 同じスコープルールはループ (for() { ... } など) と条件ブロック (if() { ... }など) には適用されません。それらは非常によく似ていますが、同じものではありません。混乱しないように注意してください。

+
+ +
+

: ReferenceError: "x" is not defined というエラーは、あなたが遭遇する最も一般的なエラーの 1 つです。このエラーが発生し、問題の変数が定義されていると確信できる場合は、変数のスコープを確認してください。

+
+ + + +

関数の中の関数

+ +

別の関数内であっても、どこからでも関数を呼び出すことができます。これは、コードをきれいにする方法としてよく使われます。大きな複雑な関数がある場合は、いくつかのサブ関数に分解すれば分かります。

+ +
function myBigFunction() {
+  let myValue;
+
+  subFunction1();
+  subFunction2();
+  subFunction3();
+}
+
+function subFunction1() {
+  console.log(myValue);
+}
+
+function subFunction2() {
+  console.log(myValue);
+}
+
+function subFunction3() {
+  console.log(myValue);
+}
+
+ +

関数内で使用されている値が適切にスコープ内にあることを確認してください。上記の例では ReferenceError: myValue is not defined というエラーが発生します。myValue変数は関数呼び出しと同じスコープで定義されていますが、関数定義内では定義されていないためです。従って実際のコードは関数が呼び出されたときに実行されます。これを動くようにするには、次のように関数に値を渡す必要があります。

+ +
function myBigFunction() {
+  let myValue = 1;
+
+  subFunction1(myValue);
+  subFunction2(myValue);
+  subFunction3(myValue);
+}
+
+function subFunction1(value) {
+  console.log(value);
+}
+
+function subFunction2(value) {
+  console.log(value);
+}
+
+function subFunction3(value) {
+  console.log(value);
+}
+ +

スキルをテストしよう!

+ +

この記事の最後に来ましたが、最も大事な情報を覚えていますか?次に移る前に、この情報を保持しているか検証するテストがあります — Test your skills: Functions を見てください。このテストは次の 2 つの記事でカバーしているスキルを求めていますので、テストの前にそちらを読むほうが良いかもしれません。

+ +

まとめ

+ +

この記事では関数の背後にある基本的な概念を探り、次に実用的な方法を習得し、独自のカスタム関数を構築する手順を紹介しました。

+ +

関連情報

+ + + + + +

{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/image_gallery/index.html b/files/ja/learn/javascript/building_blocks/image_gallery/index.html new file mode 100644 index 0000000000..2c8dc3c470 --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/image_gallery/index.html @@ -0,0 +1,142 @@ +--- +title: イメージギャラリー +slug: Learn/JavaScript/Building_blocks/Image_gallery +tags: + - Assessment + - Beginner + - CodingScripting + - Conditionals + - Event Handler + - JavaScript + - Learn + - Loops + - events +translation_of: Learn/JavaScript/Building_blocks/Image_gallery +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}
+ +

JavaScript の基本的な構成要素を見てきたところで、これからたくさんのウェブサイトで見かける項目、JavaScript で動作するイメージギャラリーをつくってみることで、あなたが得た繰り返し、関数、条件とイベントの知識を試してみましょう。

+ + + + + + + + + + + + +
前提条件:この評価を行う前に、このモジュールにある記事すべてを実施していること。
目標:JavaScript の繰り返し、関数、条件とイベントが理解できていることを確認する。
+ +

出発点

+ +

この評価を始めるために、サンプルが入っているサイトから ZIP ファイル を取得して、コンピュータのどこかに展開しておきます。

+ +
+

: 別の方法として, この評価を行うために JSBin や Thimble のようなサイトを使うことができます。これらのオンラインエディターに HTML、CSS、JavaScript を貼り付けることができます。利用するオンラインエディターが JavaScript/CSS パネルに分かれていなければ、 HTML ページの中の <script>/<style> 要素にそれらを貼り付けてください 。

+
+ +

プロジェクト概要

+ +

HTML、CSS と画像および数行の JavaScript のコードが提供されています。必要な JavaScript を書いて、これを動くプログラムにする必要があります。HTML のボディは次のようになっています:

+ +
<h1>Image gallery example</h1>
+
+<div class="full-img">
+  <img class="displayed-img" src="images/pic1.jpg">
+  <div class="overlay"></div>
+  <button class="dark">Darken</button>
+</div>
+
+<div class="thumb-bar">
+
+</div>
+ +

例ではこのように見えます:

+ +

+ + + +

例にある CSS ファイルで最も興味深い部分:

+ + + +

JavaScriptに必要なもの:

+ + + +

もっとアイデアを加えると、最終的な例 のようになります (ソースコードをのぞかないように!)

+ +

完成へのステップ

+ +

次のセクションですべきことを説明します。

+ +

画像をループさせる

+ +

すでに thumbBar という変数に thumb-bar <div> の参照を格納するようにしています。新しい <img> 要素を作って、その src 属性にプレースホルダーとして値 xxx をセットしてください。そして、新しい <img> 要素を thumbBar に追加してください。

+ +

必要なこと:

+ +
    +
  1. "Looping through images" コメントの下のセクションのコードを全 5 画像をループする繰り返し処理のなかに置いて下さい — 各画像を表現する5つの数についてループするだけです。
  2. +
  3. 各ループの反復で、プレースホルダー xxx の値を画像のパスに等しい文字列で置き換えてください。それぞれの場合で src 属性の値をこの値に設定します。いずれの場合も画像は画像ディレクトリーにあり、pic1.jpgpic2.jpg というようなファイル名になっています。
  4. +
+ +

onclick ハンドラーをそれぞれのサムネール画像に追加する

+ +

各ループの反復で、現在の newImageonclick ハンドラーを追加する必要があります — このハンドラは現在の画像の src 属性の値を見つけます。displayed-img <img>src 属性の値をパラメータとして渡されたものの src 値へ設定します。

+ +

替わりに、サムネイルバーへ一つのイベントリスナーを追加することも出来ます。

+ +

暗くする/明るくするボタンを処理するハンドラーを書く

+ +

暗くする/明るくする <button> が残っています。btn という変数に <button>  への参照を格納するコードはすでにご紹介しています。それらに onclick ハンドラーに追加する必要があります:

+ +
    +
  1. <button> にセットされている現在のクラス名をチェックしますーこれもまた、getAttribute() を使えば取得できます。
  2. +
  3. クラス名が "dark" なら、<button> のクラスを (setAttribute() を使って) "light" に変更します。テキストも "Lighten" にします。そして、オーバーレイ <div> の {{cssxref("background-color")}} を "rgba(0,0,0,0.5)" にします。
  4. +
  5. クラス名が "dark" でなければ、<button> のクラスを "dark" に変更します。テキストを "Darken" に戻します。そしてオーバーレイ <div> の {{cssxref("background-color")}} を "rgba(0,0,0,0)" にします。
  6. +
+ +

次のコードは上記の 2 と 3 で示された変更を行う基本的なものです。

+ +
btn.setAttribute('class', xxx);
+btn.textContent = xxx;
+overlay.style.backgroundColor = xxx;
+ +

ヒントとコツ

+ + + +

課題

+ +

組織されたコースの一部としてこの評価を行う場合、採点のため先生/メンターにあなたの成果を提出してください。もし、自習なら、このエクササイズに関するディスカッションのスレッドMozilla IRC#mdn IRC チャネルで尋ねれば、採点ガイドが簡単に得られるでしょう。まずエクササイズに挑戦してください。ーごまかしても何も得られません!

+ +

{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/index.html b/files/ja/learn/javascript/building_blocks/index.html new file mode 100644 index 0000000000..74ec4ff45f --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/index.html @@ -0,0 +1,56 @@ +--- +title: JavaScript の構成要素 +slug: Learn/JavaScript/Building_blocks +tags: + - Article + - Assesment + - Beginner + - CodingScripting + - Conditionals + - Functions + - Guide + - JavaScript + - Landing + - Loops + - Module + - events + - 'l10n:priority' +translation_of: Learn/JavaScript/Building_blocks +--- +
{{LearnSidebar}}
+ +

このモジュールでは、条件付きステートメント、ループ、関数、イベントなど一般的に発生するコードブロックの種類に注目し、JavaScript の重要な基本機能をすべてカバーしていきます。コースの中で既にこれらを目にしているのですが、説明を省いてきました。ここではすべて明示的に説明を行います。

+ +

前提条件

+ +

このモジュールを始める前に、HTMLCSS の基本に慣れておくべきです。また前のモジュールの JavaScript の第一歩 も終了させておくべきです。

+ +
+

注記 : もしあなたが作業しているコンピュータ・タブレットやその他のデバイスで自分でファイルを作れない場合は、JSBinGlitch といったようなオンラインコーディングプログラムで (ほとんどの場合) 試すことができます。

+
+ +

ガイド

+ +
+
コード内で決定を下す — 条件
+
どんなプログラミング言語でも、コードは異なる入力に応じて決定を下し、それに応じてアクションを実行する必要があります。例えば、ゲームではもしプレイヤーのライフが 0 だった場合、ゲームオーバーになります。お天気アプリでは、朝に見た場合には朝日の画像を表示し、夜に見た場合には星と月を表示します。この記事では、条件の構造が JavaScript でどのように機能するかを説明します。
+
ループコード
+
場合によっては、一度にタスクを複数回実行しなければならないことがあります。 例えば名前のリスト全体を調べる場合です。プログラミング時に、ループはこのような処理を非常にうまく実行します。ここでは JavaScript のループ構造を見ていきます。
+
関数 — 再利用可なコードブロック
+
コーディングのもう一つの重要な概念は関数です。 関数を使用すると、定義されたブロック内に単一のタスクを実行するコードを格納し、同じコードを複数回入力するのではなく、単一の短いコマンドを使用して必要となる時にコードを呼び出すことができます。この記事では、基本的な構文、関数、スコープ、パラメータを呼び出す方法と定義する方法など、関数の背後にある基本的な概念について説明します。
+
独自の関数を構築する
+
前の記事で扱った必須の理論の多くを用いて、この記事では実用的な体験を提供しています。ここでは、独自のカスタム関数を構築するための練習をします。 また進むにつれ、関数を扱うためのさらに便利な詳細についても説明します。
+
関数の戻り値
+
関数について知っておくべき最後の必須コンセプトは戻り値です。一部の関数は完了後に意味のある値を返しませんが、他の関数は返します。値が何であるか、コードでそれらを使用する方法、独自のカスタム関数で有用な値を返す方法を理解することが重要です。
+
イベントへの入門
+
イベントとは、プログラミング中のシステムで発生するアクションまたは事象のことで、システムによって通知され、必要に応じて何らかの方法で応答できるようにするものです。例えば、ユーザが Web ページ上のボタンをクリックすると、情報ボックスを表示することでそのアクションに応答することができます。この最後の記事では、イベントを取り巻くいくつかの重要な概念について説明し、それらがブラウザでどのように機能するかを見ていきます。
+
+ +

評価

+ +

以下の評価は、上のガイドで取り上げた JavaScript の基礎についての理解をテストします。

+ +
+
イメージギャラリー
+
JavaScript の基本的な構成要素を見てきましたので、JavaScript で動く画像ギャラリーという、多くの Web サイトで見ることができるかなり一般的なアイテムを構築することで、ループ、関数、条件文、イベントに関する知識をテストします
+
diff --git a/files/ja/learn/javascript/building_blocks/looping_code/index.html b/files/ja/learn/javascript/building_blocks/looping_code/index.html new file mode 100644 index 0000000000..dd5e724fca --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/looping_code/index.html @@ -0,0 +1,933 @@ +--- +title: ループコード +slug: Learn/JavaScript/Building_blocks/Looping_code +tags: + - Article + - Beginner + - CodingScripting + - DO + - Guide + - JavaScript + - Learn + - Loop + - break + - continue + - for + - 'l10n:priority' + - while +translation_of: Learn/JavaScript/Building_blocks/Looping_code +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}
+ +

プログラミング言語は、繰り返し実行するタスクを素早く終わらせるのがとても得意です。基本的な計算処理から、同じような作業がたくさんあるのならどんな状況でもこなします。今度は JavaScript でそういった目的を果たすために使用するループ構造を見てみましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターの知識および HTML と CSS への理解、JavaScript の第一歩
目的:JavaScript でループの使い方を理解する。
+ +

ループの中にとどまる

+ +

ループ、ループ、ループ。朝食用シリアルや、ジェットコースター音楽でもおなじみですが、プログラミングにおいても、とても重要な概念です。プログラミングにおけるループとは同じことを何度も何度も繰り返すことで、反復繰り返しとも言われます。

+ +

それでは、農家のケースについて考えてみましょう。彼は家族を養うため十分な食料があるか確認しようとしています。それを実現するため、以下のようなループを使用するでしょう。

+ +


+

+ +

ループにはたいてい以下のような機能があります。

+ + + +

{{glossary("pseudocode", "疑似コード")}}では、以下のようになるでしょう。

+ +
loop(food = 0; foodNeeded = 10) {
+  if (food >= foodNeeded) {
+    exit loop;
+    // 十分な食料が集まりました。家に帰りましょう
+  } else {
+    food += 2; // 1 時間経って 2 つの食料を集めました
+    // ループはさらに続きます
+  }
+}
+ +

最初に、必要な食料が 10 に設定され、農家が現在持っている食料は 0 に設定されます。ループの繰り返しごとに、農家の持っている食料が必要な食料の数に等しいかを調べています。もしそうであれば、ループを抜けられます。そうでなければ、農家は 1 時間ごとに 2 つの食料を集めるのを繰り返します。

+ +

どうしてこんなことをするの?

+ +

これで、恐らくループの背後にあるコンセプトが理解できたことでしょう。けれど、「それが JavaScript のコードを書くのにどう役立つの?」と思っているかもしれませんね。先ほどループは同じことを繰り返すことだと言いいましたが、それは素早く繰り返し同じ作業を完了させるのに最適なことなのです。

+ +

たいてい、コードはループの連続する反復のたびごとにわずかに異なるものになります。つまり、似ているけれどわずかに異なる多数のタスク全体を完了出来るのです。もしたくさんの異なる計算をしなければならないとしたら、同じことを何度も何度もするのではなく、それぞれ異なることをしたいですよね。

+ +

ループがどれだけ素晴らしいものかを説明する例を見てみましょう。100 個のランダムな円を {{htmlelement("canvas")}} 要素に描きたいとします (更新ボタンを押して、例を何度となく実行し、結果が異なることを見てみましょう。)

+ + + +

{{ EmbedLiveSample('Hidden_code', '100%', 400, "", "", "hide-codepen-jsfiddle") }}

+ +

今はコードをすべて理解する必要はありません。ですが、コードの一部で 100 個の円を実際に描いている箇所を見てみましょう。

+ +
for (let i = 0; i < 100; i++) {
+  ctx.beginPath();
+  ctx.fillStyle = 'rgba(255,0,0,0.5)';
+  ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
+  ctx.fill();
+}
+ + + +

基本的な考えがわかりましたか?このコードをループを使用して 100 回実行しますが、毎回ページ内のランダムな場所に円を描いています。必要なコードは 100 個の円を描くときも、1000 個でも 10,000 個でも同じです。1 か所だけ変更すればいいのです。

+ +

ここでループを使用しないとすれば、次のコードを描きたい数だけ繰り返し書かなければなりません。

+ +
ctx.beginPath();
+ctx.fillStyle = 'rgba(255,0,0,0.5)';
+ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
+ctx.fill();
+ +

これはとてもつまらなく、素早くメンテナンスするのが難しいコードです。ループが一番良いです。

+ +

標準的な for ループ

+ +

ここからは、具体的なループの構造を見ていきましょう。最初は、特によく使うことになるであろう for ループについてです。構文は以下の通りです。

+ +
for (初期化処理; 条件; 最後の式) {
+  // 実行するコード
+}
+ +

ここでは...

+ +
    +
  1. for キーワードに続き括弧があります。
  2. +
  3. 括弧の中にはセミコロンで区切られて以下の項目があります。 +
      +
    1. 初期化処理: これはたいていの場合、繰り返し回数分増やしていく変数の初期化処理となります。この変数をカウンター変数と呼ぶことがあります。
    2. +
    3. 条件: 既に取り上げた通り、これはループが繰り返しをやめるべき条件を定義します。ほとんどの場合は比較演算子を伴って、終了条件を満たしているかを判定します。
    4. +
    5. 最後の式: これはループの 1 回が終了する度に評価される (または実行される) コードです。大体、カウンター変数を増やし(または減らし)、条件が true では無くなるポイントに近づけていきます。
    6. +
    +
  4. +
  5. そして中括弧があり、中括弧の中のコードブロックが各ループの繰り返しで実行されます。
  6. +
+ +

それでは実際の例を見て、これらを明確に分かるようにしてみましょう。

+ +
const cats = ['ビル', 'ジェフ', 'ピート', 'ビッグルズ', 'ジャスミン'];
+let info = '私の猫の名前は、';
+const para = document.querySelector('p');
+
+for (let i = 0; i < cats.length; i++) {
+  info += cats[i] + '、';
+}
+
+para.textContent = info;
+ +

これで次の結果が得られます。

+ + + +

{{ EmbedLiveSample('Hidden_code_2', '100%', 60, "", "", "hide-codepen-jsfiddle") }}

+ +
+

このコードは GitHub でも見られます (動くデモもありますよ)。

+
+ +

これは配列のすべての要素に対して、繰り返し何かを実行するループの使用例です。JavaScript ではとてもよく見られるパターンです。

+ +
    +
  1. i をカウンター変数(イニシャライザーやイテレーター変数ともいう)として、0 から開始します (let i = 0)。
  2. +
  3. icats 配列の長さより小さくなくなるまで実行すると、ループには指定されています。これは重要です、条件にはループが継続するための条件が示されています。今回は、i < cats.length が真となるため、ループは継続します。
  4. +
  5. ループの内側では、現在繰り返し対象となる項目 (cats[i] は cats[i に入っているそのときの値] となります) を info 変数に対してカンマとスペースとともに結合しています。つまり... +
      +
    1. 初回の実行時には、i = 0 なので cats[0] + ', ' ("ビル、") が info に対して結合されます。
    2. +
    3. 2 回目の実行時には、i = 1 なので cats[1] + ', ' ("ジェフ、") が info に対して結合されます。
    4. +
    5. このように、ループ内の処理が実行されるたび、1 が i に加算され (i++)、次の処理が開始されます。
    6. +
    +
  6. +
  7. icats.length の値 (ここでは 5) と等しくなったときにループは終了し、ブラウザーはループの後に続くコードを実行します。
  8. +
+ +
+

: 条件を i <= cats.length ではなく、i < cats.length としているのは、コンピューターが数値を 1 からではなく、0 から数えるためです。コードでも i0 から始め、i = 4 (配列内の要素の最後のインデックス) となるまで加算していきます。配列内の要素が 5 つなので  cats.length は 5 となりますが、i = 5 とすると、(配列に 5 のインデックスの要素がないので) undefined となってしまいます。なので、cats.length と同じ値まで (i <=) ではなく、i の最大値を 1 減らして cats.length より小さくなる (i <) まで加算しています。

+
+ +
+

: 条件の指定でよくある間違いは「以下」(<=) ではなく、「等しい」(===) を使ってしまうことです。もし、i = 5 となるまでループを実行したければ、終了条件は i <= cats.length と指定しなければなりません。i === cats.length と指定した場合、ループは 1 度も実行されずに終了してしまいます。なぜなら、ループの最初では i5 ではないため、そこで終わってしまうからです。

+
+ +

残る小さな問題は、出力された文が完全ではないことです。

+ +
+

私の猫の名前は、ビル、ジェフ、ピート、ビッグルズ、ジャスミン、

+
+ +

ループの最後の結合処理を変更して文の最後が「、」で終わらないようにしたいと思います。まったく問題ありません。ループの中に条件ブロックを挿入して、これに対処しましょう。

+ +
for (let i = 0; i < cats.length; i++) {
+  if (i === cats.length - 1) {
+    info += cats[i] + 'です。';
+  } else {
+    info += cats[i] + '、';
+  }
+}
+ +
+

: このコードは GitHub でも見られます (動いているデモもあります)。

+
+ +
+

重要: for ループ (他のループも同様) では、カウンター変数を増加、もしくは場合により減少させて、最終的に条件が true では無くなるポイントに達するようにする必要があります。もしそうで無い場合、ループは永遠に回り続け、ブラウザーが強制的に停止するか、クラッシュしてしまうでしょう。これは無限ループといいます。

+
+ +

break でループを終了する

+ +

すべての繰り返し処理が終了する前にループを終了したいとき、break 文を使用して終了させることができます。前回の記事、switch 文で、入力した値が switch 文の case にマッチしたとき、switch 文を抜け、それ以降のコードを実行するために break 文を使用しました。 

+ +

これはループでも同様で、break 文を使用することで即時にループを抜けて、ブラウザーに続きのコードを実行させることができます。

+ +

それでは、連絡先 (電話番号を持っている) の配列の中から特定の連絡先を検索してみましょう。まずは HTML です。検索するテキスト入力用の {{htmlelement("input")}} 要素と、検索内容を送信 (submit) する {{htmlelement("button")}} 要素、検索結果を表示する {{htmlelement("p")}} 要素を備えます。

+ +
<label for="search">連絡先の名前: </label>
+<input id="search" type="text">
+<button>検索</button>
+
+<p></p>
+ +

現在の JavaScript について:

+ +
const contacts = ['クリス:2232322', 'サラ:3453456', 'ビル:7654322', 'メアリー:9998769', 'ダイアン:9384975'];
+const para = document.querySelector('p');
+const input = document.querySelector('input');
+const btn = document.querySelector('button');
+
+btn.addEventListener('click', function() {
+  let searchName = input.value.toLowerCase();
+  input.value = '';
+  input.focus();
+  for (let i = 0; i < contacts.length; i++) {
+    let splitContact = contacts[i].split(':');
+    if (splitContact[0].toLowerCase() === searchName) {
+      para.textContent = splitContact[0] + ' の電話番号は ' + splitContact[1] + ' です。';
+      break;
+    } else {
+      para.textContent = '連絡先が見つかりません。';
+    }
+  }
+});
+ + + +

{{ EmbedLiveSample('Hidden_code_3', '100%', 100, "", "", "hide-codepen-jsfiddle") }}

+ +
    +
  1. コードの先頭で、いくつか変数を宣言しています。その中に、連絡先の情報を持った配列があり、各要素は名前と電話番号をコロンで区切った文字列となっています。
  2. +
  3. 次に、ボタン (btn) にイベントリスナーを設定しています。ボタンが押されたときに検索結果が戻ってくるようになっています。
  4. +
  5. テキスト入力欄に入力された値を searchName という変数に格納してから、次の検索に備え、入力欄をクリアし、フォーカスを設定しています。検索に大文字小文字を気にしないよう、文字列に toLowerCase() を実行しているのに注意してください。
  6. +
  7. ここからが本題の for ループです。 +
      +
    1. カウンター変数を 0 から始め、contacts.length より小さくなくなるまで、ループの繰り返しの度に i を 1 増やしていきます。
    2. +
    3. ループの内側では、まず現在の連絡先 (contacts[i]) をコロンの文字で分割し、splitContact という配列に格納します。
    4. +
    5. それから、条件文を用いて、splitContact[0] (連絡先の名前) が入力された searchName にまた toLowerCase() を使って小文字化したものと等しいかを判定します。もし等しければ、連絡先の電話番号を段落 ({{htmlelement("p")}} 要素) に表示し、break を使用してループを終了しています。
    6. +
    +
  8. +
  9.   (contacts.length-1) 回目の繰り返しの後に、もし連絡先の名前が入力された検索語に一致しなければ、段落に「連絡先が見つかりません。」という文字列を表示し、条件が true では無くなるまでループを継続します。
  10. +
+ +
+

: すべてのソースは GitHub で見ることができます (動いているデモもあります)。

+
+ +

continue で繰り返しをスキップする

+ +

continue 文は break と同じような動作をします。けれど、ループを完全に抜けてしまうのではなく、次の繰り返しまで飛ばします。それでは、今度は入力として数値を受け取り、その数以下で整数の平方である値のみを返すという例を見てみましょう。

+ +

HTML は基本的に先ほどの例と同様で、1 つのテキストボックスと出力用の段落があります。JavaScript もループ自体を除けばほぼ同じですので、違う部分のみを示します。

+ +
let num = input.value;
+
+for (let i = 1; i <= num; i++) {
+  let sqRoot = Math.sqrt(i);
+  if (Math.floor(sqRoot) !== sqRoot) {
+    continue;
+  }
+
+  para.textContent += i + ' ';
+}
+ +

出力結果はこちらです。

+ + + +

{{ EmbedLiveSample('Hidden_code_4', '100%', 100, "", "", "hide-codepen-jsfiddle") }}

+ +
    +
  1. 今回の入力内容は数値 (num) です。for ループには、カウンターの初期値として、(今回は 0 ではなく) 1 が与えられ、終了する条件としてカウンターが入力値 (num) より大きくなった場合と指定されており、イテレーターとして、カウンターに 1 ずつ加算するよう指定されています。
  2. +
  3. ループ内部では、各値の平方根を Math.sqrt(i) を使用して求め、求めた平方根を切り捨てた値が、切り捨てる前の平方根と等しいかどうかを調べています (切り捨てには Math.floor() に任意の数値を渡します)。
  4. +
  5. もし、平方根と切り捨てた数値が等しくないのなら (!==)、平方根は整数ではないことを示しています。整数以外には興味がありませんので、continue 文を用いて、その数値をどこにも保持することなく、次のループの繰り返しまでスキップします。
  6. +
  7. もし、その平方根が整数値であるならば、if ブロックは飛ばされるので、continue 文は実行されません。代わりに、現在の i の値を段落の内容の後ろにスペースと一緒に結合します。
  8. +
+ +
+

: すべてのソースは GitHub でも見ることができます (動いているデモもあります)。

+
+ +

while と do ... while

+ +

for は JavaScript で利用可能な唯一のループのタイプではありません。実際には多くのものがありますが、これらのすべてを理解する必要はありませんが、仕事の同じ機能をわずかに異なる方法で認識できるように、他のものの構造を見ておく価値があります。
+
+ まず、while ループを見てみましょう。このループの構文は次のようになります。

+ +
初期化処理
+while (条件) {
+  // 実行するコード
+
+  最後の式
+}
+ +

これは for ループとよく似ていますが、初期化条件はループの前に設定され、最後の式は実行するコードの後のループ内に含まれます。これら二つの項目は丸括弧の中に含まれません。条件は、for ではなく while キーワードが前に付いた括弧内に含まれています。
+
+ for ループにもある3つの項目が、for ループとおなじ順序で定義されています。これは理にかなっています。条件が true では無くなるポイントに達したかどうかを確認する前に初期化処理を定義する必要があります ; ループ内のコードが実行された後(1回の繰り返しの完了)、最期の式が実行されます。これは、条件がまだ true である場合にのみ発生します。
+
+ 猫のリストの例をもう一度見てみましょう。ただし、while ループを使うように書き直してみましょう:

+ +
let i = 0;
+
+while (i < cats.length) {
+  if (i === cats.length - 1) {
+    info += 'and ' + cats[i] + '.';
+  } else {
+    info += cats[i] + ', ';
+  }
+
+  i++;
+}
+ +
+

: これは期待どおりに動作します。GitHub でライブ実行してみてください(完全なソースコードを見ることもできます)。

+
+ +

do ... while ループは非常によく似ていますが、while構造にはバリエーションがあります。

+ +
初期化処理
+do {
+  // 実行するコード
+
+  最後の式
+} while (条件)
+ +

この場合、初期化処理は、ループが始まる前に、再び最初に来ています。キーワードは、実行するコードと最期の式を含む中括弧の直前にあります。

+ +

ここでの違いは、条件がほかの全ての後にあり、括弧で囲まれ、その前に while キーワードが付いていることです。do...while ループでは、中括弧内のコードは、チェックが再度実行されるかどうかを確認する前に常に 1 回実行されます (while と for の場合、チェックが最初に来るため、コードは実行されない可能性があります) 。
+
+ do...while ループを使用するように、猫のリストの例をもう一度書き直してみましょう:

+ +
let i = 0;
+
+do {
+  if (i === cats.length - 1) {
+    info += 'and ' + cats[i] + '.';
+  } else {
+    info += cats[i] + ', ';
+  }
+
+  i++;
+} while (i < cats.length);
+ +
+

: 再度、これは期待どおりに動作します。GitHub でライブ実行してみてください(完全なソースコードを見ることもできます)。

+
+ +
+

重要: while と do ... while では、すべてのループと同様に、カウンター変数を増加、もしくは場合により減少させて、最終的に条件が false となるようにする必要があります。そうしなければループは永遠に進み、ブラウザーはそれ強制的に停止させるか、クラッシュします。これは無限ループと呼ばれます。

+
+ +

アクティブラーニング: カウントダウンを開始します!

+ +

この練習では、出力ボックスへの簡単な起動カウントダウンを 10 から Blast off まで印字してください。具体的には、

+ + + +
+

Note: あなたがループ(例えば (while(i>=0))からタイピングを始めると、ブラウザが固まってしまうかもしれません。終了条件をまだ入力していないからです。注意して下さい。この問題に対処するにはコメントの中にコードを書き始めて、完了してからコメントを削除することです。

+
+ +

間違えた場合は、「リセット」ボタンを使用してこの例をいつでもリセットできます。あなたが本当に立ち往生したら、"ソリューションを表示"を押して解決策を見てください。

+ + + +

{{ EmbedLiveSample('Active_learning', '100%', 880, "", "", "hide-codepen-jsfiddle") }}

+ +

アクティブラーニング: ゲストリストに記入する

+ +

この演習では、配列に格納された名前のリストを取得して、それらをゲストリストに入れることが必要です。しかし、これはそれほど簡単ではありません — 彼らは貪欲で失礼で、常にすべての食べ物を食べるので、私たちはフィルとローラを入れさせたくありません! 私たちは 2 つのリストを持っています。1 つは承認するゲストのためのもの、もう 1 つは拒否するゲストのためのものです。
+
+ 具体的には、

+ + + +

私たちはすでにあなたに次のものを提供しました:

+ + + +

特別ボーナス問題 — 上のタスクを正常に完了すると、カンマで区切られた 2 つの名前リストが残されますが、それらは整頓されません。それぞれの末尾にカンマがあります。それぞれの場合に最後のカンマを切り取り、末尾にピリオドを追加した行をどのように書くかという問題を解決出来ますか?ヘルプのため便利な文字列メソッドの記事を見てみてください。
+
+ 間違えた場合は、「リセット」ボタンを使用してこの例をいつでもリセットできます。あなたが本当に立ち往生したら、"ソリューションを表示"を押して解決策を見てください。

+ + + +

{{ EmbedLiveSample('Active_learning_2', '100%', 680, "", "", "hide-codepen-jsfiddle") }}

+ +

どのタイプのループを使用しますか?

+ +

基本的な用途では for、while、do ... while ループはほぼ互換性があります。それらはすべて同じ問題を解決するために使用することができます。どちらを使用するかは、あなたの個人的な好みに大きく左右されます。これは、どれが最も覚えやすいか、最も直感的かということです。それらをもう一度見てみましょう。

+ +

まずは for:

+ +
for (初期化処理; 条件; 最後の式) {
+  // 実行するコード
+}
+ +

while:

+ +
初期化処理
+while (条件) {
+  // 実行するコード
+
+  最後の式
+}
+ +

そして最後は do...while:

+ +
初期化処理
+do {
+  // 実行するコード
+
+  最後の式
+} while (条件)
+ +

少なくとも最初は for から始めることをお勧めします。すべてを覚えておくことが簡単だからです。初期化処理、条件、最後の式をすべて括弧内にきちんと入れなければならないので、それらがどこにあるかや見落としていないことの確認が簡単です。

+ +
+

: 高度な/特殊な状況やこの記事の範囲を超えて有用な、他のループタイプ/機能もあります。ループ学習をさらに進めたい場合は、高度なループと反復処理ガイドをお読みください。

+
+ +

スキルをテストしよう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?移動する前に、情報を維持しているか検証するテストを見ることができます — Test your skills: Loops を見てください。

+ +

まとめ

+ +

この記事では、背後にある基本的な概念と、JavaScript でコードをループする際に使用できるさまざまなオプションについて説明しました。今はループが反復コードを処理するための良い仕組みである理由がはっきり分かり、自身の例で使用できることを誇らしく思うでしょう。
+
+ あなたが理解できなかったことがあれば、記事をもう一度読んだり、ヘルプを求めて私たちに連絡してください。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/building_blocks/return_values/index.html b/files/ja/learn/javascript/building_blocks/return_values/index.html new file mode 100644 index 0000000000..e9a13429b5 --- /dev/null +++ b/files/ja/learn/javascript/building_blocks/return_values/index.html @@ -0,0 +1,201 @@ +--- +title: 関数の戻り値 +slug: Learn/JavaScript/Building_blocks/Return_values +tags: + - リターン + - リターン値 + - 戻り値 + - 返り値 + - 返却値 + - 関数 +translation_of: Learn/JavaScript/Building_blocks/Return_values +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}
+ +

このコースでの関数の学習を終えるために、最後に議論しておくべき関数についての大事なコンセプトがあります。それは戻り値です。関数によっては意味のある値を返さないものもありますが、値を返すものも当然あります。それらの値が何であるか、あなたのコードの中でどのように利用するのか、またどのように関数に意味のある値を返させるのかについて理解することは重要です。これらについてすべてを以下で紹介します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的な HTML と CSS の知識、JavaScript初級レベルの知識関数の知識
目的:関数の戻り値とその使い方を理解すること
+ +

戻り値とは?

+ +

戻り値は、その名が示すとおり関数の実行が完了した時に返される値です。戻り値についてそこまで意識してこなかったかもしれませんが、これまでに何度も戻り値を見てきているはずです。

+ +

以下の見覚えのある例を見てみましょう (このシリーズの過去の記事より) 。

+ +
let myText = 'I am a string';
+let newString = myText.replace('string', 'sausage');
+console.log(newString);
+// 文字列の replace() 関数は文字列を受け取り、
+// 一方の部分文字列をもう一方の部分文字列に置き換え、
+// 置き換えられた新しい文字列を返します。
+
+ +

replace() 関数が myText という文字列の上で実行され、2 つの引数が渡されています:

+ +
    +
  1. 置換される部分文字列 ('string')。
  2. +
  3. 置換する部分文字列 ('sausage')。
  4. +
+ +

この関数が完了 (実行が終了) した時に、関数は置換された新しい文字列を値として返します。上記のコードでは、この戻り値を newString 変数に代入しています。

+ +

replace() 関数についての MDN のリファレンスページには、戻り値 というセクションがあります。関数によって返される値が何か知り把握することはとても大事です。従って、可能な限りこちらも見るようにしてください。

+ +

関数によっては何も値を返しません (この場合、リファレンスページでは戻り値を void または undefined として記載しています)。たとえば、前の記事で作った displayMessage() 関数では、関数が実行されたときに特定の値は返されていません。ただスクリーンのどこかにボックスの表示を作っているだけです。

+ +

一般的に、戻り値は関数がある種の計算をしている途中の段階で使用されます。 関数で計算する必要があるいくつかの値を含む最終結果を取得したいとします。関数は値を計算した後、結果を返すことができるため、変数に格納できます。この変数は、計算の次の段階で使用できます。

+ +

オリジナル関数での戻り値の使い方

+ +

カスタム関数から値を返すために、必要なことは、return というキーワードを使うことです。直近の random-canvas-circles.html の例でこれを見たでしょう。draw() 関数は 100 のランダムな円を HTML 内に表示します。
+ {{htmlelement("canvas")}}:

+ +
function draw() {
+  ctx.clearRect(0, 0, WIDTH, HEIGHT);
+  for (let i = 0; i < 100; i++) {
+    ctx.beginPath();
+    ctx.fillStyle = 'rgba(255,0,0,0.5)';
+    ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
+    ctx.fill();
+  }
+}
+
+ +

ループの繰り返しの中で、現在の円の x 座標y 座標半径それぞれのランダムな値を生成するために random() 関数に対して3 回の呼び出しが行われます。random() 関数はひとつの引数 (整数) を受け取り、0 からその受け取った数値までの乱数を返します。以下のようになります。

+ +
function random(number) {
+  return Math.floor(Math.random() * number);
+}
+
+ +

次のように書くことも可能です。

+ +
function random(number) {
+  const result = Math.floor(Math.random() * number);
+  return result;
+}
+
+ +

しかし最初のものの方がよりコンパクトで、効率よく書けています。

+ +

関数が呼び出されるたびに、Math.floor(Math.random() * number) の計算の結果が返されます。この戻り値は、関数が呼び出された場所に現れて、コードが続行されます。

+ +

したがって、以下を実行すると:

+ +
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
+
+ +

この時、3 つの random() がそれぞれ 50020035 と値を返した場合、このコードは実際には次のように実行されたことになります。

+ +
ctx.arc(500, 200, 35, 0, 2 * Math.PI);
+
+ +

コード上の関数の呼び出しがまず行われ、その戻り値が関数の呼び出しの代わりとなり、その後にコードそのものが実行されます。

+ +

実践: 戻り値を返す関数を作る

+ +

戻り値を返すオリジナルな関数を書いてみましょう。

+ +
    +
  1. まず最初に GitHub から function-library.html ファイルをローカル環境にコピーします。このファイルはシンプルな HTML のページで、文字列入力用の {{htmlelement("input")}} フィールドとパラグラフ(段落)要素を含んでいます。また、{{htmlelement("script")}} 要素があり、この中でページ内の HTML 要素の参照を 2 つの変数で保持させています。このページに対して、テキストボックスに数値を入力したら、入力した数値と関連のある異なる数値を下のパラグラフ要素に表示させるようにしていきます。
  2. +
  3. いくつかの関数を <script> 要素に追加していきましょう。既に記述されている 2 行の JavaScript のコードの下に、以下の関数定義を追加します。 +
    function squared(num) {
    +  return num * num;
    +}
    +
    +function cubed(num) {
    +  return num * num * num;
    +}
    +
    +function factorial(num) {
    +  if (num < 0) return undefined;
    +  if (num == 0) return 1;
    +  let x = num - 1;
    +  while (x > 1) {
    +    num *= x;
    +    x--;
    +  }
    +  return num;
    +}
    + squared() 関数と cubed() 関数は大変わかりやすいでしょう。引数として渡された値の 2 乗や 3 乗を返しています。factorial() 関数は渡された数の階乗を返しています。
  4. +
  5. 次に input に入力された数値を出力する処理を追加していきます。イベントハンドラーを既存の関数の下に記述しましょう。 +
    input.onchange = function() {
    +  const num = input.value;
    +  if (isNaN(num)) {
    +    para.textContent = 'You need to enter a number!';
    +  } else {
    +    para.textContent = num + ' squared is ' + squared(num) + '. ' +
    +                       num + ' cubed is ' + cubed(num) + '. ' +
    +                       num + ' factorial is ' + factorial(num) + '.';
    +  }
    +}
    + +

    ここでは onchange イベントハンドラーを作っています。これは文字列入力での change イベントが発火した時に実行されます。つまり新しい値が input に入力され、送信された時です (たとえば値を入力し、TabReturn を押して入力からフォーカスを外す時)。この無名関数が実行されると、input に入力された値が num 定数に代入されます。
    +
    + 次に、条件付きテストを行うようにします。もし入力された値が数値でなければ、パラグラフ要素にエラーメッセージを出力します。テストでは、式 isNaN(num) が true を返すかどうか見るようにします。一般的に値が数値でないかをテストする際には isNaN() 関数を使います。この関数では、渡された値が数値でなければ true を返し、数値であれば false を返します。
    +
    + もしテストが false を返した場合、num の値は数値です。したがって、数値の 2 乗、3 乗、階乗の値を示す文が、パラグラフ要素内に出力されます。その出力する文章内で必要とする値を計算するために squared() 関数、cubed() 関数、factorial() 関数を呼んでいます。

    +
  6. +
  7. +

    コードを保存して、それをブラウザーで表示してみましょう。

    +
  8. +
+ +
+

注意: もしサンプルがうまく動作しない場合は、GitHub 上の完成版と比較などしてみてください(実際に動かして確認もできます)。またはお問い合わせください。

+
+ +

あなたの番です!

+ +

この時点で、独自の関数をいくつか書き出してライブラリに追加してみましょう。数値の平方根や立方根はどうですか?また、特定の半径を持つ円の円周はどうでしょうか?

+ +

関数に関する追加のヒント:

+ + + +

スキルをテストしよう!

+ +

この記事の最後まで到達しましたが、最も大事な情報を覚えていますか?移動する前に、この情報を維持しているか検証するテストを見ることができます— Test your skills: Functions を見てください。

+ +

まとめ

+ +

以上、関数は楽しく、非常に便利で、構文や機能についてまだまだ話すことはたくさんありますが、それらはかなり理解しやすいものです。

+ +

もし何か理解できなかったことがありましたら、何度もこの記事を読み込むか、またはお問い合わせください。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/client-side_web_apis/client-side_storage/index.html b/files/ja/learn/javascript/client-side_web_apis/client-side_storage/index.html new file mode 100644 index 0000000000..da7b36abbf --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/client-side_storage/index.html @@ -0,0 +1,796 @@ +--- +title: クライアント側ストレージ +slug: Learn/JavaScript/Client-side_web_APIs/Client-side_storage +tags: + - API + - Article + - Beginner + - CodingScripting + - Guide + - IndexedDB + - JavaScript + - Learn + - Storage + - Web Storage + - ウェブストレージ + - ガイド + - 保存 + - 初心者 + - 学習 +translation_of: Learn/JavaScript/Client-side_web_APIs/Client-side_storage +--- +

{{LearnSidebar}}

+ +
{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

モダン・ウェブブラウザーは、ユーザーの許可のもとにウェブサイトがユーザーのコンピューター上にデータを保存して必要なときにそのデータを取得するための、いくつもの方法をサポートしています。このことにより、長期記憶のためにデータを存続させること、オフライン利用のためにサイトまたは文書を保存すること、サイトについてのユーザー独自の設定を保持すること、などなどが可能になります。本記事では、これらがどのようにして機能するのかについてのごく基本的な点を説明します。

+ + + + + + + + + + + + +
前提知識:JavaScript の基本 (JavaScript の第一歩JavaScript の構成要素JavaScript オブジェクト入門 を参照)、ウェブ APIの紹介
学習目標:アプリケーション・データを保存するためのクライアント側のストレージ API の使い方を学ぶこと
+ +

クライアント側での保存って?

+ +

MDN 学習エリアの他の箇所で、静的なサイト動的なサイト の違いについて述べました。ほとんどの主要なモダン・ウェブサイトは動的です。つまり、ある種のデータベース (サーバー側のストレージ) を使ってデータをサーバー上に記憶し、必要なデータを取得するためにサーバー側 のコードを実行し、そのデータを静的なページ雛型に挿入し、結果として出来上がった HTML をクライアントに提供して、それがユーザーのブラウザーによって表示されるようにします。

+ +

クライアント側での保存は類似の原理に基づいて機能しますが、これにはいくつかの異なる使い道があります。クライアント側での保存は、クライアント上に (つまりユーザーのマシン上に) データを保存して必要なときにそのデータを取得できるようにしてくれる、いくつかの JavaScript API から構成されています。クライアント側での保存には、たとえば以下のように多くの異なる用途があります。

+ + + +

クライアント側での保存とサーバ側での保存は、しばしば共に使われます。たとえば、複数の音楽ファイル (おそらくウェブゲームまたは音楽プレーヤー・アプリに使われる) をダウンロードし、それらの音楽ファイルをクライアント側のデータベース内に保存し、必要に応じて再生する、といったことが可能でしょう。ユーザーは、それらの音楽ファイルをただ一度ダウンロードするだけで済むでしょう。その後の訪問では、音楽ファイルは、ダウンロードされる代わりにデータベースから取得されるでしょう。

+ +
+

: クライアント側のストレージ API を使って保存できるデータの量には、上限があります (もしかすると、個別の API ごとの上限と、累積的な上限の双方があるかもしれません)。正確な上限は、ブラウザーごとに異なりますし、もしかすると、ユーザーの設定によることもあるかもしれません。より詳しくは、ブラウザーのストレージ制限と削除基準 を参照。

+
+ +

旧式な方法: クッキー

+ +

クライアント側での保存という考え方には、長い歴史があります。ウェブの初期から、ウェブサイト上でのユーザー体験を個別化するための情報を記憶するべく、サイトは クッキー を使ってきました。そうしたクッキーは、ウェブ上で一般的に使われるクライアント側での保存の、最初期の形式です。

+ +

最近では、クライアント側のデータを保存するためのより簡単な仕組みが利用できるため、この記事ではクッキーの使用方法については説明しません。ただし、これはクッキーが現代のウェブで完全に役に立たないことを意味するわけではありません。クッキーは、ユーザーの個別化や状態に関連するデータを保存するために今でも一般的に使用されています。たとえば、セッション ID やアクセストークンです。クッキーの詳細については、HTTP cookies の記事を参照してください。

+ +

新方式派: ウェブストレージと IndexedDB

+ +

前述の「簡単な」機能には次のものがあります:

+ + + +

以下ではこれらの API について学ぶことになります。

+ +

将来: キャッシュ API

+ +

いくつかのモダン・ブラウザーは、新しい {{domxref("Cache")}} API をサポートしています。この API は、特定の要求に対する HTTP 応答を記憶しておくために設計されています。 また、ネットワーク接続なしに後でサイトを利用できるように、ウェブサイト資産をオフラインに記憶しておく、といったようなことをするうえで非常に有用です。キャッシュは通常、サービスワーカー API と組み合わせて利用します。もっとも、必ずそうしなくてはならないというわけではありません。

+ +

キャッシュとサービスワーカーの利用は先進的な話題であり、この記事ではそれほど詳しくは扱いません。とは言うものの、後述の {{anch("Offline asset storage")}} の節では、簡単な例をお見せします。

+ +

単純なデータを保存する——ウェブストレージ

+ +

Web Storage API は大変使いやすいものです。(文字列や数などに限定された) データからなる単純な名前/値のペアを保存し、必要なときにその値を取り出します。

+ +

基本的構文

+ +

以下に方法を示しましょう。

+ +
    +
  1. +

    まず、GitHub 上の ウェブストレージの空白テンプレート へ行ってください (新規タブで開いてください)。

    +
  2. +
  3. +

    ブラウザーのデベロッパー・ツールの JavaScript コンソールを開いてください。

    +
  4. +
  5. +

    ウェブストレージ・データのすべては、ブラウザー内部の二つのオブジェクト的な構造体の中に含まれます。つまり、{{domxref("Window.sessionStorage", "sessionStorage")}} と {{domxref("Window.localStorage", "localStorage")}} の中です。前者は、ブラウザーが開いている限り、データを存続させます (ブラウザーを閉じるとデータは失われます)。後者は、ブラウザーを閉じて、それから再びブラウザーを開いた後でさえも、データを存続させます。一般的には後者の方がより有用なので、本記事では後者を使います。

    + +

    {{domxref("Storage.setItem()")}} メソッドによって、ストレージ内にデータ項目を保存できます。このメソッドは二つの引数をとります。すなわち、その項目の名前と、その値です。JavaScript コンソールに以下のように打ち込んでみてください (もしお望みなら、値は御自分のお名前に変更してくださいね!)

    + +
    localStorage.setItem('name','Chris');
    +
  6. +
  7. +

    {{domxref("Storage.getItem()")}} メソッドは一つの引数をとります。つまり、取り出したいデータ項目の名前です。そして、このメソッドは、その項目の値を返します。今度は JavaScript コンソールに以下の行を打ち込んでください。

    + +
    let myName = localStorage.getItem('name');
    +myName
    + +

    2 行目を入力すると、myName という変数が今や name というデータ項目の値を保有していることが分かるはずです。

    +
  8. +
  9. +

    {{domxref("Storage.removeItem()")}} メソッドは一つの引数をとります。つまり、削除したいデータ項目の名前です。このメソッドは、ウェブストレージからその項目を削除します。JavaScript コンソールに以下の行を打ち込んでください。

    + +
    localStorage.removeItem('name');
    +let myName = localStorage.getItem('name');
    +myName
    + +

    3 行目は、今度は null を返すはずです。というのも、もはや name という項目はウェブストレージ内に存在しないからです。

    +
  10. +
+ +

データが存続する!

+ +

ウェブストレージの一つの重要な特徴は、ページ・ロードをまたいで (さらに、localStorage の場合には、ブラウザーを終了させてさえも) データが存続する、という点です。この特徴が機能しているところを見てみましょう。

+ +
    +
  1. +

    もう一度、ウェブストレージの空白テンプレートを開いてください。ただし今回は、本チュートリアルを開いたのとは別のブラウザーで開いてください! こうすることで、取り扱いがしやすくなるでしょう。

    +
  2. +
  3. +

    以下の行をブラウザーの JavaScript コンソールに打ち込んでください。

    + +
    localStorage.setItem('name','Chris');
    +let myName = localStorage.getItem('name');
    +myName
    + +

    name という項目が返されるのが分かるはずです。

    +
  4. +
  5. +

    さてここでブラウザーを終了させてから再び起動して開いてください。

    +
  6. +
  7. +

    再び、以下の行を入力してください。

    + +
    let myName = localStorage.getItem('name');
    +myName
    + +

    ブラウザーを終了させてから再び開いたというのに、それでも依然として値が利用可能である、ということが分かるはずです。

    +
  8. +
+ +

ドメインごとに別々のストレージ

+ +

ドメインごとに (ブラウザーにロードされた別々のウェブ・アドレスごとに)、別々のデータストアがあります。二つのウェブサイト (たとえば google.com と amazon.com) をロードして、一方のウェブサイトで項目を保存してみると、その項目は他方のウェブサイトでは利用できない、と分かるでしょう。

+ +

これには意義があります。もしウェブサイト同士がお互いのデータを見ることが可能であったら起こるであろうセキュリティ問題を想像できますよね!

+ +

さらに込み入った例

+ +

どのようにウェブストレージを使えるのかについてお教えするために、簡単で基礎的な事例を書くことによって、(ドメインごとのストレージという) この新たに得た知識を応用してみましょう。この事例では、名前を入力できるようにします。その入力の後、個人に合わせた挨拶を表示するべく、ページが更新されます。この状態は、ページ/ブラウザーのリロードをまたいでも存続するでしょう。なぜなら、名前がウェブストレージに記憶されているからです。

+ +

この例の HTML を personal-greeting.html で入手できます。これは、ヘッダーとコンテンツとフッターを備えた簡素なウェブサイトと、名前を入力するためのフォームとを含みます。

+ +

+ +

この例を組み上げましょう。すると、これがどのように機能するのか理解できるでしょう。

+ +
    +
  1. +

    まず、御自分のコンピュータ上の新規ディレクトリに、personal-greeting.html というファイルのローカルコピーを作ってください。

    +
  2. +
  3. +

    次に、index.js と呼ばれる JavaScript ファイルを、HTML がどのように参照しているのかに注意してください (40 行目を参照)。これ (index.js) を作成して、そこに JavaScript コードを書き込む必要があります。HTML ファイルと同じディレクトリに index.js というファイルを作成してください。

    +
  4. +
  5. +

    この例で操作する必要のある HTML 項目 (features) のすべてに対する参照を作るところから取り掛かりましょう。それらの参照のすべてを定数として作ります。なぜなら、これらの参照は、アプリのライフサイクル内で変化する必要がないからです。以下の行を JavaScript ファイルに追加してください。

    + +
    // 必要な定数を作ります。
    +const rememberDiv = document.querySelector('.remember');
    +const forgetDiv = document.querySelector('.forget');
    +const form = document.querySelector('form');
    +const nameInput = document.querySelector('#entername');
    +const submitBtn = document.querySelector('#submitname');
    +const forgetBtn = document.querySelector('#forgetname');
    +
    +const h1 = document.querySelector('h1');
    +const personalGreeting = document.querySelector('.personal-greeting');
    +
  6. +
  7. +

    次に、送信ボタンが押されたときにフォームが実際にこのフォーム自体を送信することをやめさせるための、小規模なイベント・リスナーを含める必要があります。というのも、こうした送信は所望の振る舞いではないからです。以下に示すスニペットを、前のコードに追加してください。

    + +
    // ボタンが押されたときにフォームが送信することをやめさせます。
    +form.addEventListener('submit', function(e) {
    +  e.preventDefault();
    +});
    +
  8. +
  9. +

    さてここで、イベント・リスナーを追加せねばなりません。そのイベント・リスナーのハンドラー関数は、"Say hello" ボタンがクリックされたときに実行されます。それぞれの断片が何を行うのかはコメントで詳しく説明してありますが、本質的にここでは、ユーザーがテキスト入力ボックスに入力した名前をとってきて、setItem() を用いてその名前をウェブストレージに保存し、その後、実際のウェブサイト上のテキストの更新を扱う nameDisplayCheck() と呼ばれる関数を実行しています。これをコードの末尾に加えてください。

    + +
    // 'Say hello' ボタンがクリックされたら関数を実行します。
    +submitBtn.addEventListener('click', function() {
    +  // 入力された名前をウェブストレージに保存します。
    +  localStorage.setItem('name', nameInput.value);
    +  // 個人に合わせた挨拶を表示するとともにフォーム表示を更新する
    +  // 措置をとるべく、nameDisplayCheck() を実行します。
    +  nameDisplayCheck();
    +});
    +
  10. +
  11. +

     この時点で、"Forget" ボタンがクリックされたときに関数を実行するためのイベント・ハンドラーも必要です。"Forget" ボタンは、"Say hello" ボタンがクリックされた後にのみ表示されます (二つのフォーム状態が行ったり来たり切り替わります)。この関数では、removeItem() を用いてウェブストレージから name という項目を削除し、その後、表示を更新するために nameDisplayCheck() を再び実行します。これを末尾に付け加えてください。

    + +
    // 'Forget' ボタンがクリックされたら関数を実行します。
    +forgetBtn.addEventListener('click', function() {
    +  // 保存してある名前をウェブストレージから削除します。
    +  localStorage.removeItem('name');
    +  // 再び一般的な挨拶を表示するとともにフォーム表示を更新する
    +  // 措置をとるべく、nameDisplayCheck() を実行します。
    +  nameDisplayCheck();
    +});
    +
  12. +
  13. +

    さて今や nameDisplayCheck() という関数そのものを定義すべきときです。ここでは、localStorage.getItem('name') を条件テストとして用いることにより、name という項目がウェブストレージに保存済みかどうかを調べます。もし保存済みなら、この呼び出しは true と評価されるでしょう。もし保存済みでなければ、false になるでしょう。もし true なら、個人に合わせた挨拶を表示し、フォームの "forget" の部分を表示し、フォームの "Say hello" の部分を隠します。もし false なら、一般的な挨拶を表示し、逆のことをします (フォームの "forget" の部分を隠し、フォームの "Say hello" の部分を表示します)。またもや末尾に以下のコードを追加してください。

    + +
    // nameDisplayCheck() という関数を定義します。
    +function nameDisplayCheck() {
    +  // 'name' というデータ項目がウェブストレージに保存されているかどうかを調べます。
    +  if(localStorage.getItem('name')) {
    +    // もし保存されていたら、個人に合わせた挨拶を表示します。
    +    let name = localStorage.getItem('name');
    +    h1.textContent = 'Welcome, ' + name;
    +    personalGreeting.textContent = 'Welcome to our website, ' + name + '! We hope you have fun while you are here.';
    +    // フォームのうち 'remember' の部分を隠し、'forget' の部分を表示します。
    +    forgetDiv.style.display = 'block';
    +    rememberDiv.style.display = 'none';
    +  } else {
    +    // もし保存されていなければ、一般的な挨拶を表示します。
    +    h1.textContent = 'Welcome to our website ';
    +    personalGreeting.textContent = 'Welcome to our website. We hope you have fun while you are here.';
    +    // フォームのうち 'forget' の部分を隠し、'remember' の部分を表示します。
    +    forgetDiv.style.display = 'none';
    +    rememberDiv.style.display = 'block';
    +  }
    +}
    +
  14. +
  15. +

    最後に、ページがロードされるたびに nameDisplayCheck() という関数を実行せねばなりません。もしそうしなければ、個人に合わせた挨拶は、ページのリロードをまたがってまでは持続しなくなってしまうでしょう。以下のものをコードの末尾に追加してください。

    + +
    document.body.onload = nameDisplayCheck;
    +
  16. +
+ +

例が完成しました。よくできましたね! 現時点で残っているのは、コードを保存して HTML ページをブラウザーでテストすることだけです。ライブ実行される完成版をここで 見られます。

+ +
+

: ウェブストレージ API の使用 のところには、探究するにはほんの少しだけ更に複雑な別の例もあります。

+
+ +
+

: 完成版のソースのうち <script src="index.js" defer></script> という行では、defer 属性により、ページをロードし終わるまでは {{htmlelement("script")}} 要素の中身を実行しないように指定しています。

+
+ +

複雑なデータを保存する—— IndexedDB

+ +

IndexedDB API  (ときには IDB と省略します) は、ブラウザーで利用可能であり、複雑で関係性のあるデータを保存できる、完全なデータベース・システムです。そしてそのデータの型は、文字列または数値のような単純な値に限定されません。動画や静止画像、そして、その他のものもほとんどすべて、IndexedDB インスタンスに保存できます。

+ +

しかし、これは高くつきます。IndexedDB の使用は、ウェブストレージ API の使用よりも遥かに複雑なのです。本節では、IndexedDB ができることのうち本当に表面的なところに触れるだけですが、始めるのに十分なだけのことは、お伝えしましょう。

+ +

メモ書きの保存の事例を通して作業します

+ +

ここでは、メモ書きをブラウザーに保存して好きなときにそれを見たり消したりできるようにする事例を、見ていただきましょう。その際、その例は御自分で組み立てていただきますが、進行に合わせて、IDB の最も根本的な部分について御説明します。

+ +

当該アプリは、以下のような見かけをしています。

+ +

+ +

メモ書きの各々には題名と何らかの本文があり、題名と本文のそれぞれは別々に編集できます。以下で見てゆく JavaScript コードには、何が起きているのかを理解する手助けとなる詳しいコメントがあります。

+ +

始めますよ

+ +
    +
  1. まず、index.htmlstyle.cssindex-start.js というファイルのローカルコピーを、ローカルマシンの新規ディレクトリ内に作成してください。
  2. +
  3. ファイルを見てください。HTML がかなり簡潔なのがお分かりでしょう。これは、ヘッダーとフッターのあるウェブサイトです。また、メモ書きを表示する場所と、データベースに新たなメモ書きを入力するためのフォームとを含む、本文コンテンツ領域もあります。 CSS は、何が起きているのかをより明瞭にするための、ある種の簡素なスタイルづけを提供しています。JavaScript ファイルは、宣言された五つの定数を含んでいます。つまり、 内部にメモ書きを表示することになる {{htmlelement("ul")}} 要素への参照と、題名および本文の {{htmlelement("input")}} 要素への参照と、{{htmlelement("form")}} 自体への参照と、{{htmlelement("button")}} への参照とを含んでいます。
  4. +
  5. JavaScript ファイルの名前を index.js に変更してください。コードをそこに追加し始める準備がこれで整いました。
  6. +
+ +

データベースの初期設定

+ +

では、実際にデータベースを設定するために最初にすべきことを見てみましょう。

+ +
    +
  1. +

    定数の宣言の下に、以下の行を追加してください。

    + +
    // 開いたデータベースを記憶しておくためのデータベース・オブジェクトのインスタンスを作成します。
    +let db;
    + +

    ここでは、db と呼ばれる変数を宣言しています。これは後に、データベースを表すオブジェクトを記憶するのに使われます。この変数を何箇所かで使うつもりなので、物事を容易にするために、ここでこの変数を大域的に宣言しておきました。

    +
  2. +
  3. +

    次に、以下のものをコードの末尾に加えてください。

    + +
    window.onload = function() {
    +
    +};
    + +

    続きのコードはすべて、この window.onload イベント・ハンドラー関数——ウィンドウの {{event("load")}} イベントが発火したときに呼ばれます——の中に書いてゆきます。アプリが完全にロード動作を終えるよりも前には IndexedDB 機能を使おうとはしないよう保証するために、そうしています  (もしそう保証しなかったら、失敗する可能性があります)。

    +
  4. +
  5. +

    window.onload ハンドラーの中に、以下のものを追加してください。

    + +
    // データベースを開きます。データベースは、まだ存在していない場合には
    +// 新規作成されます (後述の onupgradeneeded を参照)。
    +let request = window.indexedDB.open('notes', 1);
    + +

    この行では、notes と呼ばれるデータベースのバージョン 1 を開く request (要求) を作成します。もしそのデータベースがまだ存在しなければ、後述のコードによって新規作成されます。IndexedDB の全体を通じて、この要求パターンが非常に高頻度で使われることが、いずれお分かりになるでしょう。データベース操作には時間がかかります。その結果を待つ間、ブラウザーをハングさせることはお望みでないでしょうから、データベース操作は {{Glossary("asynchronous")}} (非同期) となっています。このことが意味するのは、結果は直ちに生じるのではなく、将来のいずれかの時点で生じるだろうということ、および、結果が出たときには通知されるということです。

    + +

    こういったことを IndexedDB で扱うために、要求オブジェクト (何とでも好きなように呼んで構いませんが、何を目的としたものなのかが明白になるので、request (要求) と呼んでおきました) を作成します。それから、要求が完了する、失敗する、などの際にコードを実行するために、いくつかのイベント・ハンドラーを使います。この点については、使用されているところを後で見ることになります。

    + +
    +

    :  バージョン番号は重要です。(たとえばテーブル構造を変更することによって) データベースをアップグレードしたい場合には、上げたバージョン番号や、onupgradeneeded ハンドラー (下記参照) の内部で指定される別のスキーマなどを使って、コードを再度実行せねばなりません。この簡単なチュートリアルでは、データベースのアップグレードは扱いません。

    +
    +
  6. +
  7. +

    さて今度は、前に追加した分のすぐ下に、以下のイベント・ハンドラーを追加してください。今度もまた、window.onload ハンドラーの中への追加です。

    + +
    // onerror ハンドラーは、データベースがうまく開けなかったことを意味します。
    +request.onerror = function() {
    +  console.log('Database failed to open');
    +};
    +
    +// onsuccess ハンドラーは、データベースがうまく開けたことを意味します。
    +request.onsuccess = function() {
    +  console.log('Database opened successfully');
    +
    +  // 開いたデータベース・オブジェクトを、db という変数に記憶します。この変数は、以下でたくさん使われます。
    +  db = request.result;
    +
    +  // IDB 内の既存のメモ書きを表示するために、displayData() 関数を実行します。
    +  displayData();
    +};
    + +

    要求は失敗した、と伝えつつシステムが戻ってくる場合には、{{domxref("IDBRequest.onerror", "request.onerror")}} というハンドラーが実行されます。これによって、(要求が失敗したという) この問題に対処できるようになります。この簡単な例では、単に JavaScript コンソールにメッセージを印字します。

    + +

    他方、{{domxref("IDBRequest.onsuccess", "request.onsuccess")}} ハンドラーは、要求が成功裡に戻ってくる場合、つまりデータベースをうまく開けた場合に、実行されます。この場合、開いたデータベースを表すオブジェクトが、{{domxref("IDBRequest.result", "request.result")}} というプロパティで利用可能となります。それにより、データベースを操作できるようになります。後で使うために、と事前に作っておいた db という変数に、このオブジェクトを保存します。また、displayData() と呼ばれるカスタム関数も実行します。この関数は、データベース内のデータを {{HTMLElement("ul")}} 内部に表示します。すでにデータベース内にあるメモ書きが、ページがロードされ次第すぐに表示されるように、ここでこの関数を実行しています。この関数を定義する様子は、後で見ることにしましょう。

    +
  8. +
  9. +

    本節の最後では、データベースを設定するためには多分もっとも重要なイベント・ハンドラーを追加しましょう。つまり、{{domxref("IDBOpenDBRequest.onupgradeneeded", "request.onupgradeneeded")}} です。このハンドラーは、データベースがまだ設定されていなかった場合、あるいは、保存済みの既存のデータベースよりも上のバージョン番号でデータベースが開かれた場合 (アップグレードを行う場合) に、実行されます。前のハンドラーの下に、以下のコードを追加してください。

    + +
    // これがまだ実行されていない場合に、データベースのテーブルを設定します。
    +request.onupgradeneeded = function(e) {
    +  // 開いたデータベースに対する参照を求めます。
    +  let db = e.target.result;
    +
    +  // 自動的にインクリメントするキーを含んでおり、メモ書きを中に保存するための
    +  // (基本的に一つのテーブルに類似した) objectStore を、作成します。
    +  let objectStore = db.createObjectStore('notes', { keyPath: 'id', autoIncrement:true });
    +
    +  // objectStore が含むことになるデータ項目を定義します。
    +  objectStore.createIndex('title', 'title', { unique: false });
    +  objectStore.createIndex('body', 'body', { unique: false });
    +
    +  console.log('Database setup complete');
    +};
    + +

    ここは、データベースのスキーマ (構造) ——すなわち、データベースが含む列 (ないしフィールド) の集合——を定義している箇所です。ここではまず、e.target.result (イベント・ターゲットの result というプロパティ) から、既存のデータベースへの参照を求めていますが、これ (e.target というイベント・ターゲット) は、request というオブジェクトです。この行は、onsuccess ハンドラーの中の db = request.result; という行と等価です。しかし、それとは別に、ここでこのようにする必要があります。なぜなら、onupgradeneeded ハンドラーは、(もし必要な場合には) onsuccess ハンドラーよりも前に実行されることになる——つまり、もしここでこのようにしておかなければ、db の値を利用できない——からです。

    + +

    それから、{{domxref("IDBDatabase.createObjectStore()")}} を用いて、開いたデータベースの内部に新たなオブジェクト・ストアを作成します。これは、従来のデータベース・システムにおける一つのテーブルと等価です。このオブジェクト・ストアには notes という名前をつけました。また、id と呼ばれる autoIncrement キーのフィールドも指定しました。新規レコードの各々において、このフィールドには、インクリメントされた値が自動的に与えられ、開発者は、このフィールドを明示的に設定する必要がありません。キーであるがゆえに、id フィールドは、たとえばレコードを削除または表示する際に、レコードを一意に識別するのに使われることでしょう。

    + +

    {{domxref("IDBObjectStore.createIndex()")}} メソッドを用いて、別の二つのインデックス (フィールド) も作成します。すなわち、title  (それぞれのメモ書きの題名を含むことになります) と、body (そのメモ書きの本文を含むことになります) を作成します。

    +
  10. +
+ +

以上のようにこの簡素なデータベース・スキーマを設定したので、データベースにレコードを追加し始めれば、それぞれのレコードは、以下の行のようなオブジェクトとして表現されることでしょう。

+ +
{
+  title: "Buy milk",
+  body: "Need both cows milk and soy.",
+  id: 8
+}
+ +

データをデータベースに追加します

+ +

それでは、どのようにしたらデータベースにレコードを追加できるか、その方法を見てみましょう。これは、ページ上のフォームを使って行われます。

+ +

前のイベント・ハンドラーの下に (ただし、やはり window.onload ハンドラーの内部に)、 以下の行を追加してください。以下の行では、フォームが送信された際に (送信 {{htmlelement("button")}} が押され、成功したフォーム送信、という結果に至ったときに)、addData() と呼ばれる関数を実行する、onsubmit ハンドラーを設定しています。

+ +
// フォームが送信されたときに addData() 関数が実行されるように、onsubmit ハンドラーを作成します。
+form.onsubmit = addData;
+ +

では、addData() 関数を定義しましょう。上記の行の下に、以下のものを追加してください。

+ +
// addData() 関数を定義します。
+function addData(e) {
+  // デフォルト動作を防止します。従来通りの方法でフォームを送信したくはないからです。
+  e.preventDefault();
+
+  // フォーム・フィールドに入力された値を求めます。そして、それらの値を、データベースへ挿入すべく準備してあるオブジェクトに保存します。
+  let newItem = { title: titleInput.value, body: bodyInput.value };
+
+  // 読み書きのデータベース・トランザクションを開いて、データの追加に備えます。
+  let transaction = db.transaction(['notes'], 'readwrite');
+
+  // データベースに追加済みのオブジェクト・ストアを呼び出します。
+  let objectStore = transaction.objectStore('notes');
+
+  // newItem というオブジェクトをオブジェクト・ストアに追加するための要求を作ります。
+  let request = objectStore.add(newItem);
+  request.onsuccess = function() {
+    // フォームをクリアして、次のエントリーの追加に備えます。
+    titleInput.value = '';
+    bodyInput.value = '';
+  };
+
+  // すべてが済んだら、完了するトランザクションの成功を報告します。
+  transaction.oncomplete = function() {
+    console.log('Transaction completed: database modification finished.');
+
+    // displayData() を再度実行することによって、データの表示を更新して、新たに追加した項目を表示します。
+    displayData();
+  };
+
+  transaction.onerror = function() {
+    console.log('Transaction not opened due to error');
+  };
+}
+ +

これは割と複雑ですね。噛み砕くと、以下の通りです。

+ + + +

データを表示します

+ +

すでにコード内で displayData() を二度も参照したからには、多分これを定義すべきでしょうね。以下のものをコードに (今までの関数定義の下に) 追加してください。

+ +
// displayData() 関数を定義します。
+function displayData() {
+  // ここでは、表示を更新するたびにリスト要素の中身を空にします。
+  // もしこのようにしなかったら、新たなメモ書きを追加するたびに複製を列挙する羽目になるでしょう。
+  while (list.firstChild) {
+    list.removeChild(list.firstChild);
+  }
+
+  // オブジェクト・ストアを開き、それから、カーソルを取得します。
+  // カーソルは、ストア内の異なるデータ項目のすべてにわたって反復処理を行うものです。
+  let objectStore = db.transaction('notes').objectStore('notes');
+  objectStore.openCursor().onsuccess = function(e) {
+    // カーソルへの参照を求めます。
+    let cursor = e.target.result;
+
+    // 反復処理を行うべき別のデータ項目がまだあれば、このコードを実行し続けます。
+    if(cursor) {
+      // 各データ項目を表示する際にそのデータ項目を中に入れるための、リスト項目と h3 と p とを作成します。
+      // HTML 断片を組み立てて、それをリスト内の最後に追加します。
+      const listItem = document.createElement('li');
+      const h3 = document.createElement('h3');
+      const para = document.createElement('p');
+
+      listItem.appendChild(h3);
+      listItem.appendChild(para);
+      list.appendChild(listItem);
+
+      // h3 および para の内部に、カーソルからのデータを入れます。
+      h3.textContent = cursor.value.title;
+      para.textContent = cursor.value.body;
+
+      // listItem の属性内部に、このデータ項目の ID を保存します。こうすると、
+      // listItem がどの項目に対応しているのかがわかります。これは、後で項目を削除したくなったときに有用です。
+      listItem.setAttribute('data-note-id', cursor.value.id);
+
+      // ボタンを作成し、それを各 listItem の内部に設置します。
+      const deleteBtn = document.createElement('button');
+      listItem.appendChild(deleteBtn);
+      deleteBtn.textContent = 'Delete';
+
+      // ボタンがクリックされたら deleteItem() 関数が実行されるように、
+      // イベント・ハンドラーを設定します。
+      deleteBtn.onclick = deleteItem;
+
+      // カーソルにおける次の項目へと反復処理を進めます。
+      cursor.continue();
+    } else {
+      // またもや、リスト項目が空であれば、'No notes stored' (メモ書きは何も保存されていません) というメッセージを表示します。
+      if(!list.firstChild) {
+        const listItem = document.createElement('li');
+        listItem.textContent = 'No notes stored.';
+        list.appendChild(listItem);
+      }
+      // 反復処理をすべきカーソル項目がこれ以上ない場合、そのように示します。
+      console.log('Notes all displayed');
+    }
+  };
+}
+ +

再びになりますが、これを噛み砕いてみましょう。

+ + + +

メモ書きを削除します

+ +

上述のとおり、メモ書きの削除ボタンが押されると、そのメモ書きは削除されます。これは、deleteItem() 関数により達成されます。この関数は以下のようなものです。

+ +
// deleteItem() 関数を定義します。
+function deleteItem(e) {
+  // 削除したいタスクの名前 (訳注: ID の間違い?) を取り出します。
+  // それを IDB で使おうとする前に、数値に変換する必要があります。
+  // IDB のキーの値には、型による区別があるのです。
+  let noteId = Number(e.target.parentNode.getAttribute('data-note-id'));
+
+  // データベース・トランザクションを開き、当該タスクを削除します。その際、上記で取得した ID を用いて、当該タスクを見つけます。
+  let transaction = db.transaction(['notes'], 'readwrite');
+  let objectStore = transaction.objectStore('notes');
+  let request = objectStore.delete(noteId);
+
+  // データ項目を削除したことを報告します。
+  transaction.oncomplete = function() {
+    // ボタンの親——リスト項目——を削除します。
+    // すると、それはもはや表示されなくなります。
+    e.target.parentNode.parentNode.removeChild(e.target.parentNode);
+    console.log('Note ' + noteId + ' deleted.');
+
+    // 再びになりますが、リスト項目が空の場合は、'No notes stored' (メモ書きは何も保存されていません) というメッセージを表示します。
+    if(!list.firstChild) {
+      let listItem = document.createElement('li');
+      listItem.textContent = 'No notes stored.';
+      list.appendChild(listItem);
+    }
+  };
+}
+ + + +

さあ、これで全部終わりです! あなたの例は今やちゃんと動くはずですよ。

+ +

もし問題があれば、気軽に ライブ例と突き合わせてみてください (ソースコード も参照してください)。

+ +

IndexedDB を通じて複雑なデータを保存します

+ +

上述のとおり、IndexedDB は、単純なテキスト文字列以上のものを保存するのに使えます。望むものはほとんど何でも——動画や静止画像のブロブ (blob) のような、複雑なオブジェクトまで含めて——保存できるのです。しかも、他のどの型のデータと比べても、達成するのがずっと困難だという訳でもないのです。

+ +

やり方を実演するために、IndexedDB 動画ストア と呼ばれる別の例を書きました (ここでライブで動いているところも 参照してください)。この例を最初に実行すると、すべての動画をネットワークからダウンロードして IndexedDB データベースに保存し、それから、{{htmlelement("video")}} 要素内部の UI の中に動画を表示します。二度目に実行すると、動画を表示する前に、データベース内の動画を見つけ出し、(ネットワークからダウンロードする) 代わりにそこから動画を取ってきます。こうすることにより、後続のロードは高速化され、帯域幅をあまり食わなくなります。

+ +

この例のもっとも興味深い部分を見て回りましょう。すべては見ないことにします。というのも、多くの部分は前の例に類似しており、コードにはちゃんとコメントがつけてありますから。

+ +
    +
  1. +

    この単純な例のために、取得すべき動画の名前をオブジェクトの配列の形で保存しておきました。

    + +
    const videos = [
    +  { 'name' : 'crystal' },
    +  { 'name' : 'elf' },
    +  { 'name' : 'frog' },
    +  { 'name' : 'monster' },
    +  { 'name' : 'pig' },
    +  { 'name' : 'rabbit' }
    +];
    +
  2. +
  3. +

    まずはじめに、データベースを成功裡に開くことができたら、init() 関数を実行します。これは、異なる動画の名前をループしてゆきますが、その際、それぞれの名前で識別されるレコードを videos というデータベースからロードしようと試みます。

    + +

    各々の動画がデータベース内で見つかったら (これは、request.resulttrue と評価されるかどうかを調べることにより、容易に確認できます。もしレコードが存在しなければ、undefined となります)、その動画ファイル (ブロブとして保存されています) および動画の名前が、UI に配置するために、すぐに displayVideo() 関数へと渡されます。もし動画がデータベース内で見つからなければ、動画の名前が fetchVideoFromNetwork() 関数に渡されます。それが何のためか、見当がついていることでしょうが……そう、その動画をネットワークから取ってくるためです。

    + +
    function init() {
    +  // 動画の名前を一つずつループしてゆきます。
    +  for(let i = 0; i < videos.length; i++) {
    +    // トランザクションを開き、オブジェクト・ストアを取得し、名前によって各動画を get() します。
    +    let objectStore = db.transaction('videos').objectStore('videos');
    +    let request = objectStore.get(videos[i].name);
    +    request.onsuccess = function() {
    +      // もし結果がデータベース内に存在したら (存在しなければ undefined)、
    +      if(request.result) {
    +        // displayVideo() を用いて、動画を IDB から取り出して表示します。
    +        console.log('taking videos from IDB');
    +        displayVideo(request.result.mp4, request.result.webm, request.result.name);
    +      } else {
    +        // 動画をネットワークから取ってきます。
    +        fetchVideoFromNetwork(videos[i]);
    +      }
    +    };
    +  }
    +}
    +
  4. +
  5. +

    以下のスニペットは、fetchVideoFromNetwork() の内部から取ったものです。ここでは、二つの別々の {{domxref("fetch()", "WindowOrWorkerGlobalScope.fetch()")}} 要求を用いて、MP4 版の動画と WebM 版の動画を取ってきます。それから、{{domxref("blob()", "Body.blob()")}} メソッドを用いて、それぞれの応答の本体をブロブとして抽出します。このブロブは、保存して後で表示することの可能な、動画のオブジェクト表現を与えてくれます。

    + +

    しかし、ここで問題があります。これらの二つの要求はどちらも非同期的なのですが、双方のプロミスが成立 (fulfill) した場合にだけ動画を表示もしくは保存しようと試みたいのです。幸い、そうした問題を扱うビルトイン・メソッドがあります。すなわち  {{jsxref("Promise.all()")}} です。これは一つの引数——成立したかどうかを調べたい個々のプロミスすべてに対する参照を配列に入れたもの——をとり、これ自体がプロミスに基づいています。

    + +

    それらのプロミスすべてが成立したら、成立した個々の値すべてを含む配列をともなって、all() プロミスも成立します。all() のブロック内部では、以前 UI に動画を表示するために行ったのと同様にして displayVideo() 関数を呼び出していること、そして、それらの動画をデータベース内に保存するために storeVideo() 関数も呼び出していることが、お分かりでしょう。

    + +
    let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response =>
    +  response.blob()
    +);
    +let webmBlob = fetch('videos/' + video.name + '.webm').then(response =>
    +  response.blob()
    +);
    +
    +// 双方のプロミスが成立したときのみ、次のコードを実行します。
    +Promise.all([mp4Blob, webmBlob]).then(function(values) {
    +  // ネットワークから取ってきた動画を、displayVideo() により表示します。
    +  displayVideo(values[0], values[1], video.name);
    +  // storeVideo() を用いて、その動画を IDB に保存します。
    +  storeVideo(values[0], values[1], video.name);
    +});
    +
  6. +
  7. +

    まず storeVideo() を見ましょう。これは、データベースにデータを追加するための上記の例で見たパターンに、とてもよく似ています。つまり、readwrite (読み書き) トランザクションを開き、videos に対するオブジェクト・ストア参照を求め、データベースに追加すべきレコードを表すオブジェクトを作成し、それから、{{domxref("IDBObjectStore.add()")}} を用いてそのオブジェクトを単純に追加しています。

    + +
    function storeVideo(mp4Blob, webmBlob, name) {
    +  // トランザクションを開き、オブジェクト・ストアを求めます。IDB に書き込めるようにするために、これは読み書きトランザクションにしておきます。
    +  let objectStore = db.transaction(['videos'], 'readwrite').objectStore('videos');
    +  // IDB に追加するレコードを作成します。
    +  let record = {
    +    mp4 : mp4Blob,
    +    webm : webmBlob,
    +    name : name
    +  }
    +
    +  // add() を使ってレコードを IDB に追加します。
    +  let request = objectStore.add(record);
    +
    +  ...
    +
    +};
    +
  8. +
  9. +

    最後に、displayVideo() があります。これは、UI に動画を挿入するのに必要な DOM 要素を作成してから、それらの DOM 要素をページに追加します。これの一番面白い部分は、以下に示した箇所です。<video> 要素内に動画ブロブを実際に表示するには、{{domxref("URL.createObjectURL()")}} メソッドを使って、オブジェクト URL (メモリに記憶されている動画ブロブを指し示す内部 URL) を作成せねばならないのです。それが済んだら、オブジェクト URL を {{htmlelement("source")}} 要素の src 属性の値として設定できて、物事がうまく機能します。

    + +
    function displayVideo(mp4Blob, webmBlob, title) {
    +  // ブロブからオブジェクト URL を作成します。
    +  let mp4URL = URL.createObjectURL(mp4Blob);
    +  let webmURL = URL.createObjectURL(webmBlob);
    +
    +  ...
    +
    +  const video = document.createElement('video');
    +  video.controls = true;
    +  const source1 = document.createElement('source');
    +  source1.src = mp4URL;
    +  source1.type = 'video/mp4';
    +  const source2 = document.createElement('source');
    +  source2.src = webmURL;
    +  source2.type = 'video/webm';
    +
    +  ...
    +}
    +
  10. +
+ +

オフラインでの資産の保存

+ +

上記の例は、IndexedDB データベース内に大規模な資産を保存するアプリの作り方を既に示しており、こうすることで、それらの大規模な資産を二度以上ダウンロードする必要性をなくしています。これは既にユーザー体験にとっての多大なる進歩ではありますが、まだ一つ欠けていることがあります。すなわち、依然として、主たる HTML と CSS と JavaScript のファイルを、サイトにアクセスするたびにダウンロードせねばならないのです。これが意味することは、ネットワーク接続がない場合にはサイトが動作しないということです。

+ +

+ +

ここは、 サービスワーカー およびそれと緊密に関連した キャッシュ API の出番です。

+ +

サービスワーカーとは、ただ単に置いてあって、特定のオリジン (ウェブサイト、または、あるドメインにあるウェブサイトの一部) に対して、そこにブラウザでアクセスした際に登録される、JavaScript ファイルのことです。登録されれば、サービスワーカーは、当該オリジンで利用可能なページを制御できます。サービスワーカーは、ロードされたページとネットワークとの間に位置して、当該オリジン宛のネットワーク要求を横取りすることにより、こうした制御を行います。

+ +

サービスワーカーが要求を横取りすると、その要求に対して望むことは何でも行えますが (使用例の案 を参照)、典型例では、ネットワーク応答をオフラインに保存しており、その後、要求に応じて、ネットワークからの応答の代わりに、保存してあるそれらの応答を提供しています。これによって事実上、ウェブサイトを完全にオフラインで機能させることが可能になります。

+ +

キャッシュ API は、クライアント側での保存のもう一つの仕組みですが、これにはちょっとした相違点があります。キャッシュ API は HTTP 応答を保存するように設計されているのです。そのため、サービスワーカーと一緒に使うと、とてもうまく機能します。

+ +
+

: サービスワーカーとキャッシュは、現在、ほとんどのモダン・ブラウザーでサポートされています。執筆時点では、Safari はまだ実装するのに忙しかったのですが、もうすぐサポートされるはずです。

+
+ +

サービスワーカーの例

+ +

これがどのような感じなのかについて少しばかりお教えするために、例を見ましょう。前節で見た動画ストアの例の、別のバージョンを作っておきました。このバージョンは、サービスワーカーを介してキャッシュ API で HTML と CSS と JavaScript も保存する点を除いて、同等に機能しますが、この点のおかげで、この例がオフラインで実行できるようになるのです!

+ +

サービスワーカーを用いた IndexedDB 動画ストアがライブで実行中のところ をご覧ください。また、ソースコードも参照してください

+ +

サービスワーカーを登録します

+ +

注意すべき第一の点は、主たる JavaScript ファイル中に追加のコードが少々ある点です (index.js を参照)。まず、{{domxref("Navigator")}} オブジェクトにおいて serviceWorker メンバーが利用可能かどうかを調べる機能検出検査を行います。もしこれが true を返したら、サービスワーカーの少なくとも基本部分がサポートされていることが分かります。ここの内部では、{{domxref("ServiceWorkerContainer.register()")}} メソッドを用いて、sw.js ファイルに含まれるサービスワーカーを、このファイルのあるオリジンに対して登録します。すると、同一ディレクトリまたは下位ディレクトリにあるページを制御できるようになります。このメソッドのプロミスが成立すると、サービスワーカーは登録されたものと見なされます。

+ +
  // サイトがオフラインで動くようにする処理を制御するために、サービスワーカーを登録します。
+
+  if('serviceWorker' in navigator) {
+    navigator.serviceWorker
+             .register('/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js')
+             .then(function() { console.log('Service Worker Registered'); });
+  }
+ +
+

: sw.js ファイルに至るまでの、与えられたパスは、サイト・オリジンに対して相対的なのであり、上記コードを含む JavaScript ファイルに対して相対的なのではありません。サービスワーカーは https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js にあります。オリジンは https://mdn.github.io です。よって、与えられるパスは、/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js でなくてはなりません。もしこの例を御自分のサーバーにホストしたいとお思いでしたら、それに合わせて、ここを変更せねばなりません。これはやや混乱を招くところですが、セキュリティ上の理由から、この方法で動作する必要があるのです。

+
+ +

サービスワーカーをインストールします

+ +

サービスワーカーの制御下にあるいずれかのページが次にアクセスされた際には (たとえば、この例がリロードされたときには)、サービスワーカーがそのページに対してインストールされます。それが意味することは、サービスワーカーがそのページを制御し始めるだろう、ということです。これが起きると、サービスワーカーに対して install イベントを発火させます。サービスワーカー自体の内部には、当該インストールに応じるコードを書くことができます。

+ +

sw.js ファイル (サービスワーカー) 内の例を見てみましょう。self に対して install リスナーが登録されるのがお分かりでしょう。この self というキーワードは、サービスワーカー・ファイルの内部からサービスワーカーのグローバル・スコープを参照する手段です。

+ +

install ハンドラーの内部では、{{domxref("ExtendableEvent.waitUntil()")}}メソッド——イベント・オブジェクト上で使えます——を用いて、当メソッドの内部のプロミスが成功して成立するまではブラウザーはサービスワーカーのインストールを完了させるべきではない、と知らせます。

+ +

ここは、キャッシュ API が動作しているのが見られる箇所です。応答を保存できる新規キャッシュ・オブジェクト (IndexedDB オブジェクト・ストアと似ています) を開くために、{{domxref("CacheStorage.open()")}} メソッドを使います。このプロミスは、video-store というキャッシュを表現する {{domxref("Cache")}} オブジェクトをともなって成立します。その後、一連の資源を取ってきて、その応答をキャッシュに追加するために、{{domxref("Cache.addAll()")}} メソッドを使います。

+ +
self.addEventListener('install', function(e) {
+ e.waitUntil(
+   caches.open('video-store').then(function(cache) {
+     return cache.addAll([
+       '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/',
+       '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.html',
+       '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.js',
+       '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/style.css'
+     ]);
+   })
+ );
+});
+ +

さて、これで終わりです。インストールが済みました。

+ +

さらなる要求に応答します

+ +

HTML ページに対してサービスワーカーが登録されてインストールされ、関連する資産がすべてキャッシュに追加されれば、ほぼ開始準備が整っています。すべきことは、あと一つだけです。つまり、さらなるネットワーク要求に応答するための何らかのコードを書くことです。

+ +

sw.js における第二のちょっとしたコードがしていることは、こうです。すなわち、サービスワーカーのグローバル・スコープにもう一つのリスナーを追加し、これにより、fetch イベントが生じたときにハンドラー関数を実行します。このイベントは、サービスワーカーの登録先のディレクトリ内の資産に対してブラウザーが要求を出す際には、いつでも生じます。

+ +

ハンドラーの内部では、要求された資産の URL をまず記録します。それから、{{domxref("FetchEvent.respondWith()")}} メソッドを使って、その要求に対するカスタム応答を提供します。

+ +

このブロックの内部では、{{domxref("CacheStorage.match()")}} を用いて、マッチング要求 (URL にマッチします) がいずれかのキャッシュの中に見つかるかどうかを調べます。このプロミスは、マッチが見つからなければ (訳注: 正しくは「見つかれば」?) そのマッチする応答をともなって成立し、マッチが見つからなければ undefined となります。

+ +

もしマッチが見つかれば、単純にそれをカスタム応答として返します。もしマッチが見つからなければ、代わりに、ネットワークから応答を fetch() して、それを返します。

+ +
self.addEventListener('fetch', function(e) {
+  console.log(e.request.url);
+  e.respondWith(
+    caches.match(e.request).then(function(response) {
+      return response || fetch(e.request);
+    })
+  );
+});
+ +

これで私たちの単純なサービスワーカーは終わりです。サービスワーカーを使ってできる、もっと多くのことがありますが、より詳しくは、service worker cookbook を参照してください。また、ウェブアプリへの Service Worker とオフラインの追加 という記事について、著者の Paul Kinlan さんに感謝します。あの記事のおかげで、この単純な例の着想を得られました。

+ +

この例をオフラインで試します

+ +

サービスワーカー の例 を試すには、それが確実にインストールされるように、二、三度ロードする必要があるでしょう。それが済んだら、以下のことができます。

+ + + +

この例のページをもう一度リフレッシュすれば、当該ページが依然として、まさに申し分なくロードされているところを見ることになるはずです。あらゆるものがオフラインに保存されています。すなわち、ページ資産はキャッシュに保存されており、動画は IndexedDB データベースに保存されています。

+ +

まとめ

+ +

これで終わりです。クライアント側での保存の技術についてのこの概要を、皆さんが有用だと思ってくださったのであれば良いな、と望んでいます。

+ +

あわせて参照

+ + + +

{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}

+ +

このモジュール

+ +
+ +
diff --git a/files/ja/learn/javascript/client-side_web_apis/drawing_graphics/index.html b/files/ja/learn/javascript/client-side_web_apis/drawing_graphics/index.html new file mode 100644 index 0000000000..86c19aa6bb --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/drawing_graphics/index.html @@ -0,0 +1,879 @@ +--- +title: グラフィックの描画 +slug: Learn/JavaScript/Client-side_web_APIs/Drawing_graphics +tags: + - API + - Article + - Beginner + - Canvas + - CodingScripting + - Graphics + - JavaScript + - Learn + - WebGL +translation_of: Learn/JavaScript/Client-side_web_APIs/Drawing_graphics +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

ブラウザーには Scalable Vector Graphics (SVG) 言語から、HTML {{htmlelement("canvas")}} 要素へ描画するための API (The Canvas API と WebGL を参照) まで、非常に強力なグラフィックプログラミングツールが含まれています。
+ この記事では、canvas の概要とさらに詳細を学ぶためのリソースについて説明します。

+ + + + + + + + + + + + +
前提条件:JavaScript basics (see first steps, building blocks, JavaScript objects), the basics of Client-side APIs
目標:JavaScript を使用して <canvas> 要素に描画するための基本を学ぶ。
+ +

Webでのグラフィック

+ +

As we talked about in our HTML Multimedia and embedding module, the Web was originally just text, which was very boring, so images were introduced — first via the {{htmlelement("img")}} element and later via CSS properties such as {{cssxref("background-image")}}, and SVG.

+ +

This however was still not enough. While you could use CSS and JavaScript to animate (and otherwise manipulate) SVG vector images — as they are represented by markup — there was still no way to do the same for bitmap images, and the tools available were rather limited. The Web still had no way to effectively create animations, games, 3D scenes, and other requirements commonly handled by lower level languages such as C++ or Java.

+ +

The situation started to improve when browsers began to support the {{htmlelement("canvas")}} element and associated Canvas API — Apple invented it in around 2004, and other browsers followed by implementing it in the years that followed. As you'll see below, canvas provides many useful tools for creating 2D animations, games, data visualizations, and other types of app, especially when combined with some of the other APIs the web platform provides.

+ +

The below example shows a simple 2D canvas-based bouncing balls animation that we originally met in our Introducing JavaScript objects module:

+ +

{{EmbedGHLiveSample("learning-area/javascript/oojs/bouncing-balls/index-finished.html", '100%', 500)}}

+ +

Around 2006–2007, Mozilla started work on an experimental 3D canvas implementation. This became WebGL, which gained traction among browser vendors, and was standardized around 2009–2010. WebGL allows you to create real 3D graphics inside your web browser; the below example shows a simple rotating WebGL cube:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}}

+ +

This article will focus mainly on 2D canvas, as raw WebGL code is very complex. We will however show how to use a WebGL library to create a 3D scene more easily, and you can find a tutorial covering raw WebGL elsewhere — see Getting started with WebGL.

+ +
+

: Basic canvas functionality is supported well across browsers, with the exception of IE 8 and below for 2D canvas, and IE 11 and below for WebGL.

+
+ +

アクティブラーニング: <canvas>を始めよう

+ +

If you want to create a 2D or 3D scene on a web page, you need to start with an HTML {{htmlelement("canvas")}} element. This element is used to define the area on the page into which the image will be drawn. This is as simple as including the element on the page:

+ +
<canvas width="320" height="240"></canvas>
+ +

This will create a canvas on the page with a size of 320 by 240 pixels.

+ +

Inside the canvas tags, you can put some fallback content, which is shown if the user's browser doesn't support canvas.

+ +
<canvas width="320" height="240">
+  <p>Your browser doesn't support canvas. Boo hoo!</p>
+</canvas>
+ +

Of course, the above message is really unhelpful! In a real example you'd want to relate the fallback content to the canvas content. 例えば、if you were rendering a constantly updating graph of stock prices, the fallback content could be a static image of the latest stock graph, with alt text saying what the prices are in text.

+ +

canvasの作成とサイズ変更

+ +

Let's start by creating our own canvas that we draw future experiments on to.

+ +
    +
  1. +

    First make a local copy of our 0_canvas_start.html file, and open it in your text editor.

    +
  2. +
  3. +

    Add the following code into it, just below the opening {{htmlelement("body")}} tag:

    + +
    <canvas class="myCanvas">
    +  <p>Add suitable fallback here.</p>
    +</canvas>
    + +

    We have added a class to the <canvas> element so it will be easier to select if we have multiple canvases on the page, but we have removed the width and height attributes for now (you could add them back in if you wanted, but we will set them using JavaScript in a below section). Canvases with no explicit width and height default to 300 pixels wide by 150 pixels high.

    +
  4. +
  5. +

    Now add the following lines of JavaScript inside the {{htmlelement("script")}} element:

    + +
    const canvas = document.querySelector('.myCanvas');
    +const width = canvas.width = window.innerWidth;
    +const height = canvas.height = window.innerHeight;
    + +

    Here we have stored a reference to the canvas in the canvas constant. In the second line we set both a new constant width and the canvas' width property equal to {{domxref("Window.innerWidth")}} (which gives us the viewport width). In the third line we set both a new constant height and the canvas' height property equal to {{domxref("Window.innerHeight")}} (which gives us the viewport height). So now we have a canvas that fills the entire width and height of the browser window!

    + +

    You'll also see that we are chaining assignments together with multiple equals signs — this is allowed in JavaScript, and it is a good technique if you want to make multiple variables all equal to the same value. We wanted to make the canvas width and height easily accessible in the width/height variables, as they are useful values to have available for later (例えば、if you want to draw something exactly halfway across the width of the canvas).

    +
  6. +
  7. +

    If you save and load your example in a browser now, you'll see nothing, which is fine, but you'll also see scrollbars — this is a problem for us, which happens because the {{htmlelement("body")}} element has a {{cssxref("margin")}} that, added to our full-window-size canvas, results in a document that's wider than the window. To get rid of the scrollbars, we need to remove the {{cssxref("margin")}} and also set {{cssxref("overflow")}} to hidden. Add the following into the {{htmlelement("head")}} of your document:

    + +
    <style>
    +  body {
    +    margin: 0;
    +    overflow: hidden;
    +  }
    +</style>
    + +

    The scrollbars should now be gone.

    +
  8. +
+ +
+

: You should generally set the size of the image using HTML attributes or DOM properties, as explained above. You could use CSS, but the trouble then is that the sizing is done after the canvas has rendered, and just like any other image (the rendered canvas is just an image), the image could become pixellated/distorted.

+
+ +

canvasコンテキストと最終セットアップを取得する

+ +

We need to do one final thing before we can consider our canvas template finished. To draw onto the canvas we need to get a special reference to the drawing area called a context. This is done using the {{domxref("HTMLCanvasElement.getContext()")}} method, which for basic usage takes a single string as a parameter representing the type of context you want to retrieve.

+ +

In this case we want a 2d canvas, so add the following JavaScript line below the others inside the <script> element:

+ +
const ctx = canvas.getContext('2d');
+ +
+

: other context values you could choose include webgl for WebGL, webgl2 for WebGL 2, etc., but we won't need those in this article.

+
+ +

So that's it — our canvas is now primed and ready for drawing on! The ctx variable now contains a {{domxref("CanvasRenderingContext2D")}} object, and all drawing operations on the canvas will involve manipulating this object.

+ +

Let's do one last thing before we move on. We'll color the canvas background black to give you a first taste of the canvas API. Add the following lines at the bottom of your JavaScript:

+ +
ctx.fillStyle = 'rgb(0, 0, 0)';
+ctx.fillRect(0, 0, width, height);
+ +

Here we are setting a fill color using the canvas' {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}} property (this takes color values just like CSS properties do), then drawing a rectangle that covers the entire area of the canvas with the{{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}} method (the first two parameters are the coordinates of the rectangle's top left hand corner; the last two are the width and height you want the rectangle drawn at — we told you those width and height variables would be useful)!

+ +

OK, our template is done and it's time to move on.

+ +

2D canvas の基本

+ +

As we said above, all drawing operations are done by manipulating a {{domxref("CanvasRenderingContext2D")}} object (in our case, ctx). Many operations need to be given coordinates to pinpoint exactly where to draw something — the top left of the canvas is point (0, 0), the horizontal (x) axis runs from left to right, and the vertical (y) axis runs from top to bottom.

+ +

+ +

Drawing shapes tends to be done using the rectangle shape primitive, or by tracing a line along a certain path and then filling in the shape. Below we'll show how to do both.

+ +

簡単な矩形

+ +

Let's start with some simple rectangles.

+ +
    +
  1. +

    First of all, take a copy of your newly coded canvas template (or make a local copy of 1_canvas_template.html if you didn't follow the above steps).

    +
  2. +
  3. +

    Next, add the following lines to the bottom of your JavaScript:

    + +
    ctx.fillStyle = 'rgb(255, 0, 0)';
    +ctx.fillRect(50, 50, 100, 150);
    + +

    If you save and refresh, you should see a red rectangle has appeared on your canvas. Its top left corner is 50 pixels away from the top and left of the canvas edge (as defined by the first two parameters), and it is 100 pixels wide and 150 pixels tall (as defined by the third and fourth parameters).

    +
  4. +
  5. +

    Let's add another rectangle into the mix — a green one this time. Add the following at the bottom of your JavaScript:

    + +
    ctx.fillStyle = 'rgb(0, 255, 0)';
    +ctx.fillRect(75, 75, 100, 100);
    + +

    Save and refresh, and you'll see your new rectangle. This raises an important point: graphics operations like drawing rectangles, lines, and so forth are performed in the order in which they occur. Think of it like painting a wall, where each coat of paint overlaps and may even hide what's underneath. You can't do anything to change this, so you have to think carefully about the order in which you draw the graphics.

    +
  6. +
  7. +

    Note that you can draw semi-transparent graphics by specifying a semi-transparent color, 例えば、by using rgba(). The a value defines what's called the "alpha channel, " or the amount of transparency the color has. The higher its value, the more it will obscure whatever's behind it. Add the following to your code:

    + +
    ctx.fillStyle = 'rgba(255, 0, 255, 0.75)';
    +ctx.fillRect(25, 100, 175, 50);
    +
  8. +
  9. +

    Now try drawing some more rectangles of your own; have fun!

    +
  10. +
+ +

ストロークと線の幅

+ +

So far we've looked at drawing filled rectangles, but you can also draw rectangles that are just outlines (called strokes in graphic design). To set the color you want for your stroke, you use the {{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle")}} property; drawing a stroke rectangle is done using {{domxref("CanvasRenderingContext2D.strokeRect", "strokeRect")}}.

+ +
    +
  1. +

    Add the following to the previous example, again below the previous JavaScript lines:

    + +
    ctx.strokeStyle = 'rgb(255, 255, 255)';
    +ctx.strokeRect(25, 25, 175, 200);
    +
  2. +
  3. +

    The default width of strokes is 1 pixel; you can adjust the {{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth")}} property value to change this (it takes a number representing the number of pixels wide the stroke is). Add the following line in between the previous two lines:

    + +
    ctx.lineWidth = 5;
    +
  4. +
+ +

Now you should see that your white outline has become much thicker! That's it for now. At this point your example should look like this:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/2_canvas_rectangles.html", '100%', 250)}}

+ +
+

: The finished code is available on GitHub as 2_canvas_rectangles.html.

+
+ +

パスの描画

+ +

If you want to draw anything more complex than a rectangle, you need to draw a path. Basically, this involves writing code to specify exactly what path the pen should move along on your canvas to trace the shape you want to draw. Canvas includes functions for drawing straight lines, circles, Bézier curves, and more.

+ +

Let's start the section off by making a fresh copy of our canvas template (1_canvas_template.html), in which to draw the new example.

+ +

We'll be using some common methods and properties across all of the below sections:

+ + + +

A typical, simple path-drawing operation would look something like so:

+ +
ctx.fillStyle = 'rgb(255, 0, 0)';
+ctx.beginPath();
+ctx.moveTo(50, 50);
+// draw your path
+ctx.fill();
+ +

線を描く

+ +

Let's draw an equilateral triangle on the canvas.

+ +
    +
  1. +

    First of all, add the following helper function to the bottom of your code. This converts degree values to radians, which is useful because whenever you need to provide an angle value in JavaScript, it will nearly always be in radians, but humans usually think in degrees.

    + +
    function degToRad(degrees) {
    +  return degrees * Math.PI / 180;
    +};
    +
  2. +
  3. +

    Next, start off your path by adding the following below your previous addition; here we set a color for our triangle, start drawing a path, and then move the pen to (50, 50) without drawing anything. That's where we'll start drawing our triangle.

    + +
    ctx.fillStyle = 'rgb(255, 0, 0)';
    +ctx.beginPath();
    +ctx.moveTo(50, 50);
    +
  4. +
  5. +

    Now add the following lines at the bottom of your script:

    + +
    ctx.lineTo(150, 50);
    +let triHeight = 50 * Math.tan(degToRad(60));
    +ctx.lineTo(100, 50+triHeight);
    +ctx.lineTo(50, 50);
    +ctx.fill();
    + +

    Let's run through this in order:

    + +

    First we draw a line across to (150, 50) — our path now goes 100 pixels to the right along the x axis.

    + +

    Second, we work out the height of our equalateral triangle, using a bit of simple trigonometry. Basically, we are drawing the triangle pointing downwards. The angles in an equalateral triangle are always 60 degrees; to work out the height we can split it down the middle into two right-angled triangles, which will each have angles of 90 degrees, 60 degrees, and 30 degrees. In terms of the sides:

    + +
      +
    • The longest side is called the hypotenuse
    • +
    • The side next to the 60 degree angle is called the adjacent — which we know is 50 pixels, as it is half of the line we just drew.
    • +
    • The side opposite the 60 degree angle is called the opposite, which is the height of the triangle we want to calculate.
    • +
    + +

    + +

    One of the basic trigonometric formulae states that the length of the adjacent multiplied by the tangent of the angle is equal to the opposite, hence we come up with 50 * Math.tan(degToRad(60)). We use our degToRad() function to convert 60 degrees to radians, as {{jsxref("Math.tan()")}} expects an input value in radians.

    +
  6. +
  7. +

    With the height calculated, we draw another line to (100, 50 + triHeight). The X coordinate is simple; it must be halfway between the previous two X values we set. The Y value on the other hand must be 50 plus the triangle height, as we know the top of the triangle is 50 pixels from the top of the canvas.

    +
  8. +
  9. +

    The next line draws a line back to the starting point of the triangle.

    +
  10. +
  11. +

    Last of all, we run ctx.fill() to end the path and fill in the shape.

    +
  12. +
+ +

円を描く

+ +

Now let's look at how to draw a circle in canvas. This is accomplished using the {{domxref("CanvasRenderingContext2D.arc", "arc()")}} method, which draws all or part of a circle at a specified point.

+ +
    +
  1. +

    Let's add an arc to our canvas — add the following to the bottom of your code:

    + +
    ctx.fillStyle = 'rgb(0, 0, 255)';
    +ctx.beginPath();
    +ctx.arc(150, 106, 50, degToRad(0), degToRad(360), false);
    +ctx.fill();
    + +

    arc() takes six parameters. The first two specify the position of the arc's center (X and Y, respectively). The third is the circle's radius, the fourth and fifth are the start and end angles at which to draw the circle (so specifying 0 and 360 degrees gives us a full circle), and the sixth parameter defines whether the circle should be drawn counterclockwise (anticlockwise) or clockwise (false is clockwise).

    + +
    +

    : 0 degrees is horizontally to the right.

    +
    +
  2. +
  3. +

    Let's try adding another arc:

    + +
    ctx.fillStyle = 'yellow';
    +ctx.beginPath();
    +ctx.arc(200, 106, 50, degToRad(-45), degToRad(45), true);
    +ctx.lineTo(200, 106);
    +ctx.fill();
    + +

    The pattern here is very similar, but with two differences:

    + +
      +
    • We have set the last parameter of arc() to true, meaning that the arc is drawn counterclockwise, which means that even though the arc is specified as starting at -45 degrees and ending at 45 degrees, we draw the arc around the 270 degrees not inside this portion. If you were to change true to false and then re-run the code, only the 90 degree slice of the circle would be drawn.
    • +
    • Before calling fill(), we draw a line to the center of the circle. This means that we get the rather nice Pac-Man-style cutout rendered. If you removed this line (try it!) then re-ran the code, you'd get just an edge of the circle chopped off between the start and end point of the arc. This illustrates another important point of the canvas — if you try to fill an incomplete path (i.e. one that is not closed), the browser fills in a straight line between the start and end point and then fills it in.
    • +
    +
  4. +
+ +

That's it for now; your final example should look like this:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/3_canvas_paths.html", '100%', 200)}}

+ +
+

: The finished code is available on GitHub as 3_canvas_paths.html.

+
+ +
+

: To find out more about advanced path drawing features such as Bézier curves, check out our Drawing shapes with canvas tutorial.

+
+ +

テキスト

+ +

Canvas also has features for drawing text. Let's explore these briefly. Start by making another fresh copy of our canvas template (1_canvas_template.html) in which to draw the new example.

+ +

Text is drawn using two methods:

+ + + +

Both of these take three properties in their basic usage: the text string to draw and the X and Y coordinates of the point to start drawing the text at. This works out as the bottom left corner of the text box (literally, the box surrounding the text you draw), which might confuse you as other drawing operations tend to start from the top left corner — bear this in mind.

+ +

There are also a number of properties to help control text rendering such as {{domxref("CanvasRenderingContext2D.font", "font")}}, which lets you specify font family, size, etc. It takes as its value the same syntax as the CSS {{cssxref("font")}} property.

+ +

Try adding the following block to the bottom of your JavaScript:

+ +
ctx.strokeStyle = 'white';
+ctx.lineWidth = 1;
+ctx.font = '36px arial';
+ctx.strokeText('Canvas text', 50, 50);
+
+ctx.fillStyle = 'red';
+ctx.font = '48px georgia';
+ctx.fillText('Canvas text', 50, 150);
+ +

Here we draw two lines of text, one outline and the other stroke. The final example should look like so:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/4_canvas_text.html", '100%', 180)}}

+ +
+

: The finished code is available on GitHub as 4_canvas_text.html.

+
+ +

Have a play and see what you can come up with! You can find more information on the options available for canvas text at Drawing text.

+ +

canvasに画像を描画する

+ +

It is possible to render external images onto your canvas. These can be simple images, frames from videos, or the content of other canvases. For the moment we'll just look at the case of using some simple images on our canvas.

+ +
    +
  1. +

    As before, make another fresh copy of our canvas template (1_canvas_template.html) in which to draw the new example. In this case you'll also need to save a copy of our sample image — firefox.png — in the same directory.

    + +

    Images are drawn onto canvas using the {{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}} method. The simplest version takes three parameters — a reference to the image you want to render, and the X and Y coordinates of the image's top left corner.

    +
  2. +
  3. +

    Let's start by getting an image source to embed in our canvas. Add the following lines to the bottom of your JavaScript:

    + +
    let image = new Image();
    +image.src = 'firefox.png';
    + +

    Here we create a new {{domxref("HTMLImageElement")}} object using the {{domxref("HTMLImageElement.Image()", "Image()")}} constructor. The returned object is the same type as that which is returned when you grab a reference to an existing {{htmlelement("img")}} element). We then set its {{htmlattrxref("src", "img")}} attribute to equal our Firefox logo image. At this point, the browser starts loading the image.

    +
  4. +
  5. +

    We could now try to embed the image using drawImage(), but we need to make sure the image file has been loaded first, otherwise the code will fail. We can achieve this using the onload event handler, which will only be invoked when the image has finished loading. Add the following block below the previous one:

    + +
    image.onload = function() {
    +  ctx.drawImage(image, 50, 50);
    +}
    + +

    If you load your example in the browser now, you should see the image embeded in the canvas.

    +
  6. +
  7. +

    But there's more! What if we want to display only a part of the image, or to resize it? We can do both with the more complex version of drawImage(). Update your ctx.drawImage() line like so:

    + +
    ctx.drawImage(image, 20, 20, 185, 175, 50, 50, 185, 175);
    + +
      +
    • The first parameter is the image reference, as before.
    • +
    • Parameters 2 and 3 define the coordinates of the top left corner of the area you want to cut out of the loaded image, relative to the top-left corner of the image itself. Nothing to the left of the first parameter or above the second will be drawn.
    • +
    • Parameters 4 and 5 define the width and height of the area we want to cut out from the original image we loaded.
    • +
    • Parameters 6 and 7 define the coordinates at which you want to draw the top-left corner of the cut-out portion of the image, relative to the top-left corner of the canvas.
    • +
    • Parameters 8 and 9 define the width and height to draw the cut-out area of the image. In this case, we have specified the same dimensions as the original slice, but you could resize it by specifying different values.
    • +
    +
  8. +
+ +

The final example should look like so:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/5_canvas_images.html", '100%', 260)}}

+ +
+

: The finished code is available on GitHub as 5_canvas_images.html.

+
+ +

ループとアニメーション

+ +

We have so far covered some very basic uses of 2D canvas, but really you won't experience the full power of canvas unless you update or animate it in some way. After all, canvas does provide scriptable images! If you aren't going to change anything, then you might as well just use static images and save yourself all the work.

+ +

ループの作成

+ +

Playing with loops in canvas is rather fun — you can run canvas commands inside a for (or other type of) loop just like any other JavaScript code.

+ +

Let's build a simple example.

+ +
    +
  1. +

    Make another fresh copy of our canvas template (1_canvas_template.html) and open it in your code editor.

    +
  2. +
  3. +

    Add the following line to the bottom of your JavaScript. This contains a new method, {{domxref("CanvasRenderingContext2D.translate", "translate()")}}, which moves the origin point of the canvas:

    + +
    ctx.translate(width/2, height/2);
    + +

    This causes the coordinate origin (0, 0) to be moved to the center of the canvas, rather than being at the top left corner. This is very useful in many situations, like this one, where we want our design to be drawn relative to the center of the canvas.

    +
  4. +
  5. +

    Now add the following code to the bottom of the JavaScript:

    + +
    function degToRad(degrees) {
    +  return degrees * Math.PI / 180;
    +};
    +
    +function rand(min, max) {
    +  return Math.floor(Math.random() * (max-min+1)) + (min);
    +}
    +
    +let length = 250;
    +let moveOffset = 20;
    +
    +for(var i = 0; i < length; i++) {
    +
    +}
    + +

    Here we are implementing the same degToRad() function we saw in the triangle example above, a rand() function that returns a random number between given lower and upper bounds, length and moveOffset variables (which we'll find out more about later), and an empty for loop.

    +
  6. +
  7. +

    The idea here is that we'll draw something on the canvas inside the for loop, and iterate on it each time so we can create something interesting. Add the following code inside your for loop:

    + +
    ctx.fillStyle = 'rgba(' + (255-length) + ', 0, ' + (255-length) + ', 0.9)';
    +ctx.beginPath();
    +ctx.moveTo(moveOffset, moveOffset);
    +ctx.lineTo(moveOffset+length, moveOffset);
    +let triHeight = length/2 * Math.tan(degToRad(60));
    +ctx.lineTo(moveOffset+(length/2), moveOffset+triHeight);
    +ctx.lineTo(moveOffset, moveOffset);
    +ctx.fill();
    +
    +length--;
    +moveOffset += 0.7;
    +ctx.rotate(degToRad(5));
    + +

    So on each iteration, we:

    + +
      +
    • Set the fillStyle to be a shade of slightly transparent purple, which changes each time based on the value of length. As you'll see later the length gets smaller each time the loop runs, so the effect here is that the color gets brighter with each successive triangle drawn.
    • +
    • Begin the path.
    • +
    • Move the pen to a coordinate of (moveOffset, moveOffset); This variable defines how far we want to move each time we draw a new triangle.
    • +
    • Draw a line to a coordinate of (moveOffset+length, moveOffset). This draws a line of length length parallel to the X axis.
    • +
    • Calculate the triangle's height, as before.
    • +
    • Draw a line to the downward-pointing corner of the triangle, then draw a line back to the start of the triangle.
    • +
    • Call fill() to fill in the triangle.
    • +
    • Update the variables that describe the sequence of triangles, so we can be ready to draw the next one. We decrease the length value by 1, so the triangles get smaller each time; increase moveOffset by a small amount so each successive triangle is slightly further away, and use another new function, {{domxref("CanvasRenderingContext2D.rotate", "rotate()")}}, which allows us to rotate the entire canvas! We rotate it by 5 degrees before drawing the next triangle.
    • +
    +
  8. +
+ +

That's it! The final example should look like so:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/6_canvas_for_loop.html", '100%', 550)}}

+ +

At this point, we'd like to encourage you to play with the example and make it your own! 例えば、:

+ + + +
+

: The finished code is available on GitHub as 6_canvas_for_loop.html.

+
+ +

アニメーション

+ +

The loop example we built above was fun, but really you need a constant loop that keeps going and going for any serious canvas applications (such as games and real time visualizations). If you think of your canvas as being like a movie, you really want the display to update on each frame to show the updated view, with an ideal refresh rate of 60 frames per second so that movement appears nice and smooth to the human eye.

+ +

There are a few JavaScript functions that will allow you to run functions repeatedly, several times a second, the best one for our purposes here being {{domxref("window.requestAnimationFrame()")}}. It takes one parameter — the name of the function you want to run for each frame. The next time the browser is ready to update the screen, your function will get called. If that function draws the new update to your animation, then calls requestAnimationFrame() again just before the end of the function, the animation loop will continue to run. The loop ends when you stop calling requestAnimationFrame() or if you call {{domxref("window.cancelAnimationFrame()")}} after calling requestAnimationFrame() but before the frame is called.

+ +
+

注: It's good practice to call cancelAnimationFrame() from your main code when you're done using the animation, to ensure that no updates are still waiting to be run.

+
+ +

The browser works out complex details such as making the animation run at a consistent speed, and not wasting resources animating things that can't be seen.

+ +

To see how it works, let's quickly look again at our Bouncing Balls example (see it live, and also see the source code). The code for the loop that keeps everything moving looks like this:

+ +
function loop() {
+  ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
+  ctx.fillRect(0, 0, width, height);
+
+  for(let i = 0; i < balls.length; i++) {
+    balls[i].draw();
+    balls[i].update();
+    balls[i].collisionDetect();
+  }
+
+  requestAnimationFrame(loop);
+}
+
+loop();
+ +

We run the loop() function once at the bottom of the code to start the cycle, drawing the first animation frame; the loop() function then takes charge of calling requestAnimationFrame(loop) to run the next frame of the animation, again and again.

+ +

Note that on each frame we are completely clearing the canvas and redrawing everything. For every ball present we draw it, update its position, and check to see if it is colliding with any other balls. Once you've drawn a graphic to a canvas, there's no way to manipulate that graphic individually like you can with DOM elements. You can't move each ball around on the canvas, because once it's drawn, it's part of the canvas, and is not an individual accessible element or object. Instead, you have to erase and redraw, either by erasing the entire frame and redrawing everything, or by having code that knows exactly what parts need to be erased and only erases and redraws the minimum area of the canvas necessary.

+ +

Optimizing animation of graphics is an entire specialty of programming, with lots of clever techniques available. Those are beyond what we need for our example, though!

+ +

In general, the process of doing a canvas animation involves the following steps:

+ +
    +
  1. Clear the canvas contents (e.g. with {{domxref("CanvasRenderingContext2D.fillRect", "fillRect()")}} or {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}).
  2. +
  3. Save state (if necessary) using {{domxref("CanvasRenderingContext2D.save", "save()")}} — this is needed when you want to save settings you've updated on the canvas before continuing, which is useful for more advanced applications.
  4. +
  5. Draw the graphics you are animating.
  6. +
  7. Restore the settings you saved in step 2, using {{domxref("CanvasRenderingContext2D.restore", "restore()")}}
  8. +
  9. Call requestAnimationFrame() to schedule drawing of the next frame of the animation.
  10. +
+ +
+

: We won't cover save() and restore() here, but they are explained nicely in our Transformations tutorial (and the ones that follow it).

+
+ +

簡単なキャラクターのアニメーション

+ +

Now let's create our own simple animation — we'll get a character from a certain rather awesome retro computer game to walk across the screen.

+ +
    +
  1. +

    Make another fresh copy of our canvas template (1_canvas_template.html) and open it in your code editor. Make a copy of walk-right.png in the same directory.

    +
  2. +
  3. +

    At the bottom of the JavaScript, add the following line to once again make the coordinate origin sit in the middle of the canvas:

    + +
    ctx.translate(width/2, height/2);
    +
  4. +
  5. +

    Now let's create a new {{domxref("HTMLImageElement")}} object, set its {{htmlattrxref("src", "img")}} to the image we want to load, and add an onload event handler that will cause the draw() function to fire when the image is loaded:

    + +
    let image = new Image();
    +image.src = 'walk-right.png';
    +image.onload = draw;
    +
  6. +
  7. +

    Now we'll add some variables to keep track of the position the sprite is to be drawn on the screen, and the sprite number we want to display.

    + +
    let sprite = 0;
    +let posX = 0;
    + +

    Let's explain the spritesheet image (which we have respectfully borrowed from Mike Thomas' Create a sprite sheet walk cycle using using CSS animation). The image looks like this:

    + +

    + +

    It contains six sprites that make up the whole walking sequence — each one is 102 pixels wide and 148 pixels high. To display each sprite cleanly we will have to use drawImage() to chop out a single sprite image from the spritesheet and display only that part, like we did above with the Firefox logo. The X coordinate of the slice will have to be a multiple of 102, and the Y coordinate will always be 0. The slice size will always be 102 by 148 pixels.

    +
  8. +
  9. +

    Now let's insert an empty draw() function at the bottom of the code, ready for filling up with some code:

    + +
    function draw() {
    +
    +};
    +
  10. +
  11. +

    the rest of the code in this section goes inside draw(). First, add the following line, which clears the canvas to prepare for drawing each frame. Notice that we have to specify the top-left corner of the rectangle as -(width/2), -(height/2) because we specified the origin position as width/2, height/2 earlier on.

    + +
    ctx.fillRect(-(width/2), -(height/2), width, height);
    +
  12. +
  13. +

    Next, we'll draw our image using drawImage — the 9-parameter version. Add the following:

    + +
    ctx.drawImage(image, (sprite*102), 0, 102, 148, 0+posX, -74, 102, 148);
    + +

    As you can see:

    + +
      +
    • We specify image as the image to embed.
    • +
    • Parameters 2 and 3 specify the top-left corner of the slice to cut out of the source image, with the X value as sprite multiplied by 102 (where sprite is the sprite number between 0 and 5) and the Y value always 0.
    • +
    • Parameters 4 and 5 specify the size of the slice to cut out — 102 pixels by 148 pixels.
    • +
    • Parameters 6 and 7 specify the top-left corner of the box into which to draw the slice on the canvas — the X position is 0 + posX, meaning that we can alter the drawing position by altering the posX value.
    • +
    • Parameters 8 and 9 specify the size of the image on the canvas. We just want to keep its original size, so we specify 102 and 148 as the width and height.
    • +
    +
  14. +
  15. +

    Now we'll alter the sprite value after each draw — well, after some of them anyway. Add the following block to the bottom of the draw() function:

    + +
      if (posX % 13 === 0) {
    +    if (sprite === 5) {
    +      sprite = 0;
    +    } else {
    +      sprite++;
    +    }
    +  }
    + +

    We are wrapping the whole block in if (posX % 13 === 0) { ... }. We use the modulo (%) operator (also known as the remainder operator) to check whether the posX value can be exactly divided by 13 with no remainder. If so, we move on  to the next sprite by incrementing sprite (wrapping to 0 after we're done with sprite #5). This effectively means that we are only updating the sprite on every 13th frame, or roughly about 5 frames a second (requestAnimationFrame() calls us at up to 60 frames per second if possible). We are deliberately slowing down the frame rate because we only have six sprites to work with, and if we display one every 60th of a second, our character will move way too fast!

    + +

    Inside the outer block we use an if ... else statement to check whether the sprite value is at 5 (the last sprite, given that the sprite numbers run from 0 to 5). If we are showing the last sprite already, we reset sprite back to 0; if not we just increment it by 1.

    +
  16. +
  17. +

    Next we need to work out how to change the posX value on each frame — add the following code block just below your last one. 

    + +
      if(posX > width/2) {
    +    newStartPos = -((width/2) + 102);
    +    posX = Math.ceil(newStartPos);
    +    console.log(posX);
    +  } else {
    +    posX += 2;
    +  }
    + +

    We are using another if ... else statement to see if the value of posX has become greater than width/2, which means our character has walked off the right edge of the screen. If so, we calculate a position that would put the character just to the left of the left side of the screen.

    + +

    If our character hasn't yet walked off the edge of the screen, we simply increment posX by 2. This will make him move a little bit to the right the next time we draw him.

    +
  18. +
  19. +

    Finally, we need to make the animation loop by calling {{domxref("window.requestAnimationFrame", "requestAnimationFrame()")}} at the bottom of the draw() function:

    + +
    window.requestAnimationFrame(draw);
    +
  20. +
+ +

That's it! The final example should look like so:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}

+ +
+

: The finished code is available on GitHub as 7_canvas_walking_animation.html.

+
+ +

簡単なドローアプリ

+ +

As a final animation example, we'd like to show you a very simple drawing application, to illustrate how the animation loop can be combined with user input (like mouse movement, in this case). We won't get you to walk through and build this one; we'll just explore the most interesting parts of the code.

+ +

The example can be found on GitHub as 8_canvas_drawing_app.html, and you can play with it live below:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html", '100%', 600)}}

+ +

Let's look at the most interesting parts. First of all, we keep track of the mouse's X and Y coordinates and whether it is being clicked or not with three variables: curX, curY, and pressed. When the mouse moves, we fire a function set as the onmousemove event handler, which captures the current X and Y values. We also use onmousedown and onmouseup event handlers to change the value of pressed to true when the mouse button is pressed, and back to false again when it is released.

+ +
let curX;
+let curY;
+let pressed = false;
+
+document.onmousemove = function(e) {
+  curX = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+  curY = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+}
+
+canvas.onmousedown = function() {
+  pressed = true;
+};
+
+canvas.onmouseup = function() {
+  pressed = false;
+}
+ +

When the "Clear canvas" button is pressed, we run a simple function that clears the whole canvas back to black, the same way we've seen before:

+ +
clearBtn.onclick = function() {
+  ctx.fillStyle = 'rgb(0, 0, 0)';
+  ctx.fillRect(0, 0, width, height);
+}
+ +

The drawing loop is pretty simple this time around — if pressed is true, we draw a circle with a fill style equal to the value in the color picker, and a radius equal to the value set in the range input. We have to draw the circle 85 pixels above where we measured it from, because the vertical measurement is taken from the top of the viewport, but we are drawing the circle relative to the top of the canvas, which starts below the 85 pixel-high toolbar. If we drew it with just curY as the y coordinate, it would appear 85 pixels lower than the mouse position.

+ +
function draw() {
+  if(pressed) {
+    ctx.fillStyle = colorPicker.value;
+    ctx.beginPath();
+    ctx.arc(curX, curY-85, sizePicker.value, degToRad(0), degToRad(360), false);
+    ctx.fill();
+  }
+
+  requestAnimationFrame(draw);
+}
+
+draw();
+ +
+

: The {{htmlelement("input")}} range and color types are supported fairly well across browsers, with the exception of Internet Explorer versions less than 10; also Safari doesn't yet support color. If your browser doesn't support these inputs, they will fall back to simple text fields and you'll just have to enter valid color/number values yourself.

+
+ +

WebGL

+ +

It's now time to leave 2D behind, and take a quick look at 3D canvas. 3D canvas content is specified using the WebGL API, which is a completely separate API from the 2D canvas API, even though they both render onto {{htmlelement("canvas")}} elements.

+ +

WebGL is based on OpenGL (Open Graphics Library), and allows you to communicate directly with the computer's GPU. As such, writing raw WebGL is closer to low level languages such as C++ than regular JavaScript; it is quite complex but incredibly powerful.

+ +

ライブラリーの使用

+ +

Because of its complexity, most people write 3D graphics code using a third party JavaScript library such as Three.js, PlayCanvas, or Babylon.js. Most of these work in a similar way, providing functionality to create primitive and custom shapes, position viewing cameras and lighting, covering surfaces with textures, and more. They handle the WebGL for you, letting you work on a higher level.

+ +

Yes, using one of these means learning another new API (a third party one, in this case), but they are a lot simpler than coding raw WebGL.

+ +

立方体を作成する

+ +

Let's look at a simple example of how to create something with a WebGL library. We'll choose Three.js, as it is one of the most popular ones. In this tutorial we'll create the 3D spinning cube we saw earlier.

+ +
    +
  1. +

    To start with, make a local copy of index.html in a new folder, then save a copy of metal003.png in the same folder. This is the image we'll use as a surface texture for the cube later on.

    +
  2. +
  3. +

    Next, create a new file called main.js, again in the same folder as before.

    +
  4. +
  5. +

    If you open index.html in your code editor, you'll see that it has two {{htmlelement("script")}} elements — the first one attaching three.min.js to the page, and the second one attaching our main.js file to the page. You need to download the three.min.js library and save it in the same directory as before.

    +
  6. +
  7. +

    Now we've got three.js attached to our page, we can start to write JavaScript that makes use of it into main.js. Let's start by creating a new scene — add the following into your main.js file:

    + +
    const scene = new THREE.Scene();
    + +

    The Scene() constructor creates a new scene, which represents the whole 3D world we are trying to display.

    +
  8. +
  9. +

    Next, we need a camera so we can see the scene. In 3D imagery terms, the camera represents a viewer's position in the world. To create a camera, add the following lines next:

    + +
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    +camera.position.z = 5;
    +
    + +

    The PerspectiveCamera() constructor takes four arguments:

    + +
      +
    • The field of view: How wide the area in front of the camera is that should be visible onscreen, in degrees.
    • +
    • The aspect ratio: Usually, this is the ratio of the scene's width divided by the scene's height. Using another value will distort the scene (which might be what you want, but usually isn't).
    • +
    • The near plane: How close to the camera objects can be before we stop rendering them to the screen. Think about how when you move your fingertip closer and closer to the space between your eyes, eventually you can't see it anymore.
    • +
    • The far plane: How far away things are from the camera before they are no longer rendered.
    • +
    + +

    We also set the camera's position to be 5 distance units out of the Z axis, which, like in CSS, is out of the screen towards you, the viewer.

    +
  10. +
  11. +

    The third vital ingredient is a renderer. This is an object that renders a given scene, as viewed through a given camera. We'll create one for now using the WebGLRenderer() constructor, but we'll not use it till later. Add the following lines next:

    + +
    const renderer = new THREE.WebGLRenderer();
    +renderer.setSize(window.innerWidth, window.innerHeight);
    +document.body.appendChild(renderer.domElement);
    + +

    The first line creates a new renderer, the second line sets the size at which the renderer will draw the camera's view, and the third line appends the {{htmlelement("canvas")}} element created by the renderer to the document's {{htmlelement("body")}}. Now anything the renderer draws will be displayed in our window.

    +
  12. +
  13. +

    Next, we want to create the cube we'll display on the canvas. Add the following chunk of code at the bottom of your JavaScript:

    + +
    let cube;
    +
    +let loader = new THREE.TextureLoader();
    +
    +loader.load( 'metal003.png', function (texture) {
    +  texture.wrapS = THREE.RepeatWrapping;
    +  texture.wrapT = THREE.RepeatWrapping;
    +  texture.repeat.set(2, 2);
    +
    +  let geometry = new THREE.BoxGeometry(2.4, 2.4, 2.4);
    +  let material = new THREE.MeshLambertMaterial( { map: texture, shading: THREE.FlatShading } );
    +  cube = new THREE.Mesh(geometry, material);
    +  scene.add(cube);
    +
    +  draw();
    +});
    + +

    There's a bit more to take in here, so let's go through it in stages:

    + +
      +
    • We first create a cube global variable so we can access our cube from anywhere in the code.
    • +
    • Next, we create a new TextureLoader object, then call load() on it. load() takes two parameters in this case (although it can take more): the texture we want to load (our PNG), and a function that will run when the texture has loaded.
    • +
    • Inside this function we use properties of the texture object to specify that we want a 2 x 2 repeat of the image wrapped around all sides of the cube. Next, we create a new BoxGeometry object and a new MeshLambertMaterial object, and bring them together in a Mesh to create our cube. An object typically requires a geometry (what shape it is) and a material (what its surface looks like).
    • +
    • Last of all, we add our cube to the scene, then call our draw() function to start off the animation.
    • +
    +
  14. +
  15. +

    Before we get to defining draw(), we'll add a couple of lights to the scene, to liven things up a bit; add the following blocks next:

    + +
    let light = new THREE.AmbientLight('rgb(255, 255, 255)'); // soft white light
    +scene.add(light);
    +
    +let spotLight = new THREE.SpotLight('rgb(255, 255, 255)');
    +spotLight.position.set( 100, 1000, 1000 );
    +spotLight.castShadow = true;
    +scene.add(spotLight);
    + +

    An AmbientLight object is a kind of soft light that lightens the whole scene a bit, like the sun when you are outside. The SpotLight object, on the other hand, is a directional beam of light, more like a flashlight/torch (or a spotlight, in fact).

    +
  16. +
  17. +

    Last of all, let's add our draw() function to the bottom of the code:

    + +
    function draw() {
    +  cube.rotation.x += 0.01;
    +  cube.rotation.y += 0.01;
    +  renderer.render(scene, camera);
    +
    +  requestAnimationFrame(draw);
    +}
    + +

    This is fairly intuitive; on each frame, we rotate our cube slightly on its X and Y axes, then render the scene as viewed by our camera, then finally call requestAnimationFrame() to schedule drawing our next frame.

    +
  18. +
+ +

Let's have another quick look at what the finished product should look like:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}}

+ +

You can find the finished code on GitHub.

+ +
+

: In our GitHub repo you can also find another interesting 3D cube example — Three.js Video Cube (see it live also). This uses {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} to take a video stream from a computer web cam and project it onto the side of the cube as a texture!

+
+ +

まとめ

+ +

At this point, you should have a useful idea of the basics of graphics programming using Canvas and WebGL and what you can do with these APIs, as well as a good idea of where to go for further information. Have fun!

+ +

関連情報

+ +

Here we have covered only the real basics of canvas — there is so much more to learn! The below articles will take you further.

+ + + +

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/client-side_web_apis/fetching_data/index.html b/files/ja/learn/javascript/client-side_web_apis/fetching_data/index.html new file mode 100644 index 0000000000..44f7c8b035 --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/fetching_data/index.html @@ -0,0 +1,389 @@ +--- +title: サーバからのデータ取得 +slug: Learn/JavaScript/Client-side_web_APIs/Fetching_data +tags: + - API + - Article + - Beginner + - CodingScripting + - Fetch + - JSON + - JavaScript + - Learn + - Promises + - Server + - XHR + - XML + - XMLHttpRequest + - data + - request +translation_of: Learn/JavaScript/Client-side_web_APIs/Fetching_data +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

モダンな Web サイトやアプリケーションでしょっちゅう必要になる仕事は、サーバから個々のデータを取ってきて、新しいページ全体を読んでくることなしに、ページの一部を書き換える事です。この一見ちょっとした事が、サイトのパフォーマンスや振舞いに巨大なインパクトを与えました。この記事ではそのコンセプトを解説し、これを可能にした技術 XMLHttpRequest や Fetch API について見ていきます。

+ + + + + + + + + + + + +
前提条件:JavaScript の基本 (最初のステップビルディングブロックJavaScript オブジェクトを参照)、クライアントサイド API の基本
目標:サーバからデータを取得し、それを使用して Web ページのコンテンツを更新する方法を習得する。
+ +

これの問題は何か?

+ +

もともと Web のページ読み込みは単純でした — Web サイトのデータをサーバにリクエストすると、何も問題がなければ、ページを構成するいろいろなものがダウンロードされてあなたのコンピュータに表示されていました。

+ +

A basic representation of a web site architecture

+ +

このモデルの問題は、どこかページの一部を書き換えたい場合、例えば新しい商品の一群を表示したり新しいページを読み込ませたりをする毎に、ページ全体を読み直さなければならない事です。これはとても無駄が多くてユーザ体験が悪化します、とりわけページが大きくて複雑になってくるにつれて。

+ +

Ajax の登場

+ +

上述の問題を解決すべく、Web ページから細かいデータ (HTML、{{glossary("XML")}}、JSON やプレーンテキストのような) をリクエストし、それを必要な時だけ表示するという技術の誕生へと繋がりました。

+ +

これは {{domxref("XMLHttpRequest")}} や、最近では Fetch API の利用によって実現されます。これらの技術は、Web ページがサーバにある特定のリソースを直接 HTTP リクエストし、必要があれば結果のデータを表示する前に整形する事を可能にしました。

+ +
+

注記: これらのテクニック一般はかつて Ajax (Asynchronous JavaScript and XML)と呼ばれていましたが、これは {{domxref("XMLHttpRequest")}} を使って XML データを要求するものが多かったためです。今日ではそういうものばかりではありませんが (XMLHttpRequest や Fetch を使って JSON を要求する場合の方が多いでしょう)、結果としては同じであり、"Ajax" という用語はしばしば今でもこのテクニックを説明するのに使われます。

+
+ +

A simple modern architecture for web sites

+ +

Ajax モデルには、ブラウザにページ全体をリロードされるのではなく、もっと賢くデータをリクエストするために Web API をプロキシとして使うという事も含まれます。これの重要性を考えてみて下さい:

+ +
    +
  1. お気に入りの情報に富んだサイト、アマゾンとか YouTube とか CNN とかに行って読み込みます。
  2. +
  3. さて新しい商品だか何だかを検索します。メインのコンテンツは変わるでしょうが、周りに表示されている情報、ヘッダーやフッター、ナビゲーションメニューなど、大半はそのままでしょう。
  4. +
+ +

これはとても良いことで、それは:

+ + + +

さらなる高速化のために、サイトの中には必要なものやデータを最初にリクエストされた時にユーザのコンピュータに保存してしまい、以降の訪問では保存ずみのものを、サーバから最新版のダウンロードさせる事なく使用するものもあります。コンテンツはそれが更新された時だけサーバから再読み込みされます。

+ +

A basic web app data flow architecture

+ +

基本的な Ajax リクエスト

+ +

{{domxref("XMLHttpRequest")}} と Fetch それぞれを使って、そのようなリクエストをどうやるのか見ていきましょう。それらの例では、いくつかの異なるテキストファイルから取り出したデータをリクエストし、コンテンツ領域に埋め込みます。

+ +

この一連のファイルは疑似データベースとして働きます。実際のアプリケーションでは、PHP や Python、Node のようなサーバサイド言語を使ってデータベースから取り出したデータをリクエストする場合が多いでしょう。ですがここでは簡単にしておき、クライアント側のパートに集中します。

+ +

XMLHttpRequest

+ +

XMLHttpRequest (よく XHR と略記されます) は今となってはかなり古い技術です — Microsoft によって1990年代に発明され、非常に長い間ブラウザを超えて標準化されてきました。

+ +
    +
  1. +

    この例題を始めるにあたり、ajax-start.html と4つのテキストファイル — verse1.txtverse2.txtverse3.txtverse4.txt — のローカルコピーを、あなたのコンピュータの新しいディレクトリに作って下さい。この例題では、ドロップダウンメニューから選択されたら、詩 (ご存知の詩かも) のこれら異なる節を XHR を使って読み込みます。

    +
  2. +
  3. +

    {{htmlelement("script")}} 要素のすぐ内側に、下のコードを書き足して下さい。これは {{htmlelement("select")}} と {{htmlelement("pre")}} 要素への参照を定数に保存し、{{domxref("GlobalEventHandlers.onchange","onchange")}} イベントハンドラ関数を定義していて、これは select の値が変わったら、その値が呼び出される関数 updateDisplay() の引数となるようにします。

    + +
    const verseChoose = document.querySelector('select');
    +const poemDisplay = document.querySelector('pre');
    +
    +verseChoose.onchange = function() {
    +  const verse = verseChoose.value;
    +  updateDisplay(verse);
    +};
    +
  4. +
  5. +

    updateDisplay() 関数を定義しましょう。まずはさっきのコードブロックの下に以下を書き足します — これは関数のからっぽのガワです。 注: ステップ 4 から 9 はすべて、この関数内で実施します。

    + +
    function updateDisplay(verse) {
    +
    +}
    +
  6. +
  7. +

    関数を、後から必要になる読み込みたいテキストファイルを指す相対 URL を作るところからはじめます。{{htmlelement("select")}} 要素の値は常に、選択されている {{htmlelement("option")}} の内側テキスト、例えば"Verse 1"とか、に一致します (value 属性で異なる値を設定していなければ)。これに相当するテキストファイルは "verse1.txt" で HTML と同じディレクトリにあるので、ファイル名だけで十分です。

    + +

    ただ、Web サーバはたいてい大文字小文字を区別しますし、今回のファイル名にスペースは含まれていません。"Verse 1" を "verse1.txt" に変換するためには、V を小文字にして、スペースを取り除き、.txt を末尾に追加しなければなりません。これは{{jsxref("String.replace", "replace()")}} に {{jsxref("String.toLowerCase", "toLowerCase()")}}、あと単なる 文字列の結合 で実現できます。以下のコードをあなたの updateDisplay() 関数の内側に追加して下さい:

    + +
    verse = verse.replace(" ", "");
    +verse = verse.toLowerCase();
    +let url = verse + '.txt';
    +
  8. +
  9. +

    XHR リクエストを作り始めるため、リクエストオブジェクトを {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}} コンストラクタを使って作成しなければなりません。このオブジェクトには好きな名前を付けられますが、単純にするため request を使います。updateDisplay() 関数の内側で、先の行の下に以下を追加します:

    + +
    let request = new XMLHttpRequest();
    +
  10. +
  11. +

    次に {{domxref("XMLHttpRequest.open","open()")}} メソッドを使ってどの HTTP リクエストメソッド を使ってリソースをネットワークから取得するか、URL はどこかを指定しなければなりません。ここでは単に GET メソッドを使い、URL には url 変数の値をセットします。先の行の下に以下を追加します:

    + +
    request.open('GET', url);
    +
  12. +
  13. +

    次はレスポンスにどのような形式にしたいか指定 — これはリクエストの {{domxref("XMLHttpRequest.responseType", "responseType")}} プロパティで指定します — text にします。厳密に言えばこの場合は必須の指定ではありません — XHR はデフォルトで text を返します — が、いつの日か他のデータ形式を指定したくなる場合にそなえて、この設定をする習慣をつけておくと良いと思います。次を追加して下さい:

    + +
    request.responseType = 'text';
    +
  14. +
  15. +

    ネットワークからリソースを取得する処理は非同期{{glossary("asynchronous")}} 処理なので、戻りを使って何かをする前に、あなたは処理が完了(リソースがネットワークから返ってくる)するのを待たなければならず、さもないとエラーが投げられます。XHR では {{domxref("XMLHttpRequest.onload", "onload")}} イベントハンドラを使ってこの問題をさばけます — これは {{event("load")}} イベントが発火(レスポンスが返ってきた)した時に実行されます。このイベントが起きた後は、レスポンスデータは XHR リクエストオブジェクトの response プロパティとして取得できます。

    + +

    さっき追加した行の後に以下を追加して下さい。onload イベントハンドラの中で、poemDisplay ({{htmlelement("pre")}}要素) の textContent プロパティに {{domxref("XMLHttpRequest.response", "request.response")}} プロパティの値を設定しているのがお判りでしょう。

    + +
    request.onload = function() {
    +  poemDisplay.textContent = request.response;
    +};
    +
  16. +
  17. +

    以上は全部、XHR リクエストの設定です — 実は私たちがやれと指示するまで動作はしません。やれと指示するには、{{domxref("XMLHttpRequest.send","send()")}} メソッドを使います。さっき追加した行の後に以下を追加して、関数を完成させます。この行は、updateDisplay() 関数の閉じ中括弧のすぐ上に置く必要があります。

    + +
    request.send();
    +
  18. +
  19. +

    今の時点でのこの例題にある問題の一つは、最初に読み込まれた時点ではなにも詩が表示されないことです。これを直すには、あなたのコードの一番下 (</script> 閉じタグのすぐ上) に以下の二行を追加し、デフォルトで1番の詩を読み込みませ、{{htmlelement("select")}} 要素に適切な値を指させます:

    + +
    updateDisplay('Verse 1');
    +verseChoose.value = 'Verse 1';
    +
  20. +
+ +

サーバからあなたの例題を送らせる

+ +

今時のブラウザ (Chrome も含まれます) は、ローカルファイルとして例題を実行しても XHR リクエストを行ないません。これはセキュリティの制限によるものです (Web のセキュリティにより詳しくは Webサイトのセキュリティを読んで下さい)。

+ +

これをどうにかするため、例題をローカルの Web サーバを使って実行しなければなりません。どうやるのかは、 テスト用のローカルサーバを設定するにはどうすればいい? を読んで下さい。

+ +

Fetch

+ +

Fetch API は、基本的には XHR の今風の代替品です — 最近になってブラウザに組込まれたもので、非同期 HTTP リクエストを JavaScript で、開発者や他の Fetch の上に組まれた API から簡単に行なえるようにするためのものです。

+ +

先の例を Fetch を使うように書き換えてみましょう!

+ +
    +
  1. +

    さっき完成させた例題のディレクトリのコピーを作ります(前の例題を完成させていないなら、新しいディレクトリを作成して、そこに xhr-basic.html と4つのテキストファイル — (verse1.txtverse2.txtverse3.txtverse4.txt) のコピーを作って下さい。

    +
  2. +
  3. +

    updateDisplay() 関数の中から、XHR のコードを探し出します:

    + +
    let request = new XMLHttpRequest();
    +request.open('GET', url);
    +request.responseType = 'text';
    +
    +request.onload = function() {
    +  poemDisplay.textContent = request.response;
    +};
    +
    +request.send();
    +
  4. +
  5. +

    XHR のコードを次のように置き換えます:

    + +
    fetch(url).then(function(response) {
    +  response.text().then(function(text) {
    +    poemDisplay.textContent = text;
    +  });
    +});
    +
  6. +
  7. +

    例題をブラウザに読み込むと(Web サーバから読んで下さい)、XHR 版と同様に動作するするはずです。今時のブラウザを使っていれば。

    +
  8. +
+ +

Fetch のコードでは何が起きている?

+ +

まず最初に、{{domxref("WorkerOrWindowGlobalScope.fetch()","fetch()")}} メソッドが呼ばれ、取得したいリソースの URL が渡されています。これは XHR の {{domxref("XMLHttpRequest.open","request.open()")}} の今時な同等品で、さらに言えば .send() に相当するものは必要ありません。

+ +

その後に、{{jsxref("Promise.then",".then()")}} メソッドが fetch() の後に連鎖されているのがわかるでしょう — このメソッドは {{jsxref("Promise","Promises")}} の一部で、非同期処理を行なうための今風な JavaScript に備わる機能です。fetch() はプロミスを返し、これはサーバから送られたレスポンスによって解決されます — .then() を使ってプロミスが解決された後にある種後始末のコードを走らせるようにし、そのコードとは内側で定義した関数にあたります。これは XHR 版の onload イベントハンドラに相当します。

+ +

この関数には、fetch() のプロミスが解決された際に、自動的にサーバからのレスポンスが引数として渡されます。関数の中で、レスポンスをつかまえてその {{domxref("Body.text","text()")}} メソッド、これは基本的にレスポンスを生のテキストで返すもの、を走らせます。これは XHR 版の request.responseType = 'text' 部分と等価です。

+ +

text() もプロミスを返しているのがおわかりでしょう、ですのでそれに別の .then() を連鎖させ、その中で text() のプロミスが解決する生テキストを受けとるよう、関数を定義します。

+ +

内側のプロミスの関数の中で、XHR 版でやったのとほとんど同じ事をやっています — {{htmlelement("pre")}} 要素のテキストコンテントにテキスト値を設定しています。

+ +

Aside on promises

+ +

プロミスは初めて見るとちょっと混乱させられますが、今はひとまずそんなに心配しなくて大丈夫です。ちょっとすれば慣れます、とくに今風の JavaScript APIを学んでいけば — 新しい部分の大半がこのプロミスに強く依存しています。

+ +

上の例のプロミスの構造を見直してみましょう、もうちょっと意味が通じてくるかもしれません:

+ +
fetch(url).then(function(response) {
+  response.text().then(function(text) {
+    poemDisplay.textContent = text;
+  });
+});
+ +

最初の行で言っているのは、「urlにあるリソースを取ってこい(fetch)」(fetch(url))で、「それから(then)プロミスが解決したら指定した関数を実行しろ」(.then(function() { ... }))です。「解決」とは、「この先どこかの時点で、指定された処理の実行を終える」事を意味します。この場合だと指定された処理とは、指定のURLからリソースを取ってきて(HTTPリクエストを使って)、そのレスポンスを私たちがどうにかできるように返せ、です。

+ +

実際のところ、then()に渡される関数は、すぐには実行されないコードの塊です — すぐにではなく、未来のどこかの時点でレスポンスが返って来た時に実行されます。頭に入れておいて下さい、プロミスは変数に保存する事もできて、変数に {{jsxref("Promise.then",".then()")}} を連鎖する事ができます。次のコードがやっているのも同じ事です:

+ +
let myFetch = fetch(url);
+
+myFetch.then(function(response) {
+  response.text().then(function(text) {
+    poemDisplay.textContent = text;
+  });
+});
+ +

fetch() メソッドは HTTP レスポンスによって解決されるプロミスを返し、その後ろに連鎖された .then() の中にどのような関数を定義しても、それには引数としてレスポンスが自動で渡されます。引数にどんな名前を付けるのもご自由です — 下の例もちゃんと動きます:

+ +
fetch(url).then(function(dogBiscuits) {
+  dogBiscuits.text().then(function(text) {
+    poemDisplay.textContent = text;
+  });
+});
+ +

ですがパラメータにはその中身がわかる名前を付けた方がいいですよね!

+ +

今度は関数だけに着目しましょう:

+ +
function(response) {
+  response.text().then(function(text) {
+    poemDisplay.textContent = text;
+  });
+}
+ +

レスポンスオブジェクトには {{domxref("Body.text","text()")}} メソッドがあって、これはレスポンスボディにある生データを受けて、プレインテキスト(これが私たちの必要とする形式です)、に変換します。このメソッドもプロミス(これは結果となるテキスト文字列で解決します)を返すので、ここでまた別の {{jsxref("Promise.then",".then()")}} を使い、この内部で、テキスト文字列を使って私たちがやりたい事を行うための別の関数を定義します。私たちがやるのは、ただ詩用の {{htmlelement("pre")}} 要素の textContent プロパティをテキスト文字列と同じに設定だけなので、これはとても単純です。

+ +

これも覚えておく価値があります、それぞれのブロックの結果を次のブロックに渡していくように、直接複数のプロミスブロック(.then()ブロック以外の種類もあります)を次から次へと連鎖する事ができます、あたかも鎖を下にたどっていくように。このおかげで、プロミスはとても強力なのです。

+ +

次のブロックはもとの例題と同じ事をしますが、違うやり方で書かれています:

+ +
fetch(url).then(function(response) {
+  return response.text()
+}).then(function(text) {
+  poemDisplay.textContent = text;
+});
+ +

多くの開発者はこの書き方の方が好きです、なぜなら平らで、間違いなく長大なプロミス連鎖も読みやすいからです — それぞれのプロミスが、前のやつの内側に来る(これは扱いづらくなる場合があります)のではなく、前のやつから順々に続いています。違うのは return 文を response.text() の前に書いて、それが出した結果を次の鎖に渡すようにしなければならないところだけです。

+ +

どっちの機構を使うべき?

+ +

これは本当に、あなたがどんなプロジェクトを進めているかによります。XHR は長いこと存在しているので、様々なブラウザで非常によくサポートされています。一方 Fetch とプロミスは Web プラットフォームに最近追加されたものなので、ブラウザ界では結構サポートされているんですが、IE はサポートしていません。

+ +

古いブラウザをサポートする必要があるのならば、XHR の方が良いでしょう。ですがあなたがもっと先進的なプロジェクトで働いて、古いブラウザの事でさして悩まないなら、Fetch が良い選択になるでしょう。

+ +

本当はどっちも学ぶべきです — Fetch は IE が消えていくにつれ(IE は、Microsoft の新しい Edge ブラウザのおかげで開発が終了しています)どんどん一般的になっていくでしょうが、もうしばらくは XHR が必要でしょう。

+ +

もっとややこしい例題

+ +

この記事のまとめとして、Fetch のより興味深い使い方を示す、ちょっとばかり難しい例題を見ていきましょう。例題用に缶詰屋というサイトを作成しました — これは缶詰だけを売る仮想のお店です。これの GitHubでのライブ実行ソースコード が見られます。

+ +

A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column.

+ +

デフォルトではサイトには全ての商品が表示されますが、左側のカラムにあるフォームコントロールからカテゴリから、検索語から、あるいはその両方によってフィルタリングをかけられます。

+ +

商品をカテゴリや検索語によってフィルタリングする処理をし、UIでデータが正しく表示されるように文字列を操作するためなどに、けっこうな量の複雑なコードがあります。この記事のなかでそれら全てについて解説しませんが、ソースコードのコメントに詳しいことがたくさん書いてあります(can-script.jsを見て下さい)。

+ +

ですが、Fetch のコードについては説明していきます。

+ +

Fetch を使うブロックの最初は、JavaScript の初めの方にあります:

+ +
fetch('products.json').then(function(response) {
+  return response.json();
+}).then(function(json) {
+  let products = json;
+  initialize(products);
+}).catch(function(err) {
+  console.log('Fetch problem: ' + err.message);
+});
+ +

fetch() 関数はプロミスを返します。これが成功裏に完了すると、一つ目の .then() ブロックの中にある関数は、ネットワークから返された response を受け取ります。

+ +

この関数の中で、{{domxref("Body.text","text()")}} ではなくて {{domxref("Body.json","json()")}} を実行しています。プレインテキストではなく、構造化された JSON データとしてレスポンスを返してほしいからです。

+ +

次に、別の .then() を最初の .then() の後に連鎖させています。これに、response.json() プロミスから返された json を含む成功時の関数を渡しています。この jsonproducts 変数の値として代入してから、initialize(products) を実行します。すべての商品をユーザーインターフェイスに表示する処理が開始されます。

+ +

エラーを処理するために、連鎖の最後に .catch() ブロックを連鎖させています。これは、何らかの理由でプロミスが失敗した場合に実行されます。その中には、引数として渡される関数、error オブジェクトが含まれています。この error オブジェクトを使用して、発生したエラーがどういうものかを伝えられます。ここでは単純な console.log() を使用して伝えています。

+ +

ただし、完全な Web サイトでは、ユーザの画面にメッセージを表示し、状況を改善する選択肢を提供することで、このエラーをより適切に処理するでしょう。とは言え、ここでは単純な console.log() 意外は必要ありません。

+ +

あなたは自分でも失敗した場合のテストができます:

+ +
    +
  1. 例題のファイルのローカルコピーを作成して下さい(缶詰屋の ZIPファイルをダウンロードして展開して下さい)。
  2. +
  3. コードを Web サーバから読んで走らせるようにします(方法は前に {{anch("Serving your example from a server")}}で解説しました)。
  4. +
  5. fetch するファイルのパスを、'produc.json' のようなものに変更します(誤ったファイル名にして下さい)。
  6. +
  7. ここでインデックスファイルをブラウザに読み込んで( localhost:8000 から)、あなたのブラウザの開発者コンソールを見ます。次の行のようなメッセージが表示されるはずです「Network request for produc.json failed with response 404: File not found」。
  8. +
+ +

二つ目の Fetch ブロックは fetchBlob() 関数の中にあります:

+ +
fetch(url).then(function(response) {
+    return response.blob();
+}).then(function(blob) {
+  // Convert the blob to an object URL — this is basically a temporary internal URL
+  // that points to an object stored inside the browser
+  let objectURL = URL.createObjectURL(blob);
+  // invoke showProduct
+  showProduct(objectURL, product);
+});
+ +

これも前のとおおよそ同じように動作しますが、{{domxref("Body.json","json()")}} ではなくて {{domxref("Body.blob","blob()")}} を使っているところが違います — 今回の場合は画像ファイルを返したいので、これ用に使うデータ形式は Blob — これは "Binary Large Object" の略で、たいていは巨大なファイルのようなオブジェクト、画像や動画のようなものを示すのに使われます。

+ +

blob を成功裏に受信したら、{{domxref("URL.createObjectURL()", "createObjectURL()")}}を使ってそこからオブジェクトURLを取り出します。これはそのブラウザの中でのみ有効なオブジェクトを示す一時的な URL を返します。あまり読み易いものではありませんが、缶詰屋アプリを開いて画像を Ctrlクリックもしくは右クリックして、メニューから「画像を表示」を選択する(これはあなたが使っているブラウザによって異なる場合があります)と見ることができます。オブジェクトURLはブラウザのアドレスバーに表示され、こんな感じになるでしょう:

+ +
blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4
+ +

課題: XHR 版の缶詰屋

+ +

ちょっとした練習として、アプリの Fetch 版を XHR を使うように書き換えて下さい。ZIPファイル のコピーを作って、上手く JavaScript を書き換えてみて下さい。

+ +

ちょっとしたヒントです:

+ + + +
+

注記: 上手くいかないときは、我々のGitHubにある完成版のコード (ソースコードはこちらからライブ実行版もどうぞ) と比べてみて下さい。

+
+ +

まとめ

+ +

私たちのサーバからのデータ取得に関する記事は以上です。ここまでくれば、どう XHR と Fetch を使って進めていけばいいのか理解できたことでしょう。

+ +

あわせて参照

+ +

この記事には様々なほんのさわりしか説明していない事項がたくさんあります。これらの事項についてもっと詳しくは、以下の記事を見て下さい:

+ + + +
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

このモジュール

+ +
+ +
diff --git a/files/ja/learn/javascript/client-side_web_apis/index.html b/files/ja/learn/javascript/client-side_web_apis/index.html new file mode 100644 index 0000000000..0675ea4da0 --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/index.html @@ -0,0 +1,51 @@ +--- +title: クライアントサイド Web API +slug: Learn/JavaScript/Client-side_web_APIs +tags: + - API + - CodingScripting + - DOM + - JavaScript + - Landing + - WebAPI + - グラフィック + - データ + - メディア + - モジュール + - 初心者向け + - 学習 + - 記事 +translation_of: Learn/JavaScript/Client-side_web_APIs +--- +
{{LearnSidebar}}
+ +

Web サイトやアプリケーション用にクライアント側のJavaScriptを書いていると、すぐにアプリケーションプログラミングインターフェース (Apprication Programming Interfaces、API) にでくわします。API とはブラウザやサイトが動作している OS の様々な面を操作したり、他の Web サイト、サービスから取得したデータを操作するためのプログラムされた機能です。このモジュールでは API とは何か、開発作業の中でよく見かける最もよく利用される API のいくつかについて、どのように使うかを説明していきます。

+ +

前提条件

+ +

このモジュールをよく理解するためには、ここまでの一連のJavaScriptに関するモジュール (First steps, Building blocksJavaScript objects) の学習をすませているべきです。これらのモジュールでは大抵簡単な API を使っていますが、その助けなしにクライアント側の JavaScript を書き上げるのは難しいからです。このチュートリアルの中では、JavaScript 言語のコア部分については十分理解しているものとして、よく使われる Web API についてもう少し詳しく探っていきます。

+ +

HTMLCSS に関する基礎知識も役に立つでしょう。

+ +
+

注記: もし自分のファイルを作成できないようなデバイス上で作業しているなら、大半のコード例を JSBin や  Thimble のようなオンラインプログラム作成・実行環境で試してみることもできます。

+
+ +

ガイド

+ +
+
Web API の紹介
+
まずはAPIを高い視点から見ていきます — これは何なのか、どう働くのか、あなたのコードでどう使うのか、どういう風に作られているのか? また様々なクラスのAPIが何なのか、どんな使い方があるのかも見ていきます。
+
文章の操作
+
Webページやアプリを書く場合に、最も多く必要になるのはWeb文書をどうかして操作する事でしょう。これは普通ドキュメントオブジェクトモデル(Document Object Model、DOM)、これはHTMLとスタイルに関する情報を{{domxref("Document")}}オブジェクトを使いまくって操作するための一連のAPIです、を用いて行ないます。この記事では、DOMの使い方を詳しく見ながら、面白い方法であなたの環境を変える事ができる興味深い他のAPIもいくつか見ていきます。
+
サーバからのデータ取得
+
また別に、モダンなWebサイトやアプリケーションでしょっちゅう必要になるのは、サーバから個々のデータを取ってきて、新しいページ全体を読んでくることなしに、ページの一部を書き換える事です。この一見ちょっとした事が、サイトのパフォーマンスや振舞いに巨大なインパクトを与えました。この記事ではそのコンセプトを解説し、これを可能にした技術{{domxref("XMLHttpRequest")}}とFetch APIについて見ていきます。
+
サードパーティ API
+
これまでに説明したAPIはブラウザに組込まれていますが、全てのAPIが組込まれているのではありません。グーグルマップやTwitter、Facebook、ペイパルなど、多くの巨大なWebサイトやサービスが、開発者に対して彼らのデータを利用したり(例:あなたのブログにtwitterのタイムラインを表示させる)、サービスを利用したり(例:あなたのサイトに独自のグーグルマップを表示したり、あなたのサービス利用者にFacebookでログインできたり)するためのAPIを提供しています。この記事ではブラウザAPIとサードパーティAPIの違いを見ていき、典型的な後者の使い方をお見せします。
+
絵を描く
+
ブラウザにはグラフィックを描くためのとても強力なツールがいくつか組込まれています。SVG(Scalable Vector Graphics)言語から、HTMLの{{htmlelement("canvas")}}キャンバス要素に描画するためのAPIまで (キャンバスAPIWebGLを参照)。 この記事ではキャンバスAPIへの導入を説明し、もっと深く学習していくためのリソースをご紹介します。
+
動画と音声の API
+
HTML5には文書にリッチなメディアを埋め込むための要素が備わっています — {{htmlelement("video")}} と {{htmlelement("audio")}} — それぞれに再生やシークなどの操作するための独自APIを備えています。この記事では独自の再生操作パネルを作成するような、よくある仕事をどうやればいいのかお見せします。
+
クライアント側でのデータ保存
+
モダンなブラウザには、Webサイトに関するデータを保存し必要なときに取り出すための様々に異なる技術が実装されており、これを使ってデータを長期間保存したり、サイトをオフラインに保存したりなどなどができます。この記事ではこれらがいかに動作するのか、その基本の基本について説明します。
+
diff --git a/files/ja/learn/javascript/client-side_web_apis/introduction/index.html b/files/ja/learn/javascript/client-side_web_apis/introduction/index.html new file mode 100644 index 0000000000..521cd6d234 --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/introduction/index.html @@ -0,0 +1,317 @@ +--- +title: Web API の紹介 +slug: Learn/JavaScript/Client-side_web_APIs/Introduction +tags: + - 3rd party + - API + - Article + - Beginner + - Browser + - CodingScripting + - Learn + - Object + - WebAPI + - client-side +translation_of: Learn/JavaScript/Client-side_web_APIs/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

まずはAPIを高い視点から見ていきます — これは何なのか、どう働くのか、あなたのコードでどう使うのか、どういう風に作られているのか? また様々なクラスのAPIは何なのか、どのような使い方があるのかも見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータの知識および利用能力、HTMLCSS の基本的な理解、JavaScript の基本 (第一歩構成要素, JavaScriptオブジェクト).
目的:API に何ができて、あなたのコードでどう使えばいいのか知ること。
+ +

API って何?

+ +

Application Programming Interfaces (APIs) は、開発者が複雑な機能をより簡単に作成できるよう、プログラミング言語から提供される構造です。複雑なコードを抽象化し、それにかわる簡潔な構文を提供します。

+ +

実世界の例として、あなたの家、アパートや他の住処にある電気のコンセントについて考えて下さい。あなたの家で機器を使いたい時には、電源コードのプラグをコンセントに差し込めば事足ります。電源に直接結線したりしないでしょう — そんなのは非効率ですし、あなたが電気工事士でなければ、やってみるには難しいし危険です。

+ +

+ +

画像提供: 超タコ足コンセント by The Clear Communication People, Flickr より

+ +

それと同じことで、そうですね、例えば3次元グラフィックのプログラムを JavaScript や Python のような高レベル言語で書かれた API を使ってやる方が、C や C++ のような低レベル言語から直接コンピュータの GPU やグラフィック機能を叩いてやるよりも、ずっと簡単です。

+ +
+

注記: API という語についてもっと詳しいことは APIの用語解説 を参照して下さい。

+
+ +

クライアントサイド JavaScript での API

+ +

クライアントサイド API では、実際非常にたくさんのAPIが使えます — それらは JavaScript 言語本体の一部ではなく、あなたにスーパーパワーを与えるべく JavaScript 言語のコアの上に築かれた代物です。それらはおおよそ二つのカテゴリに分けられます:

+ + + + + + + +

+ + + +

JavaScript と API とその他 JavaScript ツールの関係

+ +

ここまででクライアントサイド API とは何か、JavaScript 言語とどう関係しているのかお話しました。もっとはっきりさせるために一度おさらいして、ついでに他の JavaScript ツールがどう関係してくるのかもお話しましょう:

+ + + +

API で何ができる?

+ +

モダンなブラウザではすごい数の API を利用できるので、コードからとてもいろいろな事ができます。 MDN API 索引を見てみればわかると思います。

+ +

一般的なブラウザ API

+ +

特に、あなたが使うであろう最も一般的なブラウザ API のカテゴリ (このモジュールでとても詳しい所まで網羅していきます) は:

+ + + +

一般的なサードパーティAPI

+ +

サードパーティ API はバラエティーに富んでいます。あなたが遅かれ早かれ使うようになりそうな、世間でよく使われているものには以下のようなものがあります:

+ + + +
+

注記: サードパーティAPIについては Programmable Web API directoryでもっと多くの情報を見られます。

+
+ +

APIはどのように動作する?

+ +

異なるJavaScript APIはそれぞれに違う方法で動作しますが、普通は、共通した機能とどのように動くべきかの類似したテーマを持ちます。

+ +

オブジェクトに基づいています

+ +

あなたのコードは一つ以上の JavaScript オブジェクトを通じて API とやりとりし、オブジェクトは API が使用するデータ (オブジェクトのプロパティとして持つ) や API が提供する機能(オブジェクトメソッドとして持つ) の容れ物として使われます。

+ +
+

注記: もしまだオブジェクトがどのように動作するかについて理解があやふやなら、先に進む前に JavaScript オブジェクト モジュールを読みなおし、練習するのをおすすめします。

+
+ +

Let's return to the example of the Web Audio API — this is a fairly complex API, which consists of a number of objects. The most obvious ones are:

+ + + +

So how do these objects interact? If you look at our simple web audio example (see it live also), you'll first see the following HTML:

+ +
<audio src="outfoxing.mp3"></audio>
+
+<button class="paused">Play</button>
+<br>
+<input type="range" min="0" max="1" step="0.01" value="1" class="volume">
+ +

We, first of all, include an <audio> element with which we embed an MP3 into the page. We don't include any default browser controls. Next, we include a {{htmlelement("button")}} that we'll use to play and stop the music, and an {{htmlelement("input")}} element of type range, which we'll use to adjust the volume of the track while it's playing.

+ +

Next, let's look at the JavaScript for this example.

+ +

We start by creating an AudioContext instance inside which to manipulate our track:

+ +
const AudioContext = window.AudioContext || window.webkitAudioContext;
+const audioCtx = new AudioContext();
+ +

Next, we create constants that store references to our <audio>, <button>, and <input> elements, and use the {{domxref("AudioContext.createMediaElementSource()")}} method to create a MediaElementAudioSourceNode representing the source of our audio — the <audio> element will be played from:

+ +
const audioElement = document.querySelector('audio');
+const playBtn = document.querySelector('button');
+const volumeSlider = document.querySelector('.volume');
+
+const audioSource = audioCtx.createMediaElementSource(audioElement);
+ +

Next up we include a couple of event handlers that serve to toggle between play and pause when the button is pressed and reset the display back to the beginning when the song has finished playing:

+ +
// play/pause audio
+playBtn.addEventListener('click', function() {
+    // check if context is in suspended state (autoplay policy)
+    if (audioCtx.state === 'suspended') {
+        audioCtx.resume();
+    }
+
+  // if track is stopped, play it
+    if (this.getAttribute('class') === 'paused') {
+        audioElement.play();
+        this.setAttribute('class', 'playing');
+        this.textContent = 'Pause'
+    // if track is playing, stop it
+} else if (this.getAttribute('class') === 'playing') {
+        audioElement.pause();
+        this.setAttribute('class', 'paused');
+        this.textContent = 'Play';
+    }
+});
+
+// if track ends
+audioElement.addEventListener('ended', function() {
+    playBtn.setAttribute('class', 'paused');
+    playBtn.textContent = 'Play';
+});
+ +
+

Note: Some of you may notice that the play() and pause() methods being used to play and pause the track are not part of the Web Audio API; they are part of the {{domxref("HTMLMediaElement")}} API, which is different but closely-related.

+
+ +

Next, we create a {{domxref("GainNode")}} object using the {{domxref("AudioContext.createGain()")}} method, which can be used to adjust the volume of audio fed through it, and create another event handler that changes the value of the audio graph's gain (volume) whenever the slider value is changed:

+ +
const gainNode = audioCtx.createGain();
+
+volumeSlider.addEventListener('input', function() {
+    gainNode.gain.value = this.value;
+});
+ +

The final thing to do to get this to work is to connect the different nodes in the audio graph up, which is done using the {{domxref("AudioNode.connect()")}} method available on every node type:

+ +
audioSource.connect(gainNode).connect(audioCtx.destination);
+ +

The audio starts in the source, which is then connected to the gain node so the audio's volume can be adjusted. The gain node is then connected to the destination node so the sound can be played on your computer (the {{domxref("AudioContext.destination")}} property represents whatever is the default {{domxref("AudioDestinationNode")}} available on your computer's hardware, e.g. your speakers).

+ +

認識できる入口があります

+ +

APIを使うときは、その API の入口がどこなのかしっかり確認するべきです。Web Audio APIではとても単純でした — それは {{domxref("AudioContext")}} オブジェクトであり、あらゆる音声操作を行うために使用する必要があります。

+ +

Document Object Model (DOM) API でも単純な入口があります — これの機能は{{domxref("Document")}} もしくは何らかの方法で影響を与えたい いHTML 要素のインスタンスにぶらさがっている場合が多く、例えば:

+ +
const em = document.createElement('em'); // create a new em element
+const para = document.querySelector('p'); // reference an existing p element
+em.textContent = 'Hello there!'; // give em some text content
+para.appendChild(em); // embed em inside para
+ +

Canvas API は、諸々を操作するために使用するコンテキストオブジェクトの取得にも依存していますが、この場合は、音声コンテキストではなく描画コンテキストです。そのコンテキストオブジェクトは、描画をしたい {{htmlelement("canvas")}} 要素への参照を取得して、 これの{{domxref("HTMLCanvasElement.getContext()")}} メソッドを呼ぶと作成されます:

+ +
const canvas = document.querySelector('canvas');
+const ctx = canvas.getContext('2d');
+ +

キャンバスを使って何かやろうとする場合は何でも、コンテキストオブジェクト (これは{{domxref("CanvasRenderingContext2D")}} のインスタンスです) のプロパティやメソッドを呼んで行ないます。例えば:

+ +
Ball.prototype.draw = function() {
+  ctx.beginPath();
+  ctx.fillStyle = this.color;
+  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
+  ctx.fill();
+};
+ +
+

注記: この実例を弾むボールのデモ (ライブ実行 も見てね)で見られます。

+
+ +

状態の変化を捉えるのにイベントを使います

+ +

すでに学習コース中でイベントについてはお話しています、イベントの紹介 — この記事でクライアント側 Web イベントとは何か、コードの中でどのように使えるのか詳しく見てきました。もしまだクライアント側 WebAPI の仕組みがよくわからいなら、この先に進む前に記事を読み直しておく方が良いでしょう。

+ +

イベントを持たないWebAPIもありますが、ほとんどの WebAPI はいくつか持っています。イベントが発火した際に関数を実行できるイベントハンドラーのプロパティについては、リファレンス記事の独立した"イベントハンドラー"セクションとしておおよそ列挙されています。

+ +

上記の Web Audio API の例では、すでにいくつかのイベントハンドラーが使用されています。

+ +

別の例として、XMLHttpRequest オブジェクトのインスタンス (一つ一つがサーバから何らかの新しいリソースを取得しようとするHTTPリクエストを表わします) にはとてもたくさんのイベントが付随しており、たとえば load イベントは発火したリソースに対する正常なレスポンスが返ってきて、それが使えるようになった時点で発火します。

+ +

次のコードはこれをどう使うのか示す簡単な例です:

+ +
let requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
+let request = new XMLHttpRequest();
+request.open('GET', requestURL);
+request.responseType = 'json';
+request.send();
+
+request.onload = function() {
+  const superHeroes = request.response;
+  populateHeader(superHeroes);
+  showHeroes(superHeroes);
+}
+ +
+

注記: ajax.html でこの例の動作を見られます(ライブ実行版もどうぞ)。

+
+ +

最初の 5 行で取得したいリソースを指定し、XMLHttpRequest() コンストラクタを使って新しいリクエストオブジェクトを生成し、指定のリソースを取得するために GET リクエストを作り、レスポンスを JSON 形式として吐き出すよう指定、そしてリクエストを送信します。

+ +

onload ハンドラー関数で私たちがレスポンスに対して何を行なうかを指定します。load イベントが発火した後には、レスポンスが正常に得られて利用できるようになっている (エラーは起きていない) とわかっていますので、JSON であるレスポンスを superHeroes 変数に保存し、以降の処理のために 2 つの異なる関数に引き渡しています。

+ +

必要なところには追加のセキュリティ機構があります

+ +

WebAPI 機能は JavaScript や他の Web 技術と同等のセキュリティ上の配慮が必要です (例えば same-origin ポリシー) が、追加のセキュリティ機構が必要な場合もあります。例として今時の WebAPI の中に はHTTPS で配信されるページ上でしか動かないものがあり、これは機密とすべきデータをやりとりする可能性があるためです (ServiceWorkersPush など)。

+ +

さらには、ある種のWebAPIへの呼び出しがあなたのコードにあると、ユーザに対してそれの許可を要求します。例えば、Notifications API (通知 API) はポップアップのダイアログボックスを用いて許可を要求します:

+ +

+ +

Web Audio および {{domxref("HTMLMediaElement")}} API には、自動再生 (autoplay) ポリシー と呼ばれるセキュリティ機構が適用されます。これは、基本的に、ページの読み込み時に音声を自動的に再生できないことを意味します。ユーザーに次のことを許可する必要があります。ボタンのようなコントロールを介して音声再生を開始します。これは、音声の自動再生は通常非常に煩わしいものであり、ユーザーにそれを課すべきではないためです。

+ +
+

注記: ブラウザーの厳格さによっては、このようなセキュリティ機構により、例がローカルで機能しなくなる場合があります。つまり、ローカルの例のファイルをウェブサーバーから実行するのではなく、ブラウザーに読み込んだ場合です。執筆時点では、Web Audio API の例はローカルでは Google Chrome で動作しません。動作する前に、GitHub にアップロードする必要がありました。

+
+ +

まとめ

+ +

ここまで来れば、API とは何か、どう動くのか、あなたのJavaScript コードからどんな事ができるのかよくわかったと思います。何か API を使って楽しいことをやりたくってしょうがなくなってることと思いますので、さあ始めましょう! 次から、Document Object Model (DOM) を使った文書の操作を見ていきます。

+ +

{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}

+ +

このモジュール

+ + + +
+
+
+ +
+
+
+ +
+

+ +

+
+
+
+
+
diff --git a/files/ja/learn/javascript/client-side_web_apis/manipulating_documents/index.html b/files/ja/learn/javascript/client-side_web_apis/manipulating_documents/index.html new file mode 100644 index 0000000000..b0c69f9d62 --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/manipulating_documents/index.html @@ -0,0 +1,349 @@ +--- +title: ドキュメントの操作 +slug: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents +tags: + - API + - Article + - Beginner + - CodingScripting + - DOM + - Document + - Document Object Model + - JavaScript + - Learn + - Navigator + - WebAPI + - Window +translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

ウェブページやアプリを書く場合に、最も多く必要になるのはウェブ文書をどうかして操作する事でしょう。これは普通ドキュメントオブジェクトモデル (Document Object Model、DOM) によって為され、DOM は HTML とスタイルに関する情報を {{domxref("Document")}} オブジェクトを多用して操作する一連の API です。この記事では、DOM の使い方を詳しく見ながら、面白い方法であなたの環境を変える事ができる興味深い他の API もいくつか見ていきます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータに関する知識と理解、HTML と CSS、JavaScript—JavaScript のオブジェクトについても—基本を理解していること
目的:DOM API の核と、DOM と共によく利用される API、ドキュメントの操作について詳しくなること
+ +

ウェブブラウザーの重要なパーツ

+ +

ウェブブラウザーはとてもたくさんの動いている部品からなるソフトウェアの複雑な集合体で、部品の多くはウェブ開発者の JavaScript からでは制御したり操作することはできません。こんな制約はよろしくないと思う方もいるかもしれませんが、ブラウザが保護されているのには十分な理由があって、これは主にセキュリティ関係のためです。もしあるウェブサイトがあなたが保存しているパスワードやその他の秘密情報にアクセスできて、あなたのふりをして他のサイトにログインできたらどうですか?

+ +

制限はあっても、ウェブ API は、ウェブページ上でいろいろ素敵な事をできるように、たくさんの機能を提供してくれます。あなたのコードからよく参照するであろう目に見える代物はほんのわずかです — 下の図を見て下さい、この図はウェブページの表示に直接関与しているブラウザーの主要なパーツを表わしています:

+ +

+ + + +

この記事では主にドキュメントの操作に着目しますが、それ以外の役に立つこともちょっとお見せしていきます。

+ +

ドキュメントオブジェクトモデル

+ +

あなたのブラウザーの一つ一つのタブに今読み込まれているドキュメントは、ドキュメントオブジェクトモデルとして表現されます。これは HTML の構造に対してプログラム言語から簡単にアクセスできるようにブラウザーが作成する、"木構造"による表現です — 例えば、ページをレンダリングする際にはブラウザー自体がスタイルや他の情報を適切な要素に適用するために DOM を使い、ページのレンダリングが終わった後にはあなたのような開発者が JavaScript を使って DOM を操作できます。

+ +

dom-example.html にちょっとした例を作成しました(ライブ実行もどうぞ)。ブラウザーから開いてみてください — これはとても簡素なページで、{{htmlelement("section")}} 要素の中に画像が一つと、一つのリンクを含む一つのパラグラフがあります。HTML のソースはこんな感じです:

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Simple DOM example</title>
+  </head>
+  <body>
+      <section>
+        <img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
+        <p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p>
+      </section>
+  </body>
+</html>
+ +

一方これの DOM はこんな具合になります:

+ +

+ +
+

注記: この DOM ツリーの図は Ian Hickson の Live DOM viewer を使って作成しました。

+
+ +

これを見ると、それぞれのドキュメント内の要素とちょっとばかりのテキストそれぞれが、ツリーの中でそれ自身のエントリーがあるのがわかるでしょう — これら一つ一つをノードと呼びます。またノードの種類を示す語や、ノードそれぞれの関係によりツリーでの位置があるのがわかるでしょう:

+ + + +

これからコードを見ていくとこういう語が頻出するので、DOM を使い始める前に、これらの用語をしっかり覚えておくと良いでしょう。CSS の勉強をしているときも、これらの語をみかけることでしょう(子孫セレクター、子セレクターとか)。

+ +

実践学習: 基本的なDOM操作

+ +

DOM 操作の学習スタートは、実践的な例から始めましょう。

+ +
    +
  1. dom-example.htmlimage のローカルコピーを一緒に作成して下さい。
  2. +
  3. <script></script> 要素を、閉じ</body>タグのすぐ上に追加して下さい。
  4. +
  5. DOM の中の要素を操作するため、まず DOM を選びだしてこれへの参照を変数に保存する必要があります。script 要素の中に、次の行を追加して下さい: +
    const link = document.querySelector('a');
    +
  6. +
  7. 要素への参照を変数に保存したので、これが備えているプロパティとメソッドを使って DOM の操作を始められます (利用できるプロパティとメソッドは、たとえば {{htmlelement("a")}} 要素であれば {{domxref("HTMLAnchorElement")}} インターフェース、さらにその汎化した親のインターフェース {{domxref("HTMLElement")}} や {{domxref("Node")}} — これは DOM の全てノードが相当します — で定義されています)。まずは、リンクの中のテキストを、{{domxref("Node.textContent")}} プロパティを更新する事で変更してみましょう。上で書いた行の下に、次の行を追加して下さい: +
    link.textContent = 'Mozilla Developer Network';
    +
  8. +
  9. クリックされたときに変な場所に行かないよう、リンクが指す先の URL も変えておくべきでしょう。また下に、以下の行を追加して下さい: +
    link.href = 'https://developer.mozilla.org';
    +
  10. +
+ +
+

JavaScript あるあるですが、要素を選んで変数に保存する方法にはいろんなやり方があることを頭に入れておいて下さい。{{domxref("Document.querySelector()")}} を使うのが推奨される今風のやり方ですが、これは CSS セレクタと同じ方法で要素を選別できるからです。上記の querySelector() 呼び出しでは文書に現われる最初の {{htmlelement("a")}} がマッチします。もし複数の要素を選択し処理したいのであれば {{domxref("Document.querySelectorAll()")}} を使うことができて、これはセレクタとマッチする全ての要素にマッチし、それらへの参照を {{domxref("NodeList")}} と呼ばれる配列のようなオブジェクトに保存します。

+ +

要素への参照を得るための、次のような古いやり方もあります:

+ + + +

上の二つは querySelector() のような今風のメソッドよりも古いブラウザーで動作しますが、あまり便利ではありません。これ以外にどんなやり方があるかは、あなた自身で探してみて下さい!

+
+ +

新しいノードの作成と配置

+ +

ここまでで、どんな事ができるのかちょっと見えてきたと思いますが、さらに進んで新しい要素を作る方法を見ていきましょう。

+ +
    +
  1. 今の例題に戻って、{{htmlelement("section")}} 要素を掴むところから始めましょう — すでに書いてあるスクリプトの下に次のコードを追加して下さい(この先の他の行についても、同じようにやって下さい): +
    const sect = document.querySelector('section');
    +
  2. +
  3. {{domxref("Document.createElement()")}} を使って新しいパラグラフを作り、前やったのと同じ方法でテキストを入れてやりましょう: +
    const para = document.createElement('p');
    +para.textContent = 'We hope you enjoyed the ride.';
    +
  4. +
  5. この新しいパラグラフを section の最後に {{domxref("Node.appendChild()")}} を使って追加できます: +
    sect.appendChild(para);
    +
  6. +
  7. このパートの締めとして、文章がうまいことまとまるように、リンクを含んでいるパラグラフに対してテキストノードを追加しましょう。まずテキストノードを {{domxref("Document.createTextNode()")}} を使って作成します: +
    const text = document.createTextNode(' — the premier source for web development knowledge.');
    +
  8. +
  9. リンクを含んだパラグラフへの参照を取り出して、そこにテキストノードを追加します: +
    const linkPara = document.querySelector('p');
    +linkPara.appendChild(text);
    +
  10. +
+ +

以上が DOM にノードを追加するために必要な事のほぼ全てです — 動的なインターフェースを作成する際(あとでそういう例題をいくつか見ていきます)これらのメソッドをめっちゃ使う事になるでしょう。

+ +

要素を移動したり削除したり

+ +

ノードを移動したり、DOM から削除したくなる場合があると思います。勿論できます。

+ +

リンクを含むパラグラフを section の最後に移動したい場合は、こうするだけです:

+ +
sect.appendChild(linkPara);
+ +

これでパラグラフは section の一番下に移動します。コピーが作成されるだけじゃないのかとお思いかもしれませんが、この場合は違います — linkPara はパラグラフへの参照の唯一のコピーです。もしコピーをした上で同じように追加をしたいのであれば、 {{domxref("Node.cloneNode()")}} をかわりに使う必要があります。

+ +

削除したいノードとその親ノードへの参照を得ていれば、ノードを削除するのも非常に簡単です。今の例題であれば、以下のように {{domxref("Node.removeChild()")}} を使うだけです:

+ +
sect.removeChild(linkPara);
+ +

よくあるケースですが、削除したいノードそのものへの参照しかない場合に、{{domxref("ChildNode.remove()")}} が使えます:

+ +
linkPara.remove();
+ +

このメソッドは、古いブラウザではサポートされていません。 ノードにそれ自体を削除するように指示するメソッドはないので、次のようにしなければなりません。

+ +
linkPara.parentNode.removeChild(linkPara);
+ +

上の行をあなたのコードに追加してやってみて下さい。

+ +

スタイルを操作する

+ +

いろんなやり方で CSS スタイルを JavaScript から操作することができます。

+ +

まず、ドキュメントに付随する全部のスタイルシートのリストは {{domxref("Document.stylesheets")}} を使って得られ、これは {{domxref("CSSStyleSheet")}} オブジェクトを含む配列のようなオブジェクトを返します。そうしたらお望みのままにスタイルを追加したり削除したりできます。ですがこのやり方について詳しくはやりません。なぜならスタイルをいじるにはちょっとばかり古風で難しいやり方だからです。もっと簡単なやり方があります。

+ +

まずは、動的にスタイルを指定したい要素に、インラインスタイルを直接追加するやり方です。これには {{domxref("HTMLElement.style")}} プロパティを使い、このプロパティはドキュメント中の各素要のインラインスタイル情報を保持しています。このオブジェクトのプロパティを更新すれば要素のスタイルを直接変更できます。

+ +
    +
  1. 例として、作成中の例題に以下の行を追加してみて下さい: +
    para.style.color = 'white';
    +para.style.backgroundColor = 'black';
    +para.style.padding = '10px';
    +para.style.width = '250px';
    +para.style.textAlign = 'center';
    +
  2. +
  3. ページをリロードすると指定のパラグラフにスタイルが適用されているはずです。ブラウザーの Page Inspector や DOM inspector からパラグラフを見ると、言うまでもなく上の行がドキュメントのインラインスタイルに追加されているはずです: +
    <p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p>
    +
  4. +
+ +
+

注記: CSS ではハイフン記法になっているものを、JavaScript プロパティ版の CSS スタイルはどんな風に小文字のキャメルケースで書いている(background-colorbackgroundColor とか)か見ておいて下さい。まぜこぜにしないよう注意して下さい、さもないと動きませんよ。

+
+ +

ドキュメントのスタイルを動的にいじる際によく使われる別のやり方をこれから見ていきましょう。

+ +
    +
  1. さっき JavaScript に追加した 5 行を削除します。
  2. +
  3. HTML の {{htmlelement("head")}} の中に、以下を追加します: +
    <style>
    +.highlight {
    +  color: white;
    +  background-color: black;
    +  padding: 10px;
    +  width: 250px;
    +  text-align: center;
    +}
    +</style>
    +
  4. +
  5. さて、多くの HTML 操作においてとても役に立つメソッドをお見せします — {{domxref("Element.setAttribute()")}} — これはに二つの引数、要素に設定したい属性名と、属性に設定したい値、を与えます。この場合だと、我々のパラグラフにクラス名、highlight をセットします: +
    para.setAttribute('class', 'highlight');
    +
  6. +
  7. ページをリロードしても何も変わりません — パラグラフには CSS が今も適用されていますが、今回はクラスを指定して CSS ルールが選んでいて、インライン CSS スタイルによるものではありません。
  8. +
+ +

どうやるかはあなた次第です。それぞれに利点と欠点があります。最初のやり方は少ない設定ですみ、簡単な場合には向いていますが、二つ目のやり方はずっときれいです (よくないやり方とされる、CSS と JavaScript の混在やインラインスタイルの使用がありません)。もっと大規模で複雑なアプリを作り始めたら、多分二つ目のやり方をよく使うようになると思いますが、結局はホントにあなた次第です。

+ +

ここまで、実はそれほど役に立つことをやってません! 静的なコンテンツの作成に JavaScript を使う利点はありません — JavaScript など使わず、普通に HTML に書けば良いんです。HTML よりややこしいですし、コンテンツを JavaScript で作成するのは他にも問題があります (検索エンジンで読めない、とか)。

+ +

次の二つのセクションでは、DOM API のもっと実践的な使い方を見ていきます。

+ +
+

注記: 私たちによる dom-example.htm l完成版 のデモが GitHub にあります (ライブ実行もどうぞー)。

+
+ +

実践学習: ウィンドウオブジェクトから使える情報を取り出す

+ +

ここまででは文書を操作するための {{domxref("Node")}} と {{domxref("Document")}} の機能ばかり見てきましたが、他のソースからデータを取ってきてあなたの UI で使ったって勿論かまわないわけです。あなたはデータが正しい形式である事を確認するだけです。これは JavaScript が弱い型付け言語であるために、他の多く言語の場合よりも簡単です — 例えば画面に表示しようとしたとき、数値は自動的に文字列に変換されます。

+ +

ここの例題ではよくある問題を解決していきます — あなたのアプリを表示しているウィンドウがどんな大きさであれ、それを同じ大きさになるようにすることです。これはゲームのような、表示する画面領域をできるだけ大きくしたいような場合に、しばしば役に立ちます。

+ +

まずは window-resize-example.htmlbgtile.png ファイルのローカルコピーを作成して下さい。読み込んで見てみて下さい — 背景に画像がタイル表示された、{{htmlelement("div")}} 要素が画面に小さく表示されているでしょう。この領域が、私たちのアプリの UI 領域だとしていきます。

+ +
    +
  1. まず最初に、div への参照を取得し、ビューポート (ドキュメントが表示されている内側のウィンドウです) の幅と高さを取得して、これらを変数に保存します。便利なことに幅と高さの値は {{domxref("Window.innerWidth")}} と {{domxref("Window.innerHeight")}} プロパティにあります。以下の行を、もう書いてある {{htmlelement("script")}} の中に書き足します: +
    const div = document.querySelector('div');
    +let winWidth = window.innerWidth;
    +let winHeight = window.innerHeight;
    +
  2. +
  3. 次は、動的に div の幅と高さをビューポートのものと同じにします。次の二行を、さっき追加した部分の後に書き足して下さい: +
    div.style.width = winWidth + 'px';
    +div.style.height = winHeight + 'px';
    +
  4. +
  5. 保存してブラウザーで読み直してみて下さい — どんな大きさの画面を使っているのであれ、div がビューポートと同じ大きさになったはずです。ウィンドウが大きくなるようにリサイズしてみても、div の大きさは変わらないはずです — 一度しか大きさを設定していないからです。
  6. +
  7. ウィンドウがリサイズされた時に div もリサイズされるよう、イベントを使ってみるのはどうでしょう? {{domxref("Window")}} オブジェクトにはリサイズされた時に呼ばれるイベントがあって、ウィンドウがリサイズされる毎発火します — この機能を {{domxref("Window.onresize")}} イベントハンドラーから使って、リサイズされる毎私たちのコードが再実行されるようにしてみましょう。あなたのコードの最後に以下を書き足して下さい: +
    window.onresize = function() {
    +  winWidth = window.innerWidth;
    +  winHeight = window.innerHeight;
    +  div.style.width = winWidth + 'px';
    +  div.style.height = winHeight + 'px';
    +}
    +
  8. +
+ +
+

注記: もし行き詰まったら、私たちによる 完成版ウィンドウリサイズ例題 (ライブ実行版もあるよ) を見て下さい。

+
+ +

実践学習: 動的な買い物リスト

+ +

この記事の締めとして、あなたにちょっとした難題を出したいと思います — 単純な買い物リストの例を作ってもらいます。フォーム入力(input)とボタンからリストに動的に商品を追加できるようにします。input に商品を入力してボタンを押したら:

+ + + +

完成版のデモはこんな感じになるでしょう:

+ +

+ +

この課題を完了させるには、以下のステップに従い、上で説明した通りに買い物リストが動くようにして下さい。

+ +
    +
  1. まず私たちが用意した shopping-list.html 初期ファイルをダウンロードしてローカルコピーをどこかに作成します。最小限の CSS、ラベルのついたリスト、inputとボタン、空のリストと {{htmlelement("script")}} 要素が書いてあるはずです。この先書き足していくものは全部 script の中に書きます。
  2. +
  3. ({{htmlelement("ul")}}) と {{htmlelement("input")}} と {{htmlelement("button")}} 要素への参照を保持する3つの変数を作成します。
  4. +
  5. ボタンがクリックされた時の応答として走らせる 関数 を作成します。
  6. +
  7. 関数本体は、input 要素の現在の を変数に保存するところから始めます。
  8. +
  9. 次に、input 要素の値に空文字列('')を代入して、input 要素を空にします。
  10. +
  11. 3つの要素を作成します — リスト項目({{htmlelement('li')}}) と {{htmlelement('span')}} と {{htmlelement('button')}} で、これらを変数に保存します。
  12. +
  13. span と button をリスト項目 li の子に追加します。
  14. +
  15. spanのテキストコンテントに、先程保存した input 要素の値を代入し、ボタンのテキストコンテントを「削除」にします。
  16. +
  17. できたリスト項目をリストの子に追加します。
  18. +
  19. 削除ボタンにイベントハンドラーを追加して、クリックされたらボタンが含まれているリスト項目全体を削除するようにします。
  20. +
  21. 最後に、focus()メソッドを使って input 要素にフォーカスし、次の買い物リスト商品をすぐに入力できるようにします。
  22. +
+ +
+

注記: 本当にどうしようもなく詰まったら、私たちの 完成版買い物リスト (ライブ実行版もあるよ)を見て下さい。

+
+ +

まとめ

+ +

私たちのドキュメントと DOM 操作に関する学習はこれで終わりです。ここまでくれば、ドキュメントの制御やユーザのウェブ体験に関するブラウザーの重要な部品は何か、理解できたと思います。一番大事な DOM とは何か、役に立つ機能を作るのにこれをどう使えば良いのか理解できたと思います。

+ +

参考文献

+ +

ドキュメントをいじるのに役立つ機能はたくさんあります。私たちのリファレンスも見て、いろいろ発見して下さい:

+ + + +

(私共の Web API index から、MDNにあるウェブAPIに関する全ドキュメント一覧も見て下さい!)

+ +
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}
+ +
+

このモジュール内の文書

+ + +
+ +
+
+
+ +
+
+
+ +
+

+ +

+
+
+
+
+
diff --git a/files/ja/learn/javascript/client-side_web_apis/third_party_apis/index.html b/files/ja/learn/javascript/client-side_web_apis/third_party_apis/index.html new file mode 100644 index 0000000000..b44a2b17bf --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/third_party_apis/index.html @@ -0,0 +1,442 @@ +--- +title: サードパーティ API +slug: Learn/JavaScript/Client-side_web_APIs/Third_party_APIs +tags: + - 3rd party + - API + - Beginner + - CodingScripting + - Google Maps + - Learn + - NYTimes + - Third party + - youtube +translation_of: Learn/JavaScript/Client-side_web_APIs/Third_party_APIs +--- +
{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

これまで説明してきた API はブラウザーに組み込まれていましたが、すべての API がそうというわけではありません。Google Maps・Twitter・Facebook・PayPal などの大規模なサイトやサービスの多くは開発者がそれらのデータ (ブログに Twitter のストリームを表示するなど) やサービス (ユーザーのログインに Facebook ログインを利用するなど) を利用できるように API を提供しています。この記事ではブラウザー API とサードパーティ API の違いを見て、後者の典型的な使い方について説明します。

+ + + + + + + + + + + + +
前提知識:JavaScript の基礎 (JavaScript の第一歩, JavaScript の構成要素, JavaScript オブジェクト入門 をご覧ください),クライアントサイド API の基礎
到達目標:サードパーティ API の仕組み、それらを利用してウェブサイトを強化する方法を学習する
+ +

サードパーティAPIとは?

+ +

サードパーティ API は、サードパーティ (通常は Facebook、Twitter、Google などの企業) が提供する API で、JavaScript を介して機能にアクセスしてサイトで使用することができます。最もわかりやすい例の 1 つとして、マッピング API を使用してページにカスタムマップを表示することがあります。

+ +

Simple Mapquest API の例を参考に、サードパーティ API とブラウザー API の違いを説明します。

+ +
+

注意: 一度にすべてのコード例を取得したい場合があります。その場合は、各セクションで必要なサンプルファイルをレポジトリーで検索するだけで済みます。

+
+ +

それらはサードパーティのサーバーにあります

+ +

ブラウザー API はブラウザーに組み込まれており、すぐに JavaScript からアクセスできます。たとえば、紹介記事で見たWeb Audio API は、ネイティブの {{domxref("AudioContext")}} オブジェクトを使ってアクセスします。例えば:

+ +
const audioCtx = new AudioContext();
+  ...
+const audioElement = document.querySelector('audio');
+  ...
+const audioSource = audioCtx.createMediaElementSource(audioElement);
+// etc.
+ +

一方、サードパーティの API はサードパーティのサーバーにあります。JavaScript からこれらにアクセスするには、まず API 機能に接続してページで利用できるようにする必要があります。 これは通常、Mapquest の例で見られるように、{{htmlelement("script")}} 要素を介してサーバー上で利用可能な JavaScript ライブラリーへの最初のリンクを含めます。

+ +
<script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script>
+<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/>
+ +

そのライブラリーで利用可能なオブジェクトを使い始めることができます。例えば:

+ +
let map = L.mapquest.map('map', {
+  center: [53.480759, -2.242631],
+  layers: L.mapquest.tileLayer('map'),
+  zoom: 12
+});
+ +

ここでは、マップ情報を格納するための変数を作成し、次に mapquest.map() メソッドを使用して新しいマップを作成します。このメソッドは、必要な {{htmlelement("div")}} 要素の ID を受け取ります。('map') で地図を表示し、表示したい特定の地図の詳細を含む options オブジェクトを表示します。この場合は、地図の中心座標、表示する map 型の地図レイヤー (mapquest.tileLayer() メソッドを使用して作成)、およびデフォルトのズームレベルを指定します。

+ +

これが、Mapquest API が単純な地図を描くために必要なすべての情報です。接続しているサーバーは、表示されている地域の正しい地図タイルを表示するなど、複雑なものをすべて処理します。

+ +
+

メモ: API の中には、機能へのアクセスをわずかに異なる方法で処理するものがあり、開発者はデータを取得するために特定の URL パターンに対して HTTP リクエストを行う必要があります。これらは RESTful API と呼ばれ、後で例が出てきます

+
+ +

通常は API キーが必要です

+ +

最初の記事で説明したように、ブラウザー API のセキュリティは許可プロンプトによって処理される傾向があります。これらの目的は、ユーザーが訪問したウェブサイトで何が起こっているのかをユーザー自身が認識できるようにし、悪意のある方法で API を使用している人の被害にあう可能性を低くすることです。

+ +

サードパーティの API には、少し異なる権限システムがあります。開発者が API 機能にアクセスできるようにするために開発者キーを使用する傾向があります。

+ +

Mapquest API の例には、次のような行があります。

+ +
L.mapquest.key = 'YOUR-API-KEY-HERE';
+ +

この行では、アプリケーションで使用する API キーまたは開発者キーを指定します。アプリケーションの開発者は、キーを取得して API の機能へのアクセス許可を得るためにコードに含める必要があります。この例では、プレースホルダーを用意しました。

+ +
+

メモ: 独自の例を作成するときは、プレースホルダーの代わりに独自の API キーを使用します。

+
+ +

他の API では、少し異なる方法でキーを含める必要があるかもしれませんが、ほとんどのパターンは比較的似ています。

+ +

キーを要求することで、API プロバイダーは API のユーザーに自分のアクションに対する責任を持たせることができます。開発者がキーを登録すると、それらは API プロバイダに認識され、彼らが API に悪意のあることをし始めたらアクション (たとえば、人々の位置を追跡したり、APIを機能させないために大量のリクエストで API をスパムしようとするなど) を取ることができます。最も簡単なアクションは、単にそれらの API 特権を取り消すことです。

+ +

Mapquest の例を拡張する

+ +

API の他の機能の使用方法を示すために、Mapquest の例にさらに機能を追加しましょう。

+ +
    +
  1. +

    この章を始めるにあたり、新しいディレクトリーにmapquest starter fileをコピーしましょう。もしもすでにexamples repository をクローンしているようなら、必要な javascript/apis/third-party-apis/mapquest を見つけてコピーしてください。

    +
  2. +
  3. +

    次に Mapquest developer siteに行ってください。アカウントを作り、デベロッパーキーを使用してあなたのサンプルに利用してください。(アカウント作成時、デベロッパーキーは "consumer key" と呼ばれています。そして、"callback URL" を尋ねられると思いますが、その入力欄は空欄でかまいません)

    +
  4. +
  5. starting fileを開き、APIキーのプレスホルダーにあなたのキーを入力してください。
  6. +
+ +

地図の種類を変更する

+ +

Mapquest API で表示できるマップには、さまざまな種類があります。 これを行うには、次の行を見つけます。

+ +
layers: L.mapquest.tileLayer('map')
+ +

hybrid-style map にするために 'map''hybrid' に変えてみてください。他にも様々な値があります。tileLayer reference page には使える様々なオプションや情報が載っています。

+ +

さまざまなコントロールを追加する

+ +

この地図には様々な機能を実装できますが、デフォルトでは、ズームコントロールのみが表示されます。map.addControl() メソッドを使うことで機能を拡張することが出来ます。以下のコードをwindow.onloadハンドラーに追加してみてください。

+ +
map.addControl(L.mapquest.control());
+ +

mapquest.control() メソッドは、単純なフル機能のコントロールセットを作成するだけで、デフォルトでは右上隅に配置されます。position プロパティを含むコントロールのパラメータとしてオプションオブジェクトを指定することで、位置を調整することができます。例えば、次のようにしてみてください。

+ +
  map.addControl(L.mapquest.control({ position: 'bottomright' }));
+ +

他にも、mapquest.searchControl()mapquest.satelliteControl() など、利用可能なコントロールの種類があり、中には非常に複雑で強力なものもあります。実際に遊んでみて、何ができるか見てみましょう。

+ +

カスタムマーカーを追加する

+ +

マップ上の特定のポイントにマーカー (アイコン) を追加するのは簡単です。L.marker() メソッドを使用するだけです (関連する Leaflet.js のドキュメントに記載されているようです)。次のコードを window.onload に追加します。

+ +
L.marker([53.480759, -2.242631], {
+  icon: L.mapquest.icons.marker({
+    primaryColor: '#22407F',
+    secondaryColor: '#3B5998',
+    shadow: true,
+    size: 'md',
+    symbol: 'A'
+  })
+})
+.bindPopup('This is Manchester!')
+.addTo(map);
+ +

ご覧のように、最もシンプルな方法では、2 つのパラメータを取ります。マーカーを表示する座標を含む配列と、その時点で表示するアイコンを定義する icon プロパティを含むオプションオブジェクトです。

+ +

アイコンは、mapquest.icons.marker() メソッドを使用して定義され、ご覧のようにマーカーの色やサイズなどの情報が含まれています。

+ +

最初のメソッド呼び出しの最後に .bindPopup('This is Manchester!') を連鎖させ、マーカーがクリックされたときに表示されるコンテンツを定義します。

+ +

最後に、.addTo(map) を連鎖させて、実際にマーカーをマップに追加します。

+ +

ドキュメントに記載されているその他のオプションを試してみて、何ができるか見てみましょう。Mapquest には、道案内や検索など、かなり高度な機能があります。

+ +
+

Note: サンプルがうまく動作しない場合は、完成版のコードをチェックしてみてください。expanded-example.html を参照してください (ここでライブで実行しているのも見てください)。

+
+ +

Google マップはどうですか?

+ +

Google Maps は間違いなく最も人気のある地図 API です。使用方法を示すために例を作成しましたが、最終的にはいくつかの理由から Mapquest を使用しました:

+ + + +

RESTful API — NYTimes

+ +

では、もう一つのAPIの例を見てみましょう — New York Times API です。この API を使用すると、New York Times のニュースストーリー情報を取得して、サイトに表示することができます。このタイプの API は RESTful API として知られています。Mapquest で行ったように JavaScript ライブラリーの機能を使用してデータを取得するのではなく、特定の URL にHTTP リクエストを行い、検索語やその他のプロパティのようなデータを URL 内にエンコードしてデータを取得します (多くの場合、URL パラメーターとして)。これは、API でよく見られるパターンです。

+ +

サードパーティAPIを利用するためのアプローチ

+ +

以下では、NYTimes API の使用方法を示すエクササイズを紹介しますが、新しい API を使用するためのアプローチとして、より一般的なステップのセットを提供します。

+ +

ドキュメントを探す

+ +

サードパーティの API を利用したい場合、その API がどのような機能を持っているのか、どのように利用するのかなどを知るために、ドキュメントがどこにあるのかを知ることは欠かせません。New York Times API のドキュメントは https://developer.nytimes.com/ にあります。

+ +

開発者キーを取得

+ +

ほとんどの API では、セキュリティと説明責任のために、何らかの開発者キー使用する必要があります。NYTimes API キーの登録には、https://developer.nytimes.com/get-started の指示に従ってください。

+ +
    +
  1. +

    記事検索 API のキーを要求してみよう — 新規アプリを作成し、これを利用したい API として選択します (名前と説明を記入し、「記事検索 API 」の下のスイッチをオンに切り替えて「作成」をクリックします)。

    +
  2. +
  3. +

    結果のページから API キーを取得します。

    +
  4. +
  5. +

    さて、例題を始めるために、nytimes_start.htmlnytimes.css のコピーをコンピュータ上の新しいディレクトリに作成してください。すでに examples リポジトリをクローンしている場合は、javascript/apis/third-party-apis/nytimes ディレクトリにあるこれらのファイルのコピーをすでに持っているでしょう。最初に <script> 要素には、例のセットアップに必要な変数がいくつか含まれています。

    +
  6. +
+ +

このアプリは、検索用語とオプションの開始日と終了日を入力することを可能にし、Article Search API をクエリして検索結果を表示するために使用します。

+ +

+ +

API をアプリに接続する

+ +

まず、API とアプリ間の接続を行う必要があります。この API の場合、サービスから正しい URL でデータを要求するたびに、API キーを取得パラメーターとして含める必要があります。

+ +
    +
  1. +

    次の行を探します。

    + +
    let key = ' ... ';
    + +

    既存の API キーを、前のセクションで取得した実際の API キーに置き換えます。

    + +

    JavaScriptに次の行を追加してください。// Event listeners to control the functionality コメントの下に、次の行を追加します。これは、フォームが送信されたとき (ボタンが押されたとき) に submitSearch() という関数を実行します。

    + +
    searchForm.addEventListener('submit', submitSearch);
    +
  2. +
  3. +

    前の行の下に submitSearch() と fetchResults() 関数の定義を追加します。

    + +
    function submitSearch(e) {
    +  pageNumber = 0;
    +  fetchResults(e);
    +}
    +
    +function fetchResults(e) {
    +  // Use preventDefault() to stop the form submitting
    +  e.preventDefault();
    +
    +  // Assemble the full URL
    +  url = baseURL + '?api-key=' + key + '&page=' + pageNumber + '&q=' + searchTerm.value + '&fq=document_type:("article")';
    +
    +  if(startDate.value !== '') {
    +    url += '&begin_date=' + startDate.value;
    +  };
    +
    +  if(endDate.value !== '') {
    +    url += '&end_date=' + endDate.value;
    +  };
    +
    +}
    +
  4. +
+ +

submitSearch() は最初にページ番号を 0 に戻してから fetchResults() を呼び出します。これは最初にイベントオブジェクトの preventDefault() を呼び出し、フォームが実際に送信されるのを止めるためです (これでは例が壊れてしまいます)。次に、文字列を操作してリクエスト先の完全な URL を組み立てます。このデモで必須と思われる部分を組み立てることから始めます。

+ + + +

次に、いくつかの if() ステートメントを使用して、startDateendDate <input> に値が入力されているかどうかをチェックします。記入されている場合は、それぞれ begin_dateend_date の URL パラメーターで指定された値を URL に追加します。

+ +

そのため、完全な URL は次のような形になってしまいます。

+ +
https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=YOUR-API-KEY-HERE&page=0&q=cats
+&fq=document_type:("article")&begin_date=20170301&end_date=20170312
+ +
+

Note: どのようなURLパラメーターを含めることができるかについての詳細は、NYTimes developer docs を参照してください。

+
+ +
+

Note: この例では初歩的なフォームデータの検証を行っています — 検索語フィールドは、フォームを送信する前に入力しなければなりません (required 属性を使用して達成されます)。日付フィールドには pattern 属性が指定されており、値が 8 個の数字 (pattern="[0-9]{8}") で構成されていないと送信されません。これらがどのように機能するかについての詳細は Form data validation を参照してください。

+
+ +

API からデータを要求する

+ +

これで URL を作成したので、それにリクエストしてみましょう。これは Fetch API を使って行います。

+ +

以下のコードブロックを fetchResults() 関数の中に追加します:

+ +
// Use fetch() to make the request to the API
+fetch(url).then(function(result) {
+  return result.json();
+}).then(function(json) {
+  displayResults(json);
+});
+ +

ここでは、url 変数を fetch() に渡してリクエストを実行し、json() 関数を使用してレスポンスボディを JSON に変換し、結果の JSON を displayResults() 関数に渡して、データを UI に表示できるようにします。

+ +

データを表示する

+ +

それでは、データを表示する方法を見てみましょう。 fetchResults() 関数の下に以下の関数を追加します。

+ +
function displayResults(json) {
+  while (section.firstChild) {
+      section.removeChild(section.firstChild);
+  }
+
+  const articles = json.response.docs;
+
+  if(articles.length === 10) {
+    nav.style.display = 'block';
+  } else {
+    nav.style.display = 'none';
+  }
+
+  if(articles.length === 0) {
+    const para = document.createElement('p');
+    para.textContent = 'No results returned.'
+    section.appendChild(para);
+  } else {
+    for(var i = 0; i < articles.length; i++) {
+      const article = document.createElement('article');
+      const heading = document.createElement('h2');
+      const link = document.createElement('a');
+      const img = document.createElement('img');
+      const para1 = document.createElement('p');
+      const para2 = document.createElement('p');
+      const clearfix = document.createElement('div');
+
+      let current = articles[i];
+      console.log(current);
+
+      link.href = current.web_url;
+      link.textContent = current.headline.main;
+      para1.textContent = current.snippet;
+      para2.textContent = 'Keywords: ';
+      for(let j = 0; j < current.keywords.length; j++) {
+        const span = document.createElement('span');
+        span.textContent += current.keywords[j].value + ' ';
+        para2.appendChild(span);
+      }
+
+      if(current.multimedia.length > 0) {
+        img.src = 'http://www.nytimes.com/' + current.multimedia[0].url;
+        img.alt = current.headline.main;
+      }
+
+      clearfix.setAttribute('class','clearfix');
+
+      article.appendChild(heading);
+      heading.appendChild(link);
+      article.appendChild(img);
+      article.appendChild(para1);
+      article.appendChild(para2);
+      article.appendChild(clearfix);
+      section.appendChild(article);
+    }
+  }
+}
+ +

ここにはたくさんのコードがあります:

+ + + +

ページネーションボタンの配線

+ +

ページ分割ボタンを動作させるために、pageNumber 変数の値をインクリメント (またはデクリメント) し、ページ URL パラメーターに含まれる新しい値でフェッチリクエストを再実行します。これは、NYTimes API が一度に 10 件の結果しか返さないからです — 10 件以上の結果が利用可能な場合、page URL パラメーターが 0 に設定されている場合は最初の 10 (0-9) を (または全く含まれない — 0 がデフォルト値です。) 1 に設定されている場合は次の 10 (10-19) を返します。

+ +

これにより、単純なページネーション関数を簡単に書くことができるようになりました。

+ +
    +
  1. +

    既存の addEventListener() コールの下に、関連するボタンがクリックされたときに nextPage() および previousPage() 関数が呼び出されるように、これら 2 つの新しいものを追加します:

    + +
    nextBtn.addEventListener('click', nextPage);
    +previousBtn.addEventListener('click', previousPage);
    +
  2. +
  3. +

    前回の追加の下に、2 つの関数を定義してみましょう — 今すぐこのコードを追加します:

    + +
    function nextPage(e) {
    +  pageNumber++;
    +  fetchResults(e);
    +};
    +
    +function previousPage(e) {
    +  if(pageNumber > 0) {
    +    pageNumber--;
    +  } else {
    +    return;
    +  }
    +  fetchResults(e);
    +};
    + +

    最初の関数は単純で、変数 pageNumber をインクリメントしてから、次のページの結果を表示するために fetchResults() 関数を再度実行します。

    + +

    2 番目の関数は逆の方法でほぼ正確に同じように動作しますが、pageNumber がすでに 0 ではないことを確認するという余分なステップを踏まなければなりません — もしフェッチリクエストがマイナスの page パラメーターで実行された場合、エラーを引き起こす可能性があります。もし pageNumber がすでに 0 であれば、処理能力を無駄にしないように、単に関数から return します (すでに最初のページにいるのであれば、同じ結果を再び読み込む必要はありません)。

    +
  4. +
+ +
+

Note: 完成した nytimes API のサンプルコードは GitHub で見ることができます (ここでもライブで動作しています) 。

+
+ +

YouTube の例

+ +

また、YouTube video search example をご覧ください。これは 2 つの関連する API を使用しています。

+ + + +

この例は、2つの関連するサードパーティ API を一緒に使用してアプリを構築していることを示しているので興味深いです。1 つ目は RESTful API で、2 つ目は Mapquest のように動作します (API 固有のメソッドなどがあります)。ただし、どちらの API もページに適用するために JavaScript ライブラリを必要とする点は注目に値します。RESTful API には、HTTP リクエストを行い、結果を返すための関数が用意されています。

+ +

+ +

この例については、記事の中ではあまり多くを語るつもりはありません。ソースコードには、それがどのように動作するかを説明するために、その中に詳細なコメントが挿入されています。

+ +

稼動させるために必要です:

+ + + +

まとめ

+ +

この記事では、サードパーティ API を使用してウェブサイトに機能を追加するための便利な方法を紹介しました。

+ +

{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}}

+ +

このモジュール

+ +
+ +
diff --git a/files/ja/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html b/files/ja/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html new file mode 100644 index 0000000000..09e6e27ca7 --- /dev/null +++ b/files/ja/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html @@ -0,0 +1,507 @@ +--- +title: 動画と音声の API +slug: Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs +tags: + - API + - Audio + - Beginner + - CodingScripting + - Guide + - JavaScript + - Learn + - Video + - 記事 +translation_of: Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Learn/JavaScript/Client-side_web_APIs")}}
+ +

HTML5 comes with elements for embedding rich media in documents — {{htmlelement("video")}} and {{htmlelement("audio")}} — which in turn come with their own APIs for controlling playback, seeking, etc. This article shows you how to do common tasks such as creating custom playback controls.

+ + + + + + + + + + + + +
前提条件:JavaScript basics (see first steps, building blocks, JavaScript objects), the basics of Client-side APIs
目的:To learn how to use browser APIs to control video and audio playback.
+ +

HTML5 video と audio

+ +

The {{htmlelement("video")}} and {{htmlelement("audio")}} elements allow us to embed video and audio into web pages. As we showed in Video and audio content, a typical implementation looks like this:

+ +
<video controls>
+  <source src="rabbit320.mp4" type="video/mp4">
+  <source src="rabbit320.webm" type="video/webm">
+  <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
+</video>
+ +

This creates a video player inside the browser like so:

+ +

{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html", '100%', 380)}}

+ +

You can review what all the HTML features do in the article linked above; for our purposes here, the most interesting attribute is {{htmlattrxref("controls", "video")}}, which enables the default set of playback controls. If you don't specify this, you get no playback controls:

+ +

{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats-no-controls.html", '100%', 380)}}

+ +

This is not as immediately useful for video playback, but it does have advantages. One big issue with the native browser controls is that they are different in each browser — not very good for cross-browser support! Another big issue is that the native controls in most browsers aren't very keyboard-accessible.

+ +

You can solve both these problems by hiding the native controls (by removing the controls attribute), and programming your own with HTML, CSS, and JavaScript. In the next section we'll look at the basic tools we have available to do this.

+ +

The HTMLMediaElement API

+ +

Part of the HTML5 spec, the {{domxref("HTMLMediaElement")}} API provides features to allow you to control video and audio players programmatically — for example {{domxref("HTMLMediaElement.play()")}}, {{domxref("HTMLMediaElement.pause()")}}, etc. This interface is available to both {{htmlelement("audio")}} and {{htmlelement("video")}} elements, as the features you'll want to implement are nearly identical. Let's go through an example, adding features as we go.

+ +

Our finished example will look (and function) something like the following:

+ +

{{EmbedGHLiveSample("learning-area/javascript/apis/video-audio/finished/", '100%', 360)}}

+ +

Getting started

+ +

To get started with this example, download our media-player-start.zip and unzip it into a new directory on your hard drive. If you downloaded our examples repo, you'll find it in javascript/apis/video-audio/start/

+ +

At this point, if you load the HTML you should see a perfectly normal HTML5 video player, with the native controls rendered.

+ +

Exploring the HTML

+ +

Open the HTML index file. You'll see a number of features; the HTML is dominated by the video player and its controls:

+ +
<div class="player">
+  <video controls>
+    <source src="video/sintel-short.mp4" type="video/mp4">
+    <source src="video/sintel-short.webm" type="video/webm">
+    <!-- fallback content here -->
+  </video>
+  <div class="controls">
+    <button class="play" data-icon="P" aria-label="play pause toggle"></button>
+    <button class="stop" data-icon="S" aria-label="stop"></button>
+    <div class="timer">
+      <div></div>
+      <span aria-label="timer">00:00</span>
+    </div>
+    <button class="rwd" data-icon="B" aria-label="rewind"></button>
+    <button class="fwd" data-icon="F" aria-label="fast forward"></button>
+  </div>
+</div>
+
+ + + +

Exploring the CSS

+ +

Now open the CSS file and have a look inside. The CSS for the example is not too complicated, but we'll highlight the most interesting bits here. First of all, notice the .controls styling:

+ +
.controls {
+  visibility: hidden;
+  opacity: 0.5;
+  width: 400px;
+  border-radius: 10px;
+  position: absolute;
+  bottom: 20px;
+  left: 50%;
+  margin-left: -200px;
+  background-color: black;
+  box-shadow: 3px 3px 5px black;
+  transition: 1s all;
+  display: flex;
+}
+
+.player:hover .controls, player:focus .controls {
+  opacity: 1;
+}
+
+ + + +

Next, let's look at our button icons:

+ +
@font-face {
+   font-family: 'HeydingsControlsRegular';
+   src: url('fonts/heydings_controls-webfont.eot');
+   src: url('fonts/heydings_controls-webfont.eot?#iefix') format('embedded-opentype'),
+        url('fonts/heydings_controls-webfont.woff') format('woff'),
+        url('fonts/heydings_controls-webfont.ttf') format('truetype');
+   font-weight: normal;
+   font-style: normal;
+}
+
+button:before {
+  font-family: HeydingsControlsRegular;
+  font-size: 20px;
+  position: relative;
+  content: attr(data-icon);
+  color: #aaa;
+  text-shadow: 1px 1px 0px black;
+}
+ +

First of all, at the top of the CSS we use a {{cssxref("@font-face")}} block to import a custom web font. This is an icon font — all the characters of the alphabet equate to common icons you might want to use in an application.

+ +

Next we use generated content to display an icon on each button:

+ + + +

Icon fonts are very cool for many reasons — cutting down on HTTP requests because you don't need to download those icons as image files, great scalability, and the fact that you can use text properties to style them — like {{cssxref("color")}} and {{cssxref("text-shadow")}}.

+ +

Last but not least, let's look at the CSS for the timer:

+ +
.timer {
+  line-height: 38px;
+  font-size: 10px;
+  font-family: monospace;
+  text-shadow: 1px 1px 0px black;
+  color: white;
+  flex: 5;
+  position: relative;
+}
+
+.timer div {
+  position: absolute;
+  background-color: rgba(255,255,255,0.2);
+  left: 0;
+  top: 0;
+  width: 0;
+  height: 38px;
+  z-index: 2;
+}
+
+.timer span {
+  position: absolute;
+  z-index: 3;
+  left: 19px;
+}
+ + + +

Implementing the JavaScript

+ +

We've got a fairly complete HTML and CSS interface already; now we just need to wire up all the buttons to get the controls working.

+ +
    +
  1. +

    Create a new JavaScript file in the same directory level as your index.html file. Call it custom-player.js.

    +
  2. +
  3. +

    At the top of this file, insert the following code:

    + +
    const media = document.querySelector('video');
    +const controls = document.querySelector('.controls');
    +
    +const play = document.querySelector('.play');
    +const stop = document.querySelector('.stop');
    +const rwd = document.querySelector('.rwd');
    +const fwd = document.querySelector('.fwd');
    +
    +const timerWrapper = document.querySelector('.timer');
    +const timer = document.querySelector('.timer span');
    +const timerBar = document.querySelector('.timer div');
    +
    + +

    Here we are creating constants to hold references to all the objects we want to manipulate. We have three groups:

    + +
      +
    • The <video> element, and the controls bar.
    • +
    • The play/pause, stop, rewind, and fast forward buttons.
    • +
    • The outer timer wrapper <div>, the digital timer readout <span>, and the inner <div> that gets wider as the time elapses.
    • +
    +
  4. +
  5. +

    Next, insert the following at the bottom of your code:

    + +
    media.removeAttribute('controls');
    +controls.style.visibility = 'visible';
    + +

    These two lines remove the default browser controls from the video, and make the custom controls visible.

    +
  6. +
+ +

Playing and pausing the video

+ +

Let's implement probably the most important control — the play/pause button.

+ +
    +
  1. +

    First of all, add the following to the bottom of your code, so that the playPauseMedia() function is invoked when the play button is clicked:

    + +
    play.addEventListener('click', playPauseMedia);
    +
    +
  2. +
  3. +

    Now to define playPauseMedia() — add the following, again at the bottom of your code:

    + +
    function playPauseMedia() {
    +  if(media.paused) {
    +    play.setAttribute('data-icon','u');
    +    media.play();
    +  } else {
    +    play.setAttribute('data-icon','P');
    +    media.pause();
    +  }
    +}
    + +

    Here we use an if statement to check whether the video is paused. The {{domxref("HTMLMediaElement.paused")}} property returns true if the media is paused, which is any time the video is not playing, including when it is set at 0 duration after it first loads. If it is paused, we set the data-icon attribute value on the play button to "u", which is a "paused" icon, and invoke the {{domxref("HTMLMediaElement.play()")}} method to play the media.

    + +

    On the second click, the button will be toggled back again — the "play" icon will be shown again, and the video will be paused with {{domxref("HTMLMediaElement.pause()")}}.

    +
  4. +
+ +

Stopping the video

+ +
    +
  1. +

    Next, let's add functionality to handle stopping the video. Add the following addEventListener() lines below the previous one you added:

    + +
    stop.addEventListener('click', stopMedia);
    +media.addEventListener('ended', stopMedia);
    +
    + +

    The {{event("click")}} event is obvious — we want to stop the video by running our stopMedia() function when the stop button is clicked. We do however also want to stop the video when it finishes playing — this is marked by the {{event("ended")}} event firing, so we also set up a listener to run the function on that event firing too.

    +
  2. +
  3. +

    Next, let's define stopMedia() — add the following function below playPauseMedia():

    + +
    function stopMedia() {
    +  media.pause();
    +  media.currentTime = 0;
    +  play.setAttribute('data-icon','P');
    +}
    +
    + +

    there is no stop() method on the HTMLMediaElement API — the equivalent is to pause() the video, and set its {{domxref("HTMLMediaElement.currentTime","currentTime")}} property to 0. Setting currentTime to a value (in seconds) immediately jumps the media to that position.

    + +

    All there is left to do after that is to set the displayed icon to the "play" icon. Regardless of whether the video was paused or playing when the stop button is pressed, you want it to be ready to play afterwards.

    +
  4. +
+ +

Seeking back and forth

+ +

There are many ways that you can implement rewind and fast forward functionality; here we are showing you a relatively complex way of doing it, which doesn't break when the different buttons are pressed in an unexpected order.

+ +
    +
  1. +

    First of all, add the following two addEventListener() lines below the previous ones:

    + +
    rwd.addEventListener('click', mediaBackward);
    +fwd.addEventListener('click', mediaForward);
    +
    +
  2. +
  3. +

    Now on to the event handler functions — add the following code below your previous functions to define mediaBackward() and mediaForward():

    + +
    let intervalFwd;
    +let intervalRwd;
    +
    +function mediaBackward() {
    +  clearInterval(intervalFwd);
    +  fwd.classList.remove('active');
    +
    +  if(rwd.classList.contains('active')) {
    +    rwd.classList.remove('active');
    +    clearInterval(intervalRwd);
    +    media.play();
    +  } else {
    +    rwd.classList.add('active');
    +    media.pause();
    +    intervalRwd = setInterval(windBackward, 200);
    +  }
    +}
    +
    +function mediaForward() {
    +  clearInterval(intervalRwd);
    +  rwd.classList.remove('active');
    +
    +  if(fwd.classList.contains('active')) {
    +    fwd.classList.remove('active');
    +    clearInterval(intervalFwd);
    +    media.play();
    +  } else {
    +    fwd.classList.add('active');
    +    media.pause();
    +    intervalFwd = setInterval(windForward, 200);
    +  }
    +}
    +
    + +

    You'll notice that first we initialize two variables — intervalFwd and intervalRwd — you'll find out what they are for later on.

    + +

    Let's step through mediaBackward() (the functionality for mediaForward() is exactly the same, but in reverse):

    + +
      +
    1. We clear any classes and intervals that are set on the fast forward functionality — we do this because if we press the rwd button after pressing the fwd button, we want to cancel any fast forward functionality and replace it with the rewind functionality. If we tried to do both at one, the player would break.
    2. +
    3. We use an if statement to check whether the active class has been set on the rwd button, indicating that it has already been pressed. The {{domxref("Element.classList", "classList")}} is a rather handy property that exists on every element — it contains a list of all the classes set on the element, as well as methods for adding/removing classes, etc. We use the classList.contains() method to check whether the list contains the active class. This returns a boolean true/false result.
    4. +
    5. If active has been set on the rwd button, we remove it using classList.remove(), clear the interval that has been set when the button was first pressed (see below for more explanation), and use {{domxref("HTMLMediaElement.play()")}} to cancel the rewind and start the video playing normally.
    6. +
    7. If it hasn't yet been set, we add the active class to the rwd button using classList.add(), pause the video using {{domxref("HTMLMediaElement.pause()")}}, then set the intervalRwd variable to equal a {{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}} call. When invoked, setInterval() creates an active interval, meaning that it runs the function given as the first parameter every x milliseconds, where x is the value of the 2nd parameter. So here we are running the windBackward() function every 200 milliseconds — we'll use this function to wind the video backwards constantly. To stop a {{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}} running, you have to call {{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}}, giving it the identifying name of the interval to clear, which in this case is the variable name intervalRwd (see the clearInterval() call earlier on in the function).
    8. +
    +
  4. +
  5. +

    Finally, we need to define the windBackward() and windForward() functions invoked in the setInterval() calls. Add the following below your two previous functions:

    + +
    function windBackward() {
    +  if(media.currentTime <= 3) {
    +    rwd.classList.remove('active');
    +    clearInterval(intervalRwd);
    +    stopMedia();
    +  } else {
    +    media.currentTime -= 3;
    +  }
    +}
    +
    +function windForward() {
    +  if(media.currentTime >= media.duration - 3) {
    +    fwd.classList.remove('active');
    +    clearInterval(intervalFwd);
    +    stopMedia();
    +  } else {
    +    media.currentTime += 3;
    +  }
    +}
    + +

    Again, we'll just run through the first one of these functions as they work almost identically, but in reverse to one another. In windBackward() we do the following — bear in mind that when the interval is active, this function is being run once every 200 milliseconds.

    + +
      +
    1. We start off with an if statement that checks to see whether the current time is less than 3 seconds, i.e., if rewinding by another three seconds would take it back past the start of the video. This would cause strange behaviour, so if this is the case we stop the video playing by calling stopMedia(), remove the active class from the rewind button, and clear the intervalRwd interval to stop the rewind functionality. If we didn't do this last step, the video would just keep rewinding forever.
    2. +
    3. If the current time is not within 3 seconds of the start of the video, we simply remove three seconds from the current time by executing media.currentTime -= 3. So in effect, we are rewinding the video by 3 seconds, once every 200 milliseconds.
    4. +
    +
  6. +
+ +

Updating the elapsed time

+ +

The very last piece of our media player to implement is the time elapsed displays. To do this we'll run a function to update the time displays every time the {{event("timeupdate")}} event is fired on the <video> element. The frequency with which this event fires depends on your browser, CPU power, etc (see this stackoverflow post).

+ +

Add the following addEventListener() line just below the others:

+ +
media.addEventListener('timeupdate', setTime);
+ +

Now to define the setTime() function. Add the following at the bottom of your file:

+ +
function setTime() {
+  let minutes = Math.floor(media.currentTime / 60);
+  let seconds = Math.floor(media.currentTime - minutes * 60);
+  let minuteValue;
+  let secondValue;
+
+  if (minutes < 10) {
+    minuteValue = '0' + minutes;
+  } else {
+    minuteValue = minutes;
+  }
+
+  if (seconds < 10) {
+    secondValue = '0' + seconds;
+  } else {
+    secondValue = seconds;
+  }
+
+  let mediaTime = minuteValue + ':' + secondValue;
+  timer.textContent = mediaTime;
+
+  let barLength = timerWrapper.clientWidth * (media.currentTime/media.duration);
+  timerBar.style.width = barLength + 'px';
+}
+
+ +

This is a fairly long function, so let's go through it step by step:

+ +
    +
  1. First of all, we work out the number of minutes and seconds in the {{domxref("HTMLMediaElement.currentTime")}} value.
  2. +
  3. Then we initialize two more variables — minuteValue and secondValue.
  4. +
  5. The two if statements work out whether the number of minutes and seconds are less than 10. If so, they add a leading zero to the values, in the same way that a digital clock display works.
  6. +
  7. The actual time value to display is set as minuteValue plus a colon character plus secondValue.
  8. +
  9. The {{domxref("Node.textContent")}} value of the timer is set to the time value, so it displays in the UI.
  10. +
  11. The length we should set the inner <div> to is worked out by first working out the width of the outer <div> (any element's {{domxref("Element.clientWidth", "clientWidth")}} property will contain its length), and then multiplying it by the {{domxref("HTMLMediaElement.currentTime")}} divided by the total {{domxref("HTMLMediaElement.duration")}} of the media.
  12. +
  13. We set the width of the inner <div> to equal the calculated bar length, plus "px", so it will be set to that number of pixels.
  14. +
+ +

Fixing play and pause

+ +

There is one problem left to fix. If the play/pause or stop buttons are pressed while the rewind or fast forward functionality is active, they just don't work. How can we fix it so that they cancel the rwd/fwd button functionality and play/stop the video as you'd expect? This is fairly easy to fix.

+ +

First of all, add the following lines inside the stopMedia() function — anywhere will do:

+ +
rwd.classList.remove('active');
+fwd.classList.remove('active');
+clearInterval(intervalRwd);
+clearInterval(intervalFwd);
+
+ +

Now add the same lines again, at the very start of the playPauseMedia() function (just before the start of the if statement).

+ +

At this point, you could delete the equivalent lines from the windBackward() and windForward() functions, as that functionality has been implemented in the stopMedia() function instead.

+ +

Note: You could also further improve the efficiency of the code by creating a separate function that runs these lines, then calling that anywhere it is needed, rather than repeating the lines multiple times in the code. But we'll leave that one up to you.

+ +

Summary

+ +

I think we've taught you enough in this article. The {{domxref("HTMLMediaElement")}} API makes a wealth of functionality available for creating simple video and audio players, and that's only the tip of the iceberg. See the "See also" section below for links to more complex and interesting functionality.

+ +

Here are some suggestions for ways you could enhance the existing example we've built up:

+ +
    +
  1. +

    The time display currently breaks if the video is an hour long or more (well, it won't display hours; just minutes and seconds). Can you figure out how to change the example to make it display hours?

    +
  2. +
  3. +

    Because <audio> elements have the same {{domxref("HTMLMediaElement")}} functionality available to them, you could easily get this player to work for an <audio> element too. Try doing so.

    +
  4. +
  5. +

    Can you work out a way to turn the timer inner <div> element into a true seek bar/scrobbler — i.e., when you click somewhere on the bar, it jumps to that relative position in the video playback? As a hint, you can find out the X and Y values of the element's left/right and top/bottom sides via the getBoundingClientRect() method, and you can find the coordinates of a mouse click via the event object of the click event, called on the {{domxref("Document")}} object. For example:

    + +
    document.onclick = function(e) {
    +  console.log(e.x) + ',' + console.log(e.y)
    +}
    +
  6. +
+ +

See also

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Learn/JavaScript/Client-side_web_APIs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/first_steps/a_first_splash/index.html b/files/ja/learn/javascript/first_steps/a_first_splash/index.html new file mode 100644 index 0000000000..3281944f5b --- /dev/null +++ b/files/ja/learn/javascript/first_steps/a_first_splash/index.html @@ -0,0 +1,610 @@ +--- +title: JavaScriptへの最初のダイブ +slug: Learn/JavaScript/First_steps/A_first_splash +tags: + - CodingScripting + - Conditionals + - JavaScript + - Objects + - Operators + - events + - 'l10n:priority' + - 初心者 + - 変数 + - 学習 + - 記事 + - 関数 +translation_of: Learn/JavaScript/First_steps/A_first_splash +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}
+ +

JavaScript の理論、そしてそれを使ってできることについて学んだところで、完全に実用的なチュートリアルを通じて、JavaScript の基本的な機能についての短期集中コースをお見せします。ここでは、簡単な「数字を当てる」ゲームをステップバイステップで構築します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターの知識および HTML と CSS への理解、JavaScript とは何かを知っている。
目的:簡単な JavaScript を書いてみて、JavaScript のプログラムを書くために必要な知識を会得する。
+ +

ここでは、JavaScript (とその他のプログラミング言語) がどのように動くのかという高度なコンセプトを紹介したいので、一度ですべての詳細を理解する必要はありません。詳細については続く記事にてご紹介しますので!

+ +
+

注記: JavaScript の機能として紹介する、関数や繰り返しなどの機能は、ほとんどが他のプログラミング言語にもあります。書き方は異なりますが、コンセプトは大体同じです。

+
+ +

プログラマーのように考える

+ +

プログラミングで一番難しいのは、書き方を覚えることではなく、現実の問題にどう適用するかということです。プログラマーのように考え始める必要があります — それは一般的に、そのプログラムが何をしなければならないかという説明を見て、それを満たすためにコードのどんな機能を用いるかを考え、さらにそれを組み合わせていかなければなりません。

+ +

これには努力・プログラミング文法の経験・練習に加え、少しの想像力が必要です。たくさんコードを書けばもっと慣れていくでしょう。たったの 5分で「プログラマー脳」を開発することは約束できませんが、このコースを通じてプログラマーのように考えるたくさんの機会を提供したいと思います。

+ +

まずはそれを念頭に置いてから、この記事で作るプログラムの実例を見てみましょう。さらにその後、具体的な手順に落とし込む方法について学習しましょう。

+ +

例: 数字当てゲーム

+ +

この記事では、以下に示す簡単なゲームを作る方法を紹介します。

+ + + +

{{ EmbedLiveSample('Top_hidden_code', '100%', 320, "", "", "hide-codepen-jsfiddle") }}

+ +

さあ、ゲームで遊んでみてください。次に進む前にゲームに慣れておきましょう。

+ +

上司から、次のように作るゲームの概要を聞いたところを想像してみてください。

+ +
+

数字を予想する単純なゲームを作って欲しい。ランダムな 1 から 100 の数字を決めて、プレイヤーに 10 回以内に当ててもらうゲームだ。プレイヤーには予想する都度、正解か間違いかを表示する。もしプレイヤーが間違っていれば、プレイヤーが予想した数字に応じて、大きすぎるか小さすぎるかを表示する。また、プレイヤーの前回の予想がどうだったかも表示する。ゲームはプレイヤーの予想が正しかった場合、もしくは回数の上限に達した場合に終了する。ゲームが終了したら、プレイヤーはもう一度プレイ開始できるようにする。

+
+ +

できるだけプログラマーのように考えると、この概要から最初に行うべきことは、簡潔な実行可能な単位に分割することです。

+ +
    +
  1. 1 から 100 までの数字をランダムに一つ生成する。
  2. +
  3. プレイヤーの予想した回数を記録する。最初は 1 回から。
  4. +
  5. プレイヤーが数字が何かを予想する方法を用意する。
  6. +
  7. 予想が入力されたら、プレイヤーが以前の予想を見られるように、どこかに記録する。
  8. +
  9. 入力された数字が正しいかどうかを調べる。
  10. +
  11. 入力された数字が正しい場合... +
      +
    1. 正解したお祝いのメッセージを表示する。
    2. +
    3. プレイヤーが次の予想を出来ないようにする。(ゲームがおかしくならないように)
    4. +
    5. プレイヤーが次のゲームを始められるようなコントロールを表示する。
    6. +
    +
  12. +
  13. プレイヤーの予想が間違いで、予想回数の上限にはまだ達していない場合... +
      +
    1. プレイヤーが間違っていることを表示する。
    2. +
    3. 次の予想を入力できるようにする。
    4. +
    5. 予想回数に 1 を加算する。
    6. +
    +
  14. +
  15. プレイヤーの予想が間違いで、予想回数の上限に達した場合... +
      +
    1. プレイヤーにゲームオーバーであることを伝える。
    2. +
    3. プレイヤーが次の予想を出来ないようにする。(ゲームがおかしくならないように)
    4. +
    5. プレイヤーが次のゲームを始められるようなコントロールを表示する。
    6. +
    +
  16. +
  17. ゲームがもう一度始まったら、画面とロジックが完全にリセットされるようにして、1.に戻る。
  18. +
+ +

さあ、先に進みましょう。この手順をどのようにコードにするのか見て、JavaScript の機能を探求していきましょう。

+ +

まず初めに

+ +

チュートリアルを開始するにあたり、自分のコンピューターに number-guessing-game-start.html ファイル (こちらでデモが見られます) をコピーしてください。テキストエディターとブラウザーの両方でそのファイルを開いてください。すると、簡単な見出しと説明の段落、予想を入力するフォームが見えるでしょう。ただし、そのフォームはまだ何もできません。

+ +

コードを入力するのはすべて HTML の一番下にある {{htmlelement("script")}} 要素の中です。

+ +
<script>
+
+  // JavaScript をここに書きます
+
+</script>
+
+ +

データを保持する変数を追加する

+ +

始めましょう。まず、{{htmlelement("script")}} 要素の中に以下の内容を書いてみてください。

+ +
let randomNumber = Math.floor(Math.random() * 100) + 1;
+
+const guesses = document.querySelector('.guesses');
+const lastResult = document.querySelector('.lastResult');
+const lowOrHi = document.querySelector('.lowOrHi');
+
+const guessSubmit = document.querySelector('.guessSubmit');
+const guessField = document.querySelector('.guessField');
+
+let guessCount = 1;
+let resetButton;
+ +

上記のコードはプログラムが使用するデータを保持する変数と定数をセットアップしています。変数とは基本的には値 (数字や文字など) の入れ物です。 let (か var)  キーワードに続いて変数の名前を書くことで、変数を作成します (これらのキーワードの違いは以降の記事で見ます) 。定数は変更しない値を保持するのに、 const キーワードといっしょに使います。この場合では、定数をユーザーインターフェイスのパーツへの参照を保存するのに使っていて、一部の内部のテキストは変わるかも知れませんが、参照されるHTML要素は同じままです。

+ +

等号記号 ( = ) に続いて、与えたい値を書いて、変数や定数に値を代入できます。

+ +

この例では:

+ + + +
+

注記: 変数や定数についてはこのコースの間に、次の記事を始めとして何度も出てきます。

+
+ +

関数

+ +

次に、以下のコードを先ほどの JavaScript に追加してください。

+ +
function checkGuess() {
+  alert('ここはプレースホルダです');
+}
+ +

関数は再利用可能なコードのかたまりです。何度も実行することができ、同じコードを書く手間を省けます。これはとても便利です。関数の書き方 (定義の仕方) はいくつかありますが、今回は集中するために、一つの簡単な書き方だけを使用します。ここでは function キーワードに続いて関数の名前、括弧 ( () )、中括弧 ( { } )が続く書き方で定義しました。中括弧の中に、関数を呼ぶたびに実行されるコードを書きます。

+ +

関数を実行したい場合には、関数の名前に続いて括弧を書きます。

+ +

それでは試してみましょう。コードを保存してブラウザーを再読み込みしてみてください。開発者ツールの JavaScript コンソールを開いてください。そして次のコードを実行します。

+ +
checkGuess();
+ +

Return/Enter を押した後で、"ここはプレースホルダです"という警告が表示されましたね。呼び出すと、いつでも警告が表示される関数を定義することができました。

+ +
+

注記: 関数についてもこのコースの後の方で詳しく学びます。

+
+ +

演算子

+ +

JavaScript で演算子を使用して値の確認をしたり、計算したり、文字を結合したりなど、いろいろなことができます。

+ +

コードを保存してブラウザーを再読み込みしてみてください。まだ開いていなければ、開発者ツールの JavaScript コンソールを開いて、表の「例」の列に書いてある通りに入力してみましょう。例を一つ入力したら、その都度 Return/Enter キーを押してください。結果が表示されるはずです。

+ +

まずは算術演算子の例を見てください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子名前
+加算6 + 9
-減算20 - 15
*乗算3 * 7
/除算10 / 5
+ +

また、 + 演算子は 2 つの文字を繋げて一つにするときにも使います。(プログラミングでは文字列を結合すると言います。) 下の例も試してみてください。

+ +
let name = 'ビンゴさん';
+name;
+let hello = 'が、こんにちは!と言っています。';
+hello;
+let greeting = name + hello;
+greeting;
+ +

累算代入演算子と呼ばれるもっと短い書き方もあります。すでにある文字列に、さらに文字を追加した結果を返したい場合などに使います。例えば、

+ +
name += 'が、こんにちは!と言っています。';
+ +

のように書いたとき、次と同じです:

+ +
name = name + 'が、こんにちは!と言っています。';
+ +

true/false テスト(例えば条件内 - {{anch("Conditionals", "below")}}参照)を実行しているとき、比較演算子を使用します。例えば:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子名前
===厳密に等しい (全く同じかどうか) +
+5 === 2 + 4 // false
+'Chris' === 'Bob' // false
+5 === 2 + 3 // true
+2 === '2' // false; number versus string
+
!==等しくない (違うかどうか) +
+5 !== 2 + 4 // true
+'Chris' !== 'Bob' // true
+5 !== 2 + 3 // false
+2 !== '2' // true; number versus string
+
<小なり +
+6 < 10 // true
+20 < 10 // false
+
>大なり +
+6 > 10 // false
+20 > 10  // true
+
+ +

条件式

+ +

先ほどの checkGuess() 関数に話を戻します。当然ですが、ただ単にプレースホルダメッセージを出したいわけではありませんよね。この関数にはプレイヤーの予想が正しいかどうかを調べて適切に返事をすることを望みます。

+ +

それでは、今の checkGuess() 関数を以下のように書き換えてみましょう。

+ +
function checkGuess() {
+  let userGuess = Number(guessField.value);
+  if (guessCount === 1) {
+    guesses.textContent = '前回の予想: ';
+  }
+  guesses.textContent += userGuess + ' ';
+
+  if (userGuess === randomNumber) {
+    lastResult.textContent = 'おめでとう! 正解です!';
+    lastResult.style.backgroundColor = 'green';
+    lowOrHi.textContent = '';
+    setGameOver();
+  } else if (guessCount === 10) {
+    lastResult.textContent = '!!!ゲームオーバー!!!';
+    setGameOver();
+  } else {
+    lastResult.textContent = '間違いです!';
+    lastResult.style.backgroundColor = 'red';
+    if(userGuess < randomNumber) {
+      lowOrHi.textContent='今の予想は小さすぎです!' ;
+    } else if(userGuess > randomNumber) {
+      lowOrHi.textContent = '今の予想は大きすぎです!';
+    }
+  }
+
+  guessCount++;
+  guessField.value = '';
+  guessField.focus();
+}
+ +

たくさん書きましたね!各部分に分割して、それぞれの部分を詳細に見て何をしているか説明しましょう。

+ + + +

イベント

+ +

ここまでで、checkGuess() 関数を上手に実装することができました。しかしまだ何も起きません。なぜなら、まだこの関数を呼び出していないからです。出来れば、"予想を入力"のボタンが押されたときに、この関数が呼ばれるようにしたいです。そのためにはイベントを使います。イベントとは、ボタンが押されたり、ページが読み込まれたり、ビデオを再生したりといったブラウザーで起きることで、それに反応してコードを実行させることができます。イベントが発生したことを聞き取る構成がイベントリスナーで、発生したイベントに反応して実行されるコードブロックがイベントハンドラーです。

+ +

checkGuess() 関数の下に、以下の一文を加えましょう。

+ +
guessSubmit.addEventListener('click', checkGuess);
+ +

guessSubmit ボタンに対して、イベントリスナーを追加しました。これは発生したことを知りたいイベントの種類 (この場合は click)と、イベントが発生した場合に実行するコード (この場合は checkGuess()) の 2 つの入力値 (引数と言います) を取る関数です。({{domxref("EventTarget.addEventListener", "addEventListener()")}}の中では括弧を書く必要はありません。)

+ +

保存して再度コードを読み直してください。今度はきっとある程度まで動くはずです。ただし、まだ問題があります。もし正解したり、予想回数の上限に達してしまった場合には、ゲームが止まってしまうでしょう。なぜなら、ゲームが終わった時に実行されるべき関数 setGameOver() をまだ定義していないためです。さあ、足りないコードを書いてチュートリアルの機能を完成させましょう。

+ +

ゲームの機能を完成させる

+ +

setGameOver() 関数をコードの一番下に追加して、中身を見てみましょう。これを JavaScript の一番下に追加します。

+ +
function setGameOver() {
+  guessField.disabled = true;
+  guessSubmit.disabled = true;
+  resetButton = document.createElement('button');
+  resetButton.textContent = '新しいゲームを始める';
+  document.body.appendChild(resetButton);
+  resetButton.addEventListener('click', resetGame);
+}
+ + + +

この関数も定義しなければなりませんね!もう一度、以下のコードを JavaScript のいちばん下に追加してください。

+ +
function resetGame() {
+  guessCount = 1;
+
+  const resetParas = document.querySelectorAll('.resultParas p');
+  for (let i = 0 ; i < resetParas.length ; i++) {
+    resetParas[i].textContent = '';
+  }
+
+  resetButton.parentNode.removeChild(resetButton);
+
+  guessField.disabled = false;
+  guessSubmit.disabled = false;
+  guessField.value = '';
+  guessField.focus();
+
+  lastResult.style.backgroundColor = 'white';
+
+  randomNumber = Math.floor(Math.random() * 100) + 1;
+}
+ +

ちょっと長めのこのコードブロックは、プレイヤーが次のゲームができるように、ゲームを起動したときの状態に完全にリセットします。

+ + + +

ここまでで (単純ではありますが) 動くゲームの完成です。お疲れ様でした!

+ +

この記事では、あと少し説明しなければならない大事な機能が残っています。既に見ているはずですが気づいたでしょうか。

+ +

ループ (繰り返し)

+ +

上のコードでもう少し詳しく説明しなければならないのは、for ループです。ループはプログラミングにおいてとても重要な概念です。ある条件に達するまで何度も何度もコードを繰り返し実行することができます。

+ +

ブラウザーの開発者ツールの JavaScript コンソール をもう一度開いて次のコードを入力してみましょう。

+ +
for (let i = 1 ; i < 21 ; i++) { console.log(i) }
+ +

どうでしょうか。1 から 20 の数字がコンソールに出力されましたね。これが繰り返しです。for ループには 3 つの入力値 (引数) が必要です。

+ +
    +
  1. 初期値: 上の例では、i を 1 からはじめましたが、どんな数字でもかまいません。さらに言えば、i という名前でなくともかまいません。ただし、ループでは短くて覚えやすいため、i という変数の名前がよく使われることを覚えておいてください。
  2. +
  3. 条件: 上の例では i < 21 をループが継続する条件としました。つまりループは i が 21未満でなくなるまで継続します。i が 21 になったらループの実行が終了します。
  4. +
  5. 増分: 上の例では増分を i++ と指定しています。つまり「i に 1 を足し」ます。ループは i が 21 になるまで(それは 2.の継続条件で説明しましたね) 、i の取りうる値について、それぞれ一度ずつ実行されます。今回の例では繰り返しのコードが実行される度に i の値を{{domxref("Console.log", "console.log()")}}を使用してコンソールに出力しています。
  6. +
+ +

さて、それでは数字当てゲームに登場したループを見てみましょう。resetGame() 関数に以下の記述がありますね。

+ +
const resetParas = document.querySelectorAll('.resultParas p');
+for (let i = 0 ; i < resetParas.length ; i++) {
+  resetParas[i].textContent = '';
+}
+ +

このコードは <div class="resultParas"> に含まれるすべての {{htmlelement("p")}} 要素を {{domxref("Document.querySelectorAll", "querySelectorAll()")}} というメソッドを使用して取得しています。そしてループを使用してその一つ一つの要素の中身を消去しています。

+ +

オブジェクトについて(簡単に)

+ +

オブジェクトについて説明する前に、プログラムに対して最後のちょっとした改良を加えてみましょう。JavaScript の書き出しの方にある let resetButton; のすぐ下に、以下の行を追記してファイルを保存します。

+ +
guessField.focus();
+ +

この行はページが読み込まれるとすぐ、 {{domxref("HTMLElement.focus", "focus()")}} メソッドを呼び出して、入力フォームの {{htmlelement("input")}} 要素に対して自動的にカーソル (フォーカス) を設定しています。つまり、ページが開いたと同時に、入力フォームを最初にクリックすることなくプレイヤーが予想を入力できるようにしているのです。本当にちょっとしたことですが、ユーザーにゲームで遊ぶためには何をすればよいかの視覚的なヒントを教えてあげることで、使い勝手が向上します。

+ +

もう少し詳細に何が起こっているのか分析しましょう。JavaScript では、すべてのものはオブジェクトです。オブジェクトというのは 1 か所に関連する機能をまとめたものです。自分でオブジェクトを作ることもできますが、高度なことなので、このコースの大分後まで出てきません。今は簡単に、これを使うと多くの便利なことができるようになる、ブラウザーに含まれる組み込みオブジェクトについて説明します。

+ +

この具体的なケースでは、HTML のテキスト入力フィールドを参照するために、最初に guessField 変数を作成しました。以下の行は最上部のあたりの変数定義で見つかります、

+ +
const guessField = document.querySelector('.guessField');
+ +

この参照を得るため、{{domxref("document")}} オブジェクトの{{domxref("document.querySelector", "querySelector()")}} メソッドを使用しています。querySelector() はある情報 (必要な要素を選択する CSS セレクタ) を受け取ります。

+ +

guessField に {{htmlelement("input")}} 要素の参照が得られたので、これでたくさんのプロパティ (基本的にはオブジェクトの内部に保持されている変数のことですが、中には値を変えられないものもあります) とメソッド (基本的にはオブジェクトの内部に保持されている関数のこと) にアクセスできるようになりました。ようやく {{htmlelement("input")}} 要素のメソッドの一つである focus() メソッドを使ってテキストフィールドにフォーカスを当てられます。

+ +
guessField.focus();
+ +

入力フォームの要素の参照を含まない変数に対しては、focus() は使用できません。例えば、guesses 変数には {{htmlelement("p")}} 要素への参照が入っていますし、guessCount には数値が入っています。

+ +

ブラウザーのオブジェクトで遊ぼう

+ +

少しブラウザーが持っているオブジェクトで遊んでみましょう。

+ +
    +
  1. まずブラウザーでプログラムを開いてください
  2. +
  3. 次に開発者ツールを開き、JavaScript コンソールのタブが開いたのを確認します
  4. +
  5. guessField と入力してみてください。するとコンソールに {{htmlelement("input")}} 要素を含む変数が表示されます。また、気づいたと思いますが、コンソールは実行中の環境にある変数名を含んだオブジェクト名を自動的に補完しました!
  6. +
  7. さらに下のように入力してみてください +
    guessField.value = 'Hello';
    + value プロパティは今のテキストフィールドに入力された値を表しています。コマンドを入力したら、テキストフィールドの値が変わりましたね!
  8. +
  9. さらに続けて guesses と入力して  Return/Enter を押します。{{htmlelement("p")}} 要素を含む変数がコンソールに表示されますね。
  10. +
  11. そして次のコードを入力します +
    guesses.value
    + コンソールには  undefined (未定義) という文字が返ってきましたね。value というプロパティは {{htmlelement("p")}} 要素にはないためです。
  12. +
  13. パラグラフ内のテキストを変えたい場合には、{{domxref("Node.textContent", "textContent")}} プロパティを使用する必要があります。こうしてみます +
    guesses.textContent = 'Where is my paragraph?';
    +
  14. +
  15. ちょっと遊んでみましょう。下のコードをひとつづつ入力してみてください。 +
    guesses.style.backgroundColor = 'yellow';
    +guesses.style.fontSize = '200%';
    +guesses.style.padding = '10px';
    +guesses.style.boxShadow = '3px 3px 6px black';
    + ページ内に存在するすべての要素は style プロパティを持っていて、そのオブジェクトを介して CSS のインラインスタイルで要素に適用されるすべてのプロパティにアクセスすることができます。これを使うことで、JavaScript から動的に要素の CSS のスタイルを設定できるのです。
  16. +
+ +

ここで一息...

+ +

これで数字当てゲームができました。最後までついて来れましたね!作ったプログラムを動かしてみてください 。(最後のプログラムはこちらでも遊べます。) もし作ったプログラムが動かなければ、ソースコードと見比べてみてください。

+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/first_steps/arrays/index.html b/files/ja/learn/javascript/first_steps/arrays/index.html new file mode 100644 index 0000000000..973a8511fa --- /dev/null +++ b/files/ja/learn/javascript/first_steps/arrays/index.html @@ -0,0 +1,568 @@ +--- +title: 配列 +slug: Learn/JavaScript/First_steps/Arrays +tags: + - CodingScripting + - JavaScript + - Join + - Pop + - Push + - 'l10n:priority' + - shift + - split + - unshift + - 初心者 + - 学習 + - 記事 + - 配列 +translation_of: Learn/JavaScript/First_steps/Arrays +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}
+ +

このモジュールの最後に、配列について見ていきましょう。配列は 1 つの変数名でリスト形式のデータを保持するのに好都合です。ここでは、どう便利なのか、どのように作るのか、そして配列の項目を追加したり削除したり取得したりする方法について学びます。

+ + + + + + + + + + + + +
前提条件:基礎的なコンピューターの知識、HTML と CSS への基本的な理解、JavaScript についての理解。
目的:JavaScript において、配列とは何か、どのように操作するのかを理解する。
+ +

配列とは何?

+ +

配列はたいてい「リストのようなオブジェクトである」と説明され、単一のオブジェクト内に複数の値をリストとして持っています。配列オブジェクトは変数に格納され、その他の型と同様に扱われます。異なるのはリスト内の値に個別にアクセスすることができ、繰り返しを用いて全ての値に同じことをするといった、リストとして便利で効率的に扱うことができます。商品とその価格の一覧を配列に保持し、その値をループして合計額を計算しつつ請求書にそれぞれの価格を表示して一番下に合計額を表示することもできるでしょう。

+ +

もし配列がなかったとしたら、別々の変数にそれぞれの値を格納しなければならず、各変数を表示するのと計算するので別々に呼び出さなければならなかったでしょう。こうなると、書き出すのがとても長く、非効率的でエラーを起こしやすいプログラムとなるでしょう。例えば、10 個の項目を請求書に出すだけでも最悪ですが、それが 100 個や 1000 個だったらどうでしょう。この記事の最後に実例としてやってみましょう。

+ +

前回までの記事と同様に、JavaScript コンソールに配列の基礎となるコード例をブラウザーの開発者コンソールに入力しながら学びましょう。

+ +

配列を作る

+ +

配列を作るには、角括弧の中にカンマで区切ったリストの形式で項目を並べます。

+ +
    +
  1. 買い物リストを配列に保持したいとき、次のようにします。下のコードをコンソールに入力してみましょう。 +
    let shopping = ['パン', '牛乳', 'チーズ', 'ハム', '麺'];
    +shopping;
    +
  2. +
  3. この例では、配列の各項目は文字列ですが、配列には何でも格納することができることを頭に入れておきましょう。文字列、数値、オブジェクト、その他の変数、さらには別の配列ですら格納することができます。そして混ぜ合わせることも。すべて同じデータ型である必要はありません。 +
    let sequence = [1, 1, 2, 3, 5, 8, 13];
    +let random = ['tree', 795, [0, 1, 2]];
    +
  4. +
  5. いくつか配列を作ってみましょう。それから先に進みます。
  6. +
+ +

配列の項目を取得し変更する

+ +

配列の各項目は文字列中の文字を取得したときのように列で角括弧 ([]) を使用して取得することができます。

+ +
    +
  1. 次のコードをコンソールに入力してください。 +
    shopping[0];
    +// "パン"という値が戻ります
    +
  2. +
  3. そして、配列中の項目は単に新しい値を代入することで変更することが出来ます。 +
    shopping[0] = 'タヒーニ';
    +shopping;
    +// ショッピングリストは[ "タヒーニ", "牛乳", "チーズ", "ハム", "麺" ]に変更されています。
    + +
    : 前にも言いましたが、重要なことなのでもう一度言います。コンピューターは 0 から数を数えます!
    +
  4. +
  5. 配列の中に配列があるとき、その配列は多次元配列と呼ばれます。配列中の配列に含まれる項目には角括弧を繋げて書くことでアクセスすることができます。例えば、先ほどの例で出てきた random 変数に格納された配列の 3番目の項目のさらに 3番目の項目を取得するには以下のようにします。 +
    random[2][2];
    +
  6. +
  7. 移動する前に、配列の例をいくつか変更してみてください。遊んでみて、何が動いて何がそうでないかを見てください
  8. +
+ +

配列の長さを調べる

+ +

ある配列の長さ (いくつの項目が配列中に存在するか) を知るには、文字列の (文字の) 長さを調べた時と全く同じようにします。{{jsxref("Array.prototype.length","length")}}プロパティを使用して長さを取得することができます。

+ +
sequence.length;
+// 7 が返る
+ +

このプロパティはいろいろな使われ方をするのですが、最もよく使われるのは、配列中の全項目をループするために使用されます。次の例を見てください。

+ +
let sequence = [1, 1, 2, 3, 5, 8, 13];
+for (let i = 0; i < sequence.length; i++) {
+  console.log(sequence[i]);
+}
+ +

ループについてはそのうち (Looping code の記事で) しっかりと学ぶ機会があるでしょうが、ここで簡単に説明すると上のコードは次のように動きます。

+ +
    +
  1. 配列中の項目 0 番よりループを開始します。
  2. +
  3. 項目番号が配列の長さと同じ数になったら、繰り返しを終了します。これで配列中の要素がいくつであっても動くようになります。今回の場合は、項目の番号が 7 のときに終了します(ループでカバーしたい最後の項目番号は 6 なので、これで問題ありません)。
  4. +
  5. そして、各項目を console.log() メソッドを使用してブラウザーのコンソールに出力しています。
  6. +
+ +

便利な配列メソッド

+ +

このセクションでは、文字列を配列にしたり、配列を文字列にしたり、配列に項目を追加したり、ちょっと便利な配列関連のメソッドを見てみましょう。

+ +

文字列と配列を相互に変換する

+ +

データが長い長い文字列の中に含まれていて、それを使いやすい形に分割して操作したいときがあります。例えばデータを表形式で表示するというようなときです。それには{{jsxref("String.prototype.split()","split()")}} メソッドが使用できます。このメソッドは文字列を分割するのに使用する文字を引数として取り、文字列をその文字で区切った部分文字列の配列に分割します。

+ +
+

: 実際のところ、これは配列ではなく文字列のメソッドです。しかし、ここで紹介するのが一番だと思い取り上げています。

+
+ +
    +
  1. それではどのように動くか試してみましょう。まずは文字列をコンソールに作ります。 +
    let myData = '札幌,仙台,東京,名古屋,大阪,博多';
    +
  2. +
  3. この文字列をカンマで区切ります。 +
    let myArray = myData.split(',');
    +myArray;
    +
  4. +
  5. そして、できた配列の長さを確認して、その中身を見てみましょう。 +
    myArray.length;
    +myArray[0]; // 配列の最初の項目
    +myArray[1]; // 配列の二番目の項目
    +myArray[myArray.length-1]; // 配列の最後の項目
    +
  6. +
  7. {{jsxref("Array.prototype.join()","join()")}} メソッドを使うことで、逆のことができます。 +
    let myNewString = myArray.join(',');
    +myNewString;
    +
  8. +
  9. 配列を文字列にするもう一つの方法は、{{jsxref("Array.prototype.toString()","toString()")}} メソッドを使うことです。引数を取らない toString()join() と比べ簡単でしょうが、制限があります。join() を使えば、他の区切り文字を指定することもできます (4. の例をカンマ以外の他の文字を指定して試してください)。 +
    let dogNames = ['ポチ','ハチ','タロウ','モコ'];
    +dogNames.toString(); //ポチ,ハチ,タロウ,モコ
    +
  10. +
+ +

項目の追加と削除

+ +

まだ配列への項目の追加と削除をやっていませんでしたね。次はこれをやりましょう。先ほどの例にあった myArray 配列を使用します。先ほどの例をまだ実行していなければ、以下のコードをコンソールに入力して配列を作ってください。

+ +
let myArray = ['札幌', '仙台', '東京', '名古屋', '大阪', '博多'];
+ +

まず、配列の最後に項目を追加したり、最後の項目を削除するには、それぞれ {{jsxref("Array.prototype.push()","push()")}} と {{jsxref("Array.prototype.pop()","pop()")}} を使います。

+ +
    +
  1. 先に push() を使ってみます。配列の最後に項目を追加するには 1 つ以上の項目を引数に指定します。 + +
    myArray.push('横浜');
    +myArray;
    +myArray.push('神戸', '広島');
    +myArray;
    +
    +
  2. +
  3. メソッドの呼び出しが終わると、新しい配列の長さが返ります。もし新しい配列の長さを変数に格納したければ、次のようにできます。 +
    let newLength = myArray.push('京都');
    +myArray;
    +newLength;
    +
  4. +
  5. 配列の最後の要素を削除するには pop() を呼び出すだけです。 +
    myArray.pop();
    +
  6. +
  7. メソッドの呼び出しが終わると、削除された項目それ自体が返ります。 +
    let removedItem = myArray.pop();
    +myArray;
    +removedItem;
    +
  8. +
+ +

{{jsxref("Array.prototype.unshift()","unshift()")}} と {{jsxref("Array.prototype.shift()","shift()")}} はそれぞれ push()pop() と同様の動作ですが、配列の末尾ではなく先頭において動作します。

+ +
    +
  1. まずは、unshift() を次のように実行します。 + +
    myArray.unshift('奈良');
    +myArray;
    +
  2. +
  3. 今度は shift() でやってみましょう! +
    let removedItem = myArray.shift();
    +myArray;
    +removedItem;
    +
  4. +
+ +

アクティブラーニング: 商品を印字しよう!

+ +

商品の名前と価格、合計金額を請求書に印字するという最初の話に戻りましょう。以下に示す編集可能なコードのコメントの中に数字が書かれています。この数字はコードを書くべき場所を示しています。各数字の場所に次のようなコードを書いてください。

+ +
    +
  1. // No.1 というコメントの下に、商品の名前と価格をコロン (:) で繋げた、いくつか文字列が並んでいます。これを products という名前の配列にしてください。
  2. +
  3. // No.2 というコメントの行から for ループが始まっています。この行には i <= 0 と書かれています。「i の値が 0 以下でなくなれば終了」と書かれており、i は 0 から始まるので、この for ループは一度しか実行されません。この条件を iproducts 配列の長さより小さくなくなった場合に終了するような条件に置き換えて下さい。
  4. +
  5. // No.3 のコメントの直下に 1 行で、現在の配列の項目 (name:price) を 2 つに分割するコードを書いてください。一方は商品の名前、もう一方は価格です。もしどうすればいいのかわからなければ、便利な文字列のメソッドの記事を参照してください。さらに{{anch("Converting between strings and arrays","文字列と配列を相互に変換する")}}も役に立つでしょう。
  6. +
  7. 上記のコードの一部として、価格を文字列から数値に変換する必要もあるでしょう。どのようにすべきか思い出せなければ、文字列の最初の記事を確認してみましょう。
  8. +
  9. コードの先頭に total という名前の変数が宣言されて、0 で初期化されています。ループの中で (// No.4下) 繰り返している現在の項目の価格を total 変数に加算するコードを一行で書いてください。そうすれば、コードの最後で正しい合計が請求書に印字されます。恐らく代入演算子が役に立つでしょう。
  10. +
  11. // No.5 のコメントの直下のコードを itemText 変数が「現在の項目の商品名 — $現在の項目の価格」となるように変更してください。「靴 — $23.99」という感じです。そうすれば正しい情報が請求書に印字されます。これはもう慣れたはずの単純な文字列結合で実現できます。
  12. +
+ + + +

{{ EmbedLiveSample('Playable_code', '100%', 730, "", "", "hide-codepen-jsfiddle") }}

+ +

アクティブラーニング: 上位5件の検索

+ +

{{jsxref("Array.prototype.push()","push()")}} や{{jsxref("Array.prototype.pop()","pop()")}} といったメソッドを使用するよい例は、ウェブアプリでデータの中で有効な項目だけを抜き出して維持したいときなどです。例えば、アニメーションのあるシーンで、現在表示中の背景イメージを保持している配列があり、一度に表示するイメージをパフォーマンスなどの理由で 50 に制限したいとします。その際、新しいオブジェクトを配列に追加したと同時に、古いオブジェクトを削除して配列を希望のサイズに維持します。

+ +

次の例では、もう少し単純に、検索ボックスのある、ダミーの検索サイトを用意しました。検索ボックスに文字が入力されたら、直前 5 つの検索語がリストに表示されます。検索された語が 5 を超えたら最後の検索語が削除されるようになります。新しい検索語が先頭に追加されるので、常に 5 つの検索語が表示されます。

+ +
+

: 本当の検索アプリでは、前回の検索語をクリックすることでその検索に戻れて、実際に検索結果が表示されることでしょう!ただし、今は単純にしておきましょう。

+
+ +

アプリを完成させるには...

+ +
    +
  1. // No.1 コメントの下に、検索ボックスに入力された検索語を配列の先頭に追加するコードを書いてください。検索語は searchInput.value と書いて取得します。
  2. +
  3. // No.2 コメントの下に、配列の最後の項目を削除するコードを書いてください。
  4. +
+ + + +

{{ EmbedLiveSample('Playable_code_2', '100%', 700, "", "", "hide-codepen-jsfiddle") }}

+ +

スキルをテストしよう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?移動する前に、情報を維持しているか検証するテストを見ることができます — Test your skills: Arrays を見てください。

+ +

結論

+ +

この記事を読んで、配列がとても使えるものであることがお分かりいただけたのではないでしょうか。配列は JavaScript の至るところで見かけます。特に配列の各項目に対して同じことをする際にループと一緒に使われます。便利なループの基本については次のモジュールで教えますが、今は自分自身を褒めて、十分に休みましょう!このモジュールのすべての記事をやり終えました!

+ +

ただし、次のモジュールの前に、理解度を確認するため、このモジュールの課題をやりましょう。残っているのはそれだけです。

+ +

関連情報

+ + + +

{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/first_steps/index.html b/files/ja/learn/javascript/first_steps/index.html new file mode 100644 index 0000000000..13cb953a6c --- /dev/null +++ b/files/ja/learn/javascript/first_steps/index.html @@ -0,0 +1,84 @@ +--- +title: JavaScript の第一歩 +slug: Learn/JavaScript/First_steps +tags: + - Arrays + - Article + - Assessment + - Beginner + - CodingScripting + - Guide + - JavaScript + - Landing + - Module + - Numbers + - Operators + - Variables + - 'l10n:priority' + - maths + - strings +translation_of: Learn/JavaScript/First_steps +--- +
{{LearnSidebar}}
+ +

最初の JavaScript のモジュールでは、初めて JavaScript を書く実践的な経験を体験する前に、「JavaScript とは何?」や「どのようなもの?」や「何ができる?」といったような基本的な質問に答えます。その後変数や文字列、 数値、配列といったような言語の内容をお話します。

+ +
+

フロントエンドのWeb開発者になりたいですか?

+ +

私たちはあなたがあなたの目標に向かって取り組むために必要なすべての重要な情報を含むコースをまとめました。

+ +

始めましょう

+
+ +

前提条件

+ +

このモジュールを始めるには JavaScript の知識は必要ありませんが、HTML や CSS に少し慣れている必要があります。JavaScript の学習を開始する前に以下のモジュールを学習することをお勧めします :

+ + + +
+

注記 : もしあなたが作業しているコンピューター・タブレットやその他のデバイスで自分でファイルを作れない場合は、JSBinGlitch といったようなオンラインコーディングプログラムで (ほとんどの場合) 試すことができます。

+
+ +

ガイド

+ +
+
JavaScript って何?
+
MDN の初心者向け JavaScript コースへようこそ!この最初の記事では JavaScript を高い視点から見ていき、「それは何ですか?」「それで何ができますか?」などの質問に答え、JavaScript の目的があなたに受け入れられるものであるかを確認します。
+
最初のダイブ
+
JavaScript の理論についていくつか学びましたが、それで何ができるのでしょう?完全に実践的なチュートリアルを通して、JavaScript の基本機能の短期集中コースを提供します。 ここでは、簡単な数字当てゲームを段階的に作っていきます。
+
何が間違っている?JavaScript のトラブルシューティング
+
前の記事で数字当てゲームを構築した時に、うまく動かなかったかもしれません。心配しないでください —この記事は、JavaScript のプログラムにエラーを見つけて修正するシンプルな方法を提供することで、こうした大変な事態からあなたを手助けすることを目的としています。
+
必要な情報を保存する — 変数
+
前の 2 つの記事を読んで、JavaScript が何であるか、あなたのために何ができるか、他のウェブテクノロジーと一緒に使う方法、そして高い視点から見た主な機能を知ったことでしょう。この記事では実際の基礎に着目し、JavaScript の最も基本的な構成要素を扱う方法を見ていきます ― それが変数です。
+
JavaScript の簡単な数学 — 数値と算術演算子
+
ここで、JavaScript における数学について論じます。指示に従ってうまく数値を操作するために、演算子やその他の機能を組み合わる方法を説明します。
+
テキストを扱う — JavaScript での文字列
+
次に、文字列に注目します ― プログラミングではテキストのことをこう呼びます。この記事では、文字列の作成、文字列の引用符のエスケープ、およびそれらの結合など、JavaScript を学習するにあたって本当に知っておくべき、文字列についてのすべての一般的な事柄を見ていきます。
+
便利な文字列メソッド
+
文字列の基本について見てきましたが、文字列の長さの取得、文字列の結合と分割、文字列内の文字の置換、その他の文字列の置換など、組込みメソッドを使用して文字列に対して実行できる便利な操作について考えてみましょう。
+
配列
+
このモジュールの最後の記事では、配列を見ていきます — 単一の変数名の下に複数のデータ項目のリストを保存するのに適した方法です。ここでは、なぜこれが便利なのかを確認してから、配列の作成方法、配列に格納された項目の取り出し、追加、削除などの方法を学びます。
+
+ +

課題

+ +

以下の成績評価では、上のガイドで取り上げた JavaScript の基礎についての理解をテストします。

+ +
+
バカ話ジェネレーター
+
この課題では、このモジュールの記事で取り上げた知識の一部を用いて、ランダムなバカ話を生成する愉快なアプリの作成に適用することを求められます。楽しんで取り組みましょう!
+
+ +

関連情報

+ +
+
Learn JavaScript
+
短いレッスンとインタラクティブなテストを使用して、自動化された評価に基づいた、インタラクティブな環境でJavaScriptを学びます。
+ 最初の40レッスンは無料で、コース全体を少額の1回払いで利用できます。
+
diff --git a/files/ja/learn/javascript/first_steps/math/index.html b/files/ja/learn/javascript/first_steps/math/index.html new file mode 100644 index 0000000000..bbdb6550b7 --- /dev/null +++ b/files/ja/learn/javascript/first_steps/math/index.html @@ -0,0 +1,469 @@ +--- +title: JavaScriptでの基本演算 — 数値と演算子 +slug: Learn/JavaScript/First_steps/Math +tags: + - Article + - Beginner + - CodingScripting + - Guide + - JavaScript + - Learn + - Math + - Operators + - augmented + - increment + - 'l10n:priority' + - maths + - modulo +translation_of: Learn/JavaScript/First_steps/Math +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}
+ +

今回は JavaScript での数学的処理についてです。我々の命令を実行するために上手く数値を操作するのにどのように {{Glossary("Operator","演算子")}} や、その他の機能を使用できるのかを見ていきましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターの知識、HTML と CSS の基本についての理解、JavaScript が何かが分かっていること。
目的:JavaScript での基礎的な数値処理に慣れる。
+ +

みんな数学が大好き

+ +

まあ、みんなではないですね。好きな人もいれば、九九や長い数字の割り算が出てきてから嫌いになってしまった人もいるでしょう。どちらでもない人も。けれど、数学が生活に必要なものであるということは、否定することは出来ません。特に JavaScript のプログラミングを学習しているのなら、なおさらです。数値データを処理したり、計算をしたりすることが多いので、JavaScript に数学的な関数が十分にそろっていることは、驚くことではありません。

+ +

この記事ではまず知っておくべき基礎的なものに絞って見ていきます。

+ +

数値の種類

+ +

プログラミングをしていると、慣れ親しんだ普通の数値ですら難しいと思えるかもしれません。数値と言ってもいくつか種類があり、それぞれ名前を付けて区別しています。

+ + + +

さらに通常とは異なる数値表現も使います!今まで出てきた数値は 10 を基数 (0 ~ 9 を 1 つの桁として扱う) とした十進数でしたが、他にも以下のようなものがあります。

+ + + +

脳みそが溶けそうだと思う前に、少し待ってください!まず、この講座では十進数しか扱いません。それに「もしかすれば」ですが、他の数値表現について考える機会は訪れないということだってあり得ます。

+ +

さらにちょっといいことを教えましょう。いくつかの他のプログラミング言語とは違い、JavaScript には数値(整数と少数の両方)を表すデータ型が一つしかありません。わかりますか?{{jsxref("Number","Number (数値)")}} で、これは整数と小数の両方です。これはJavaScript でどんな型の数値を扱おうとも、それらを全く同じように扱うことが可能だということを意味します。

+ +
+

: 実際に、JavaScript には 2 つ目の数値型である{{Glossary("BigInt")}} があり、これはとても大きな整数に使います。しかしこのコースの目的としては、Number の値だけに関心を持つことにします。

+
+ +

すべてが「Number」に見えるよね

+ +

書き方の復習を兼ねてちょっと数字で遊んでみましょう。以下に示すコマンドを開発者ツールの JavaScript コンソール入力してみましょう。もちろんこのページに埋め込みのコンソールを使っても構いません。

+ +
    +
  1. まず、変数を 2 つ宣言して、それぞれ整数と浮動小数点数で初期化してみましょう。そして、変数の名前を入力して、期待通りに値が入っていることを確認してみましょう。 +
    var myInt = 5;
    +var myFloat = 6.667;
    +myInt;
    +myFloat;
    +
  2. +
  3. 数値にはクォーテーションマークが不要です。次に進む前にもう少し変数の宣言と初期化をしてみてください。
  4. +
  5. さて、それでは上で入力した 2 つの変数が同じデータ型であるか確認してみましょう。JavaScript では、{{jsxref("Operators/typeof", "typeof")}} という演算子を使用することで、データ型を確認することができます。次の 2 行を入力してみましょう。 +
    typeof myInt;
    +typeof myFloat;
    + どちらの変数についても "number" という文字が戻ってきましたね。もし、別々の数値型が存在しているとすれば、別々に処理しなければならないので、そう考えるととても簡単に思えますよね!
  6. +
+ +

便利な Number メソッド

+ +

Number オブジェクトは、あなたが JavaScript を使う時すべての基本的な数値を表現するインスタンスですが、その中には、数値を操作するための沢山の便利なメソッドがあります。この記事では、簡単な紹介と基本的な要点だけまとめたいので、詳しくは割愛しますが、この段落を何回か読んだら、オブジェクト参照ページに行って、どんなメソッドが使えるのかを勉強するのが良いと思います。

+ +

例えば、数値を固定の桁数に丸めるには toFixed() メソッドを使用します。ブラウザのコンソールに次の行を入力します。

+ +
let lotsOfDecimal = 1.766584958675746364;
+lotsOfDecimal;
+let twoDecimalPlaces = lotsOfDecimal.toFixed(2);
+twoDecimalPlaces;
+ +

数値データ型への変換

+ +

たまに、文字列型として格納されている数字で計算ができなくなってしまうことがあります。これは、データがフォーム入力に入力され、input タイプが text である場合によく起こります。この問題を解決する方法があります - 文字列の値を Number() コンストラクタに渡して、同じ値の数値バージョンを返します。

+ +

例えば、これらの命令をコンソールに入力してみてください。

+ +
let myNumber = '74';
+myNumber + 3;
+ +

答えは 743 です。77 ではありません。 なぜなら myNumber は string として定義されているからです。以下の命令で確認することができます。

+ +
typeof myNumber;
+ +

これは以下のようにして修正することができます。

+ +
Number(myNumber) + 3;
+ +

算術演算子

+ +

算術演算子は JavaScript で計算をするのに使用する最も基本的な演算子です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子名前目的
+加算左項と右項を足す。6 + 9
-減算左項より右項の数を引く。20 - 15
*乗算左項と右項を掛ける。3 * 7
/除算左項の数値を右項で割る。10 / 5
%剰余 (モジューロともいう)   +

左項を右項で割った余りを求める。

+
8% 3 (8 を 3 で割ったとき、商 2 余り 2 の 2 ですね)
**指数 +

基数指数の累乗にします。つまり、指数の回数だけ基数の数自身を乗算します。EcmaScript 2016 で最初に導入されました。

+
5 ** 2 ( 25 を返します。その値は 5 * 5 と同じですね)
+ +
+

メモ: 演算子 (オペレーター) に必要とされる数のことを{{Glossary("Operand", "オペランド")}}と呼ぶことがあります。

+
+ +
+

メモ: 指数が古い {{jsxref("Math.pow()")}} メソッドを使って表現されているのを見ることがあるかもしれませんが、それはとてもよく似た働きをします。たとえば、Math.pow(7, 3)では、7 が基底で 3 が指数であるため、式の結果は 343 になります。Math.pow(7, 3)7**3 と同じです。

+
+ +

たぶん基本的な数学を教える必要はないでしょうが、ここに出てくる文法を理解しているかをテストしたいと思います。書き方を覚えるため、以下に示す例を開発者ツールの JavaScript コンソールに入力してみましょう。

+ +
    +
  1. まずは次のような簡単な例を自分で試してみてください。 +
    10 + 7
    +9 * 8
    +60 % 3
    +
  2. +
  3. そして、変数を宣言して初期化し、数を変数に格納します。それから変数を使って計算してみましょう。変数は計算するにあたり、保持している値がそこにあるかのように使えます。例えば次の通り。 +
    let num1 = 10;
    +let num2 = 50;
    +9 * num1;
    +num1 ** 3;
    +num2 / num1;
    +
  4. +
  5. それではさらに難しい計算式を入力してみましょう。 +
    5 + 10 * 3;
    +num2 % 9 * num1;
    +num2 + num1 / 8 + 2;
    +
  6. +
+ +

最後の例の中に予想した結果と違う答えがありませんでしたか。次の章でなぜそうなったかを説明してみましょう。

+ +

演算子の優先順位

+ +

先ほどの計算式の一番最後の例を見てみましょう。num2 に 50、num1 に 10 が格納されているものとします。(最初はそうでしたよね。)

+ +
num2 + num1 / 8 + 2;
+ +

ある人は、先に「50 + 10 = 60」と「8 + 2 = 10」を先に計算して、その後で「60 ÷ 10 = 6」となるように計算するかもしれません。

+ +

けれどもブラウザは「10 ÷ 8 = 1.25」を先に計算してから「50 + 1.25 + 2 = 53.25」を計算します。

+ +

どうしてこうなるのかといえば、演算子には優先順位があるからです。ある演算子は (プログラムのによっては) 他の演算子よりも先に実行されます。JavaScript の演算子の優先順位は算数の授業で教わったものと同じです。つまり、乗算と除算は常に最初に行われ、それから加算と減算が実行されます(通常の計算は常に左から右に評価されます)。

+ +

もし、演算子の優先順位を変更したいならば、先に実行したい部分を括弧 (()) を使って囲みます。もし先ほどの例で 6 が答えになるようにしたいなら次のようにします。

+ +
(num2 + num1) / (8 + 2);
+ +

実際に実行し、結果を見てみてください。

+ +
+

メモ: JavaScript の演算子とその優先順位については式と演算子で確認することができます。

+
+ +

インクリメント演算子とデクリメント演算子

+ +

たまに、繰り返し値を足したり引いたりしたいときがあるでしょう。そんなときに便利なのがインクリメント演算子 (++) とデクリメント演算子 (--) です。もう既に、JavaScript への最初のダイブに出てくる「数字当てゲーム」で、ユーザーの残り予想回数を求めるために使用する guessCount 変数に 1 を加えるのに ++ を使用しましたね。

+ +
guessCount++;
+ +
+

メモ: これらの演算子は、このコースの後で学ぶ繰り返し処理でよく使われます。例えば、価格の一覧があって、それに対して掛かる税金を各要素に足していきたいとします。恐らく繰り返し処理を使用して、それぞれの価格に対して必要な計算をすることになるでしょう。そのときに、次の値に移動するためインクリメント演算子を使用します。どのように行うかを説明する簡単な例をご用意しました。— インクリメント演算子に興味を持ったらライブで実行、およびソースコードの閲覧をしてみてください。繰り返しについては、このコースの後で詳細を見てみます。

+
+ +

それでは、コンソールで試してみましょう。ただし、その前に注意点です。この演算子は数値には直接使用できません。変に思えるかもしれませんが、これは対象の値そのものに作用するわけではなく、変数に対して新しい値を代入するのです。次の例はエラーになります。

+ +
3++;
+ +

既に存在する値に対してのみインクリメントすることができます。

+ +
let num1 = 4;
+num1++;
+ +

また変なことが起きましたね!上のコードを実行したとき「4」がコンソールに表示されました。これはブラウザが現在の値を先に返して、その後にインクリメントを実行したためです。もう一度変数を入力してみると、変数がインクリメントされていることがわかります。

+ +
num1;
+ +

それは -- 演算子についても同様です。以下のコードも試してみてください。

+ +
var num2 = 6;
+num2--;
+num2;
+ +
+

メモ: 変数の前に演算子を置くことで、ブラウザにインクリメントまたはデクリメントを先にさせてから値を戻すようにすることもできます。上記の例に戻って今度は ++num1 や --num2 のように入力してみてください。

+
+ +

代入演算子

+ +

代入演算子は変数に値を代入します。すでに一番基本的な = 演算子を何度も使用しています。この演算子は単に左辺に記述された値を右辺に代入します。

+ +
let x = 3; // x には 3 が入る
+let y = 4; // y には 4 が入る
+x = y; // x には y と同じ値:4 が入る
+ +

ただし、コードを簡潔に効率よく書くための、もっと複雑な方法が用意されています。よく見かけるものを以下に示します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子名前目的同様のコード
+=加算代入右辺の値を左辺の変数値に加算してから、新しい値を返しますx += 4;x = x + 4;
-=減算代入右辺の値を左辺の変数値より減算してから、新しい値を返しますx -= 3;x = x - 3;
*=乗算代入左辺の変数値に右辺の値を乗算してから、新しい値を返しますx *= 3;x = x * 3;
/=除算代入左辺の変数値を右辺の値で除算してから、新しい値を返しますx /= 5;x = x / 5;
+ +

どのように動いているか理解するため、コンソールに上記の例をいくつか入力してみましょう。どの例も、2 行目を入力する前にコードがどのようになるかを予想してから入力しましょう。

+ +

ちなみに、どの演算子も右辺には自由に変数を置くことができます。例えば以下のように。

+ +
let x = 3; // x には 3 が入る
+let y = 4; // y には 4 が入る
+x *= y; // x は 12 になる
+ +
+

メモ: もっとたくさんの代入演算子がありますが、とりあえず今は基本的なものだけ知っておけばよいでしょう。

+
+ +

アクティブラーニング: Canvas のボックスのサイズを変更する

+ +

練習として、数値と演算子を使用してボックスのサイズを変更してみましょう。ブラウザの {{domxref("Canvas API", "", "", "true")}} を使用してボックスを描きます。どうやって描くかについて気にする必要はありません。今は計算に集中しましょう。ボックスの幅と高さ (ピクセル単位で) 変数 xy で宣言しています。最初は 50 になっています。

+ +

{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 620)}}

+ +

新しいウィンドウで開く

+ +

上の編集可能なコードには、変更すべき 2 つの行にコメントが書かれています。その行を適切な演算子および値を用いて変更し、拡大縮小させてください。それではやってみましょう。

+ + + +

コードを完全に壊してしまっても大丈夫です。いつでもリセットボタンを押すことで何度でも最初から実行できます。上の問題に全問正解したら、もう少し遊んでみてもいいですし、自分で問題を作ってみてもいいですね。

+ +

比較演算子

+ +

ときには、true または false を判定し、その結果により動作を変更したいと思う時があるでしょう。そのようなことをするために比較演算子を使用します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子名前目的
===厳密な等価右辺と左辺が厳密に同一の値であるかを判定します5 === 2 + 4
!==厳密な不等右辺と左辺が厳密に同一の値ではないことを判定します5 !== 2 + 3
<小なり左辺の値が右辺の値より小さいこととを判定します10 < 6
>大なり左辺の値が右辺の値より大きいことを判定します10 > 20
<=以下なり左辺の値が右辺の値以下であることを判定します3 <= 2
>=以上なり左辺の値が右辺の値以上であることを判定します5 >= 4
+ +
+

メモ: もしかしたら == や != といった演算子を同値かどうかの判定に使用する人を見かけることがあるかもしれません。これらも JavaScript の有効な演算子ですが、=== や !== とは異なります。前者のバージョンは値が同様であるかを判定しますが、データ型が同様かは判定しません。後者は厳格なバージョンで値とデータ型の両方を判定します。厳格なバージョンはエラーとなることが少ないため後者を使用することをお勧めします。

+
+ +

もし、これらの値をコンソールに入力したら、すべて true または false の値を返します。これは前回の記事で言及した、真偽値です。真偽値はとても便利です。コードで判断をすることを可能にしてくれます。また選択肢を選ぶときには毎回使うことになるでしょう。例えば以下のような場合に。

+ + + +

後の記事にて、条件文でどのようにロジックをコーディングするのかを見ていきます。とりあえずの簡易な例で見てみましょう。

+ +
<button>起動する</button>
+<p>マシンは停止中です。</p>
+
+ +
const btn = document.querySelector('button');
+const txt = document.querySelector('p');
+
+btn.addEventListener('click', updateBtn);
+
+function updateBtn() {
+  if (btn.textContent === '起動する') {
+    btn.textContent = '停止する';
+    txt.textContent = 'マシンが起動しました!';
+  } else {
+    btn.textContent = '起動する';
+    txt.textContent = 'マシンは停止中です。';
+  }
+}
+ +

{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}}

+ +

新しいウィンドウで開く

+ +

等価演算子が updateBtn() 関数の中で使用されていることがわかりますね。今回の場合は数値が同じ値かを判定するためには使用していません。ボタンの内容として設定されている文字列が、特定の文字列であるかどうかを比較しています。ただし、原理的には同じ働きです。もしボタンに「起動する」と書かれていれば、押されたときにボタンのラベルが「停止する」に代わります。もしボタンに「停止する」と書かれていれば、再度入れ替わって元に戻ります。

+ +
+

メモ: 2 つの状態を行き来するこのような操作を一般的にトグルといいます。スイッチの ON/OFF のように、ある状態がもう一つの状態にトグル (切り替え) するといいます。

+
+ +

スキルをテストしよう!

+ +

この記事の終わりまで到達しましたが、最も大事な情報を覚えていますか?移動する前に、この情報を取得したかのテストを見ることができます — Test your skills: Math を見てください。

+ +

まとめ

+ +

この記事では、JavaScript の数値処理で知っておくべき基礎的なことを学びました。JavaScript を学習する間、今後も繰り返し数値を扱うことになるので、しっかりと復習しておきましょう。数学が好きではなくとも、この章はとても短いので安心して (復習して) ください。

+ +

次の章では文字列と、文字列を JavaScript で操作する方法について見ていきます。

+ +
+

メモ: もし数学が好きで、JavaScript にどう実装されているかをもっと知りたいのであれば、MDN の JavaScript のメインの章に詳細がたくさん載っています。まずは数値と日付式と演算子辺りの記事から読むのがいいでしょう。

+
+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/first_steps/silly_story_generator/index.html b/files/ja/learn/javascript/first_steps/silly_story_generator/index.html new file mode 100644 index 0000000000..ae52da17c7 --- /dev/null +++ b/files/ja/learn/javascript/first_steps/silly_story_generator/index.html @@ -0,0 +1,151 @@ +--- +title: バカ話ジェネレーター +slug: Learn/JavaScript/First_steps/Silly_story_generator +tags: + - Arrays + - Assessment + - CodingScripting + - JavaScript + - Numbers + - Operators + - Variables + - 'l10n:priority' + - strings + - 初心者 + - 学習 +translation_of: Learn/JavaScript/First_steps/Silly_story_generator +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}
+ +

この評価試験では、このモジュールを通して身に付けた知識を生かして、ランダムなバカ話を生成する楽しいアプリを作ります。楽しんでください!

+ + + + + + + + + + + + +
前提条件:この評価試験を試す前に、このモジュール内のすべての記事を一通り作業しておくべきです。
目的:JavaScript の基礎である、変数、数値、演算子、文字列、配列などの理解をテストする。
+ +

開始地点

+ +

評価試験を開始するには...

+ + + +
+

: 上記の手順に代わって、JSBinThimble のようなサイトを使って評価試験を実施できます。HTML、CSS、JavaScript をオンラインエディターにペーストできます。使っているオンラインエディターが独立した JavaScript パネルを持たない場合、HTML ページ内の <script> 要素内に書いても問題ありません。

+
+ +

プロジェクトの要点

+ +

HTML および CSS と少しのテキストと JavaScript 関数がありますね。JavaScript を必要なだけ書いて、下記のような動作をするプログラムを書きましょう。

+ + + +

下記のスクリーンショットは完成したプログラムが出力する例を表しています:

+ +

+ +

これ以上のアイデアを与えるには完成プログラムの例を見てください (ソースコードは覗かないで!)

+ +

完成させるステップ

+ +

以下の項目が達成すべきリストです。

+ +

基本的なセットアップ

+ +
    +
  1. index.html ファイルと同じディレクトリーに main.js を作ります。
  2. +
  3. {{htmlelement("script")}} 要素を使用して、HTML ファイルに main.js への参照を外部 JavaScript として適用します。{{htmlelement("script")}} 要素は </body> タグの直前に配置します。
  4. +
+ +

最初の変数と関数

+ +
    +
  1. 先ほどのテキストファイル内の "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" という見出しの直後にあるコードをコピーして main.js の先頭に貼り付けます。これで "Enter custom name" テキストフィールド (customName) 、"Generate random story" ボタン (randomize) 、HTML の body の下のほうにある {{htmlelement("p")}} 要素 (story) への参照を保持することができます。さらに randomValueFromArray() という、引数として配列を取りその配列からランダムに 1 つの項目を戻り値として返す関数が使えるようになります。
  2. +
  3. 次にテキストファイルの 2番目のセクションを見てみましょう。"2. RAW TEXT STRINGS" という見出しのところです。このプログラムの入力となる文字列が書かれています。main.js の内部で使用できるように、これらの文字列を変数に保持してください。 +
      +
    1. 先頭の長い長い文字列を storyText という変数に格納します。
    2. +
    3. 3 つセットになっている最初の文字列の組を insertX という配列に格納します。
    4. +
    5. 2組目の文字列を insertY という配列に格納します。
    6. +
    7. 3組目の文字列を insertZ という配列に格納します。
    8. +
    +
  4. +
+ +

イベントハンドラーと未完成の関数の配置:

+ +
    +
  1. テキストファイルに戻ります。
  2. +
  3. "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" という見出しの直後にあるコードをコピーして main.js ファイルの最後に貼り付けます。これで、 +
      +
    • randomize 変数へのクリックイベントリスナーが追加され、その変数に紐づくボタンが押された場合に result() 関数が実行されるようになります。
    • +
    • 部分的に実装されている result() 関数の定義が追加されます。この課題の中で、この関数の残りを実装し、正しく動作するようにします。
    • +
    +
  4. +
+ +

result() 関数の作成

+ +
    +
  1. newStory という変数を作り、storyText の値を newStory 変数に格納します。これはボタンが押された場合に、毎回新しい話を作り出すために必要となります。もし storyText 変数自体に変更を加えてしまうと一度しか面白い話が生成できなくなってしまいます。
  2. +
  3. xItemyItemzItem という変数を 3 つ作成し、それぞれ対応する配列で呼び出した randomValueFromArray() の戻り値を設定します (それぞれの配列に含まれる文字列がランダムに選ばれます)。例えば、関数を呼び出して insertX から一つの文字列を取得するには randomValueFromArray(insertX) のように書きます。
  4. +
  5. 次に newStory 文字列内の :insertx::inserty::insertz: という 3 か所のプレースホルダーをそれぞれ xItemyItemzItem に格納されている文字列で置き換えます。ここでは適切なメソッドを使用して、newStory に対して何度メソッドを呼び出しても newStory 自体の値を変えずに置換された文字列が手に入るようにしてください。これでボタンが何度押されても、プレースホルダーの値をランダムなバカ話で置き換えることができます。もう少しヒントを出すと、そのメソッドは見つけた最初の部分文字列だけを置き換えるため、同じ部分文字列を置換するためには 2 回メソッドを呼び出す必要があるでしょう。
  6. +
  7. 最初の if ブロックで、newStory の文字列内で見つかる 'Bob' という文字列を name 変数の値で置換するため、別の文字列置換のメソッド呼び出し追加します。このブロック内では、「もし ( if ) customName テキストフィールドに何かが入力されていれば、Bob をその文字列で置き換える」ということを言っています。
  8. +
  9. 次の if ブロックの中では、uk のラジオボタンが選択されているかどうかを調べています。もし選択されているのなら、重さと温度の単位をポンド・華氏から、ストーン・摂氏に変換したいと思います。そのために必要なことは... +
      +
    1. ポンドからストーンへ変換する公式、および、華氏から摂氏へ変換する公式を調べます。
    2. +
    3. weight 変数が宣言されている行内の、300 を ポンドからストーンに変換した値で置き換えます。そして ' stone' (ストーン) を Math.round() の結果に対して、その後ろに結合します。
    4. +
    5. temperature 変数が宣言されている行内の、94 を華氏から摂氏に変換した値で置き換えます。こちらには ' centigrade' (摂氏~度) という文字を Math.round() の結果に対して、後ろに結合します。
    6. +
    7. 上記2 つの変数の宣言の直後に、さらにもう 2 つ文字列を置換するコードを書いて、'94 farenheit' を temperature 変数の内容に、'300 pounds' を weight 変数の内容にそれぞれ置換します。
    8. +
    +
  10. +
  11. 最後に、関数の下から 2行目にある、story 変数の textContent プロパティ(段落を参照している) を、newStory 変数の内容で置き換えます。
  12. +
+ +

ヒントと tips

+ + + +

評価

+ +

もし特定の組織の元でこのコースを受けているのなら、先生やメンターに出来たものを見せて、評価をお願いしてみましょう。もし自分だけでやっているのなら、この評価試験のスレッドや、Mozilla IRC#mdn IRC チャンネルに評価をお願いしてみましょう。まずはやってみましょう。カンニングしても得られるものはないですよ!

+ +

{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/javascript/first_steps/strings/index.html b/files/ja/learn/javascript/first_steps/strings/index.html new file mode 100644 index 0000000000..d4b850bd6d --- /dev/null +++ b/files/ja/learn/javascript/first_steps/strings/index.html @@ -0,0 +1,240 @@ +--- +title: テキストを扱う — JavaScript での文字列 +slug: Learn/JavaScript/First_steps/Strings +tags: + - Article + - Beginner + - CodingScripting + - Guide + - JavaScript + - Join + - Quotes + - concatenation + - 'l10n:priority' + - strings +translation_of: Learn/JavaScript/First_steps/Strings +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}
+ +

プログラミングでは文字の羅列を文字列と呼びますが、次はこれを学習しましょう。この記事では、JavaScript でよく使われる、文字列を作ったり、引用符をエスケープしたり、文字列を結合したりといった、文字列について本当に知っておくべきことだけを見てみましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピュータの知識および HTML と CSS への理解、JavaScript とは何かを知っている。
目的:JavaScript の文字列操作に慣れる。
+ +

言葉の力

+ +

言葉はコミュニケーションの大部分を担う、人類にとって、とても大切なものです。Web は情報の共有やコミュニケーションができるように設計された大規模な文字ベースの媒体ですので、そこで使用される言葉を操作できると便利です。{{glossary("HTML")}} は意味付けされ、構造化されたテキストを提供し、{{glossary("CSS")}} がきれいに体裁を整える事を可能にし、そして JavaScript には、挨拶用の文章を生成したり、適切なラベルを表示したり、言葉を並べ替えたりといった、文字列を操作するたくさんの機能が含まれています。

+ +

今までこのコースでお見せしたプログラムのほとんどが、何らかの文字列操作を含んでいましたね。

+ +

文字列 — 基本

+ +

文字列は一見すると数値と同じように見えますが、少し深く見ていくと、違いに気づくことでしょう。まずは慣らすために基本的なコードをブラウザの開発者ツールに入力してみましょう。

+ +

文字列を作る

+ +
    +
  1. 初めに、次の行を入力してみましょう。 +
    let string = '革命はテレビでは放送されない。';
    +string;
    + 数値のところでやったのと同じように、変数を宣言して、値を入れて初期化しています。そして値を返しています。ただ違うのは、文字列が引用符で囲まれて書かれていることです。
  2. +
  3. もし引用符で囲わななかったり、どちらか一方を書き忘れたりすると、エラーになります。 +
    let badString = これはテストです;
    +let badString = 'これはテストです;
    +let badString = これはテストです';
    + これらの行は動きません。なぜなら引用符で文字を囲わなければ、変数名や、プロパティ名や、予約語などと解釈されてしまうためです。もしブラウザが引用符を見つけられないと、エラーとなります (たとえば "missing ; before statement" [文の前に、セミコロンが見つかりません] のようなエラーです)。2行目の例のように、ブラウザが引用符を見つけても、文字列の終わりが示されていなければ、これもエラーとなります ("unterminated string literal" [文字列リテラルの終わりがありません] というエラーです)。このようなエラーがプログラムで起きたら、全ての文字列について、引用符の付け忘れがないかを確認してください。
  4. +
  5. 続くコードは先ほど変数を string という名前で宣言していれば、動くでしょう。試してみましょう。 +
    let badString = string;
    +badString;
    + badString という変数に string という変数の値が設定されたことでしょう。
  6. +
+ +

シングルクォーテーション vs. ダブルクォーテーション

+ +
    +
  1. JavaScript では、文字列を囲む引用符として、シングルクォーテーションとダブルクォーテーションを使用することができます。以下のどちらの例も正しく動きます。 +
    let sgl = 'シングルクォーテーション';
    +let dbl = "ダブルクォーテーション";
    +sgl;
    +dbl;
    +
  2. +
  3. どちらを使ってもほとんど違いはありません。どちらを使うかは好みの問題ですが、どちらを使うかは統一するべきでしょう。両方を同時に使うと混乱してしまいます、特に同じ文字列に二種類の引用符を使ってしまうときなど!次の行はエラーです。 +
    let badQuotes = 'なんということだ!";
    +
  4. +
  5. ブラウザは上の文字列が閉じていないと認識します。なぜなら、文字列を囲うのに使用していない引用符はその文字列の中に含めることができるからです。たとえば次の例は問題ありません。 +
    let sglDbl = 'Would you eat a "fish supper"?';
    +let dblSgl = "I'm feeling blue.";
    +sglDbl;
    +dblSgl;
    +
  6. +
  7. ただし、文字列の中に、囲んでいるのと同じ種類の引用符を含めることはできません。以下の例は文字列の終わりがわからないので、ブラウザを混乱させてしまいます。 +
    let bigmouth = 'I've got no right to take my place...';
    + それでは同じ種類の引用符を含めるにはどのようにすればよいでしょうか。
  8. +
+ +

文字列をエスケープする

+ +

先ほどのコード行を直すには、問題となっている引用符をエスケープする必要があります。文字のエスケープとは、その文字が、コードではなく、文字列の一部であるとブラウザに認識させる書き方です。JavaScript ではバックスラッシュ ( \ [環境によっては円マーク (¥)]) を文字の前におくことでエスケープすることができます。

+ +
let bigmouth = 'I\'ve got no right to take my place...';
+bigmouth;
+ +

これでうまく動きます。 同じ方法で他の文字をエスケープする (例えば \") ことができ、それ以外にも特別なコードがあります。詳細はエスケープ記法を見てください。

+ +

文字列を連結する

+ +
    +
  1. コンカチする (concatenate) という単語は「結合する」ことを表すプログラミングの用語です。JavaScript で文字列を結合するにはプラス (+) 演算子を使用します。数値の加算をするのに使用した演算子ですが、今回は違う動作をします。下の例をコンソールに入力してみてください。 +
    let one = 'こんにちは、';
    +let two = 'ご機嫌いかがでしょう?';
    +let joined = one + two;
    +joined;
    + この例の実行結果は joined という変数に格納され、値は "こんにちは、ご機嫌いかがでしょう?" となります。
  2. +
  3. 今の例は 2 つの文字列だけを結合しましたが、+ 演算子が変数と変数の間にあれば、いくつでも結合することができます。例えば、次の例を試しましょう。 +
    let multiple = one + one + one + one + two;
    +multiple;
    +
  4. +
  5. 変数のほかに、実際の文字列と混ぜて使うこともできます。 +
    let response = one + '私は元気です。' + two;
    +response;
    +
  6. +
+ +
+

: コード中に、シングルクォーテーションおよびダブルクォーテーションで囲われた、実際の文字列を書いたときそれは文字列リテラルと呼ばれます。

+
+ +

様々な結合

+ +

実際に文字列が結合されている場面を見てみましょう。これはこのコースの最初の方からの例です。

+ +
<button>押してみて!</button>
+ +
let button = document.querySelector('button');
+
+button.onclick = function() {
+  let name = prompt('あなたの名前は?');
+  alert('こんにちは、' + name + 'さん。初めまして!');
+}
+ +

{{ EmbedLiveSample('Concatenation_in_context', '100%', 50, "", "", "hide-codepen-jsfiddle") }}

+ +

4行目でユーザに答えてもらうため、{{domxref("Window.prompt()", "Window.prompt()")}}関数を使用して、テキストを入力できるポップアップダイアログを表示し、ユーザによって入力された文字列を name 変数に格納しています。そして、5行目で{{domxref("Window.alert()", "Window.alert()")}}関数を使用し、2 つの文字列リテラルと name 変数を結合して別のポップアップに文字列を作り上げています。

+ +

数値 vs. 文字列

+ +
    +
  1. それでは文字列と数値を足したら (もしくは結合したら) 何が起きるでしょうか。コンソールに入力してみましょう。 +
    'フロント' + 242;
    +
    + エラーが起きると予想したかもしれませんが、普通に動きます。文字列を数値として表すのには意味がありませんが、数値を文字で表すのはわかりますね。つまりブラウザはどうやら、数値を文字列に変換し、2 つの文字列としてから結合しているようです。
  2. +
  3. 数字同士でやっても同じです。数字を引用符で囲むと文字列になります。次の行を実行してみてください。(typeof演算子で変数が文字列なのか数値なのか調べています。) +
    let myDate = '19' + '67';
    +typeof myDate;
    +
  4. +
  5. もし、数値を文字列に変換したかったり、文字列を数値に変換したかったりする場合には、次の 2 つの生成方法を見てください。 +
      +
    • {{jsxref("Number")}}オブジェクトは渡されたものすべてを数値に変換します。次の例を実行してみましょう。 +
      let myString = '123';
      +let myNum = Number(myString);
      +typeof myNum;
      +
    • +
    • 反対に全ての数値は toString() という文字列に変換するメソッドを持っています。 +
      let myNum = 123;
      +let myString = myNum.toString();
      +typeof myString;
      +
    • +
    + この生成方法は状況によってはとても便利です。例えば、ユーザがフォームのテキストフィールドに数字を入力した場合、入力された値は文字列です。しかし、その数字を使って計算したい場合、数値にしなければなりません。そんな時は Number() に任せましょう。これは実際に数字当てゲームの 54行目で使用した方法です。
  6. +
+ +

テンプレートリテラル

+ +

遭遇する可能性のある別のタイプの文字列構文は、テンプレートリテラル(テンプレート文字列と呼ばれることもあります)です。 これは、より柔軟で読みやすい文字列を提供する新しい構文です。

+ +
+

注: 以下の例をブラウザの JavaScript コンソールに入力して、どのような結果が得られるかを確認してください。

+
+ +

標準の文字列リテラルをテンプレートリテラルに変換するには、引用符 (' ' または " ") をバッククォート文字 (` `) に置き換える必要があります。

+ +

簡単な例。

+ +
let song = 'Fight the Youth';
+ +

テンプレートリテラルに変換します。

+ +
song = `Fight the Youth`;
+ +

文字列を連結したり、文字列内に式の結果を含めたりする場合、従来の文字列で書くのは面倒です。

+ +
let score = 9;
+let highestScore = 10;
+let output = 'I like the song "' + song + '". I gave it a score of ' + (score/highestScore * 100) + '%.';
+ +

テンプレートリテラルはこれを非常に簡単に行えます。

+ +
output = `I like the song "${ song }". I gave it a score of ${ score/highestScore * 100 }%.`;
+ +

複数の文のピースを繋げる必要はありません。文章全体を1組のバッククォートで囲むだけです。文字列内に変数または式を含める場合は、プレースホルダーと呼ばれる ${ } 構造内に含めます。

+ +

テンプレートリテラル内に複雑な式を含めることもできます。

+ +
let examScore = 45;
+let examHighestScore = 70;
+examReport = `You scored ${ examScore }/${ examHighestScore } (${ Math.round((examScore/examHighestScore*100)) }%). ${ examScore >= 49 ? 'Well done, you passed!' : 'Bad luck, you didn\'t pass this time.' }`;
+ + + +

従来の文字列リテラルで複数の行に分割する場合は、改行文字 \n を含める必要がありました。

+ +
output = 'I like the song "' + song + '".\nI gave it a score of ' + (score/highestScore * 100) + '%.';
+ +

テンプレートリテラルはソースコードの改行をそのまま再現するため、改行文字は不要になります。 以下は同じ結果を得ます。

+ +
output = `I like the song "${ song }".
+I gave it a score of ${ score/highestScore * 100 }%.`;
+ +

できるだけ早くテンプレートリテラルの使用に慣れることをお勧めします。 これらは最新のブラウザで十分にサポートされており、サポートが不足しているのは Internet Explorer だけです。私たちの例の多くはまだ標準の文字列リテラルを使用していますが、今後さらに多くのテンプレートリテラルを含める予定です。

+ +

高度な機能の例と詳細については、テンプレートリテラルのリファレンスページを参照してください。

+ +

あなたのスキルをテストしてください!

+ +

この記事の最後に到達しましたが、最も重要な情報を覚えていますか? 先に進む前に、この情報を記憶していることを確認するためのいくつかのテストを見つけることができます。これには次の記事の知識も必要なので、最初にそれを読むことをお勧めします。

+ +

結論

+ +

ここまでが JavaScript での文字列の基礎になります。次の記事では、JavaScript で使える文字列操作の組み込み関数と、それを使って思い通りの形に文字列を変換する方法を、その基礎の上に建てていきましょう。

+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/first_steps/useful_string_methods/index.html b/files/ja/learn/javascript/first_steps/useful_string_methods/index.html new file mode 100644 index 0000000000..0c2f22adfd --- /dev/null +++ b/files/ja/learn/javascript/first_steps/useful_string_methods/index.html @@ -0,0 +1,680 @@ +--- +title: 便利な文字列メソッド +slug: Learn/JavaScript/First_steps/Useful_string_methods +tags: + - Article + - Beginner + - CodingScripting + - JavaScript + - Learn + - case + - indexof + - 'l10n:priority' + - length + - lower + - replace + - split + - upper +translation_of: Learn/JavaScript/First_steps/Useful_string_methods +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}
+ +

文字列の基本についてはすでに見ました。ここからはレベルを上げて、組み込みのメソッドを使用して文字列に対して実行できる便利な操作について考えてみましょう。例えば、文字列の長さを調べたり、繋げたり、分割したり、ある文字を他の文字に置き換えたりなどです。

+ + + + + + + + + + + + +
前提条件:基礎的なコンピュータの知識、HTML と CSS の基本の理解、JavaScript が何かを知っていること。
目的:文字列がオブジェクトであることを理解して、そのオブジェクトで使用できる基本的なメソッドを使って文字列を操作する方法を身に付ける。
+ +

オブジェクトとしての文字列

+ +

JavaScript ではほとんどのものはオブジェクトです。たとえば、次のように文字列を作った時も、

+ +
let string = 'This is my string';
+ +

この変数は文字列オブジェクトのインスタンスになり、大量のプロパティとメソッドが使用可能となります。{{jsxref("String")}} オブジェクトのページに行って、横にある一覧を眺めてみてください!

+ +

また、脳が溶け出しそうかもしれませんが、安心してください!先ほどのページにある、ほとんどのメソッドは学習の初期に覚える必要はありません。しかし、今から紹介する、文字列操作のメソッドはとてもよく使いますのでぜひ覚えましょう。 

+ +

ブラウザの開発者コンソールにいくつかの例を入力してみましょう。

+ +

文字列の長さを調べる

+ +

ただ {{jsxref("String.prototype.length", "length")}} プロパティを使用すればよいので、とても簡単です。次の行を入力してみましょう。

+ +
let browserType = 'mozilla';
+browserType.length;
+ +

これで 7 という数値が戻ります。なぜなら "mozilla" は 7文字だからです。例えば、文字の長さによって文字列を並べたいときや、ユーザーがある長さ以上のユーザー名をフォームの入力フィールドに入れたことを知らせたりするような場面で便利です。

+ +

特定の文字列を扱う

+ +

前の例と関連していますが、文字列に対して角括弧記法を使用することで文字列中の任意の 1文字が得られます。つまり角括弧 ([]) を変数名の後ろに付け、その中に数値を入れることで、その番目にある文字が返ってきます。例えば最初の一文字を取得するには次のようにします。

+ +
browserType[0];
+ +

コンピューターは 1 からではなく、0 から数えます!例えば、文字列から最初の文字を見つけてアルファベット順に並べるときに使うことができます。

+ +

文字列の一番最後の文字を取得したいときは、先ほどの length プロパティと組み合わせて以下のようにします。

+ +
browserType[browserType.length-1];
+ +

"mozilla" の長さは 7 ですが、0 から始まるので、最後の文字の位置は 6 になります。よって length-1 とする必要があるのです。

+ +

部分文字列を探して抽出する

+ +

長い文字列の中に、ある文字列が存在するか調べたいと思うことがあります (よく文字列中に部分文字列が存在するなどといいます)。これには、探したい部分文字列を{{glossary("parameter","引数")}}に取る {{jsxref("String.prototype.indexOf()", "indexOf()")}} メソッドを使用することで可能です。

+ +

もし対象の文字列中に部分文字列が見つかった場合、このメソッドは部分文字列のインデックス位置を表す数値 (対象の文字列上で部分文字列が始まる文字数) を返します。もし対象の文字列中に部分文字列が見つからなかった場合は、-1 の値を返します。

+ +
    +
  1. 以下を試してみましょう。 +
    browserType.indexOf('zilla');
    + このコードは 2 を返します。なぜならば、"mozilla"という文字列中で、部分文字列"zilla"の開始位置が 2 (0、1、2 — つまり 3文字目)であるからです。このようなコードは文字列を絞り込むときなどに使います。例えば、ウェブサイトのアドレスの一覧があったとき、その中から"mozilla"を含むものだけを表示したい場合などです。
  2. +
+ +
    +
  1. 部分文字列が含まれてることを確認するもう一つの方法があり、こちらのほうが効果的な場合があります。 +
    browserType.indexOf('vanilla');
    + 上記のコードは -1 を返します。これは部分文字列 (この場合は 'vanilla') がメインの文字列の中に見つからなかった場合に返されます。
    +
    + これを使って、部分文字列 'mozilla' を含まない (あるいは否定演算子 !== を使うなら含む) 文字列のすべてのインスタンスを見つけることができます。 + +
    if(browserType.indexOf('mozilla') === -1) {
    +  // もし部分文字列 'mozilla' が含まれていない場合は、
    +  // 文字列で何かをします。
    +}
    +
    +if(browserType.indexOf('mozilla') !== -1) {
    +  // もし部分文字列 'mozilla' が含まれている場合は、
    +  // 文字列で何かをします。
    +}
    +
  2. +
  3. 部分文字列がその文字列のどこから始まるかが分かっており、どこで終わっているかがわかれば、その部分文字列を {{jsxref("String.prototype.slice()", "slice()")}} メソッドを使用することで抽出することができます。 +
    browserType.slice(0,3);
    + このコードは "moz" という文字列を返します。最初の引数は抽出を始める最初の位置で、2番目の引数が抽出する最後の文字の直後の位置です。つまり、この場合先頭から 4番目の手前までの文字列が切り出されたということです。言い換えると、この場合は 2番目の引数と同じ 3文字が切り出されました。
  4. +
  5. また、ある文字以降の文字列の残りの文字をすべて抽出したいとわかっている場合は、2番目のパラメータを含める必要はありません!その代わり、文字列内の残りの文字を抽出したい文字の位置を含める必要があるだけです。次のようにしてみてください。 +
    browserType.slice(2);
    + この例は "zilla" という文字列を返します。なぜなら、2 の位置にある文字は z であり、2番目の引数を指定していないため、3文字目から最後までが部分文字列として戻ったのです。 
  6. +
+ +
+

: slice() の 2番目の引数はオプション (任意指定) です。もし指定しなければ、元々の文字列の最後まで切り出しを行います。他にもオプションがありますので、さらに詳しく知りたければ{{jsxref("String.prototype.slice()", "slice()")}}のページで調べてみましょう。

+
+ +

大文字・小文字の切り替え

+ +

String には{{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}}と{{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}}という 2 つのメソッドがあり、引数として渡された文字列のすべての文字の大文字・小文字を切り替えます。これは例えば、ユーザーの入力を DB に保存する場合に、値を正規化するのに便利です。

+ +

それでは次の行を入力し、何が起きるか見てみましょう。

+ +
let radData = 'My NaMe Is MuD';
+radData.toLowerCase();
+radData.toUpperCase();
+ +

文字列の一部分を書き換える

+ +

{{jsxref("String.prototype.replace()", "replace()")}}メソッドを使用することで、ある部分文字列を他の文字列に置き換えることができます。基本レベルではとても単純に動作しますが、replace() メソッドは高度な機能を持っています (今回はその機能は紹介しませんが)。

+ +

検索する文字列と、置き換える文字列の 2 つを引数に取ります。次の例を実行してみてください。

+ +
browserType.replace('moz','van');
+ +

これはコンソールで"vanilla"を返しますが、browserType の値は、"mozilla"のままです。プログラムで変数 browserType の値を実際に更新するには、演算の結果を変数に設定し直す必要があります。つまりそれ変数に設定されている部分文字列を自動的には更新してくれないのです。従って実際に変数の内容を更新するためには browserType = browserType.replace('moz','van'); のように書きます。

+ +

アクティブ学習の実例

+ +

この章では、文字列を操作するコードを書いてもらいます。以下のどの問題も文字列の配列をループで回して、順序なしリスト形式で表示しますが、配列やループに関して今は理解する必要はありません。配列については今後の記事で説明します。必要なのは、どのような書式で出力するかという要求を満たすコードを書くことです。

+ +

どの例も「リセット」ボタンがあるので、コードが動かなくなった場合は使用してみてください。もし本当に行き詰まってしまった場合には、「答えを見る」ボタンを押すことで、回答を見ることができます。

+ +

挨拶を選別する

+ +

まずは簡単な問題から始めます。挨拶状に使用するメッセージの配列の中から、クリスマスのメッセージのみを選別し、並べ替えてください。やるべきことは、メッセージがクリスマスメッセージであることを判定しその場合のみ表示されるよう、if ( ... ) 文の条件式を埋めることです。

+ +
    +
  1. まず、各メッセージがどうであればクリスマス(Christmas)メッセージとみなせるかを考えてください。こういうメッセージ中にはどんな文字列があり、それが存在するか判定するのにどんなメソッドが使えるでしょうか?
  2. +
  3. それから、オペランド 1 演算子 オペランド 2 の形で条件を書いてください。その条件は左辺と右辺が等しいかというものでしょうか?もしくは左辺のメソッドの戻り値が、右辺であるかというものでしょうか。
  4. +
  5. ヒント: 今回の場合、メソッドの戻り値の結果が何でないかを判定するとよいでしょう。
  6. +
+ + + +

{{ EmbedLiveSample('Playable_code', '100%', 590, "", "", "hide-codepen-jsfiddle") }}

+ +

単語の最初の文字を大文字に直す

+ +

この課題ではイギリスの都市名を題材にします。ところが、単語の大文字と小文字がぐちゃぐちゃになっています。そこで最初の文字を大文字にし、残りをすべて小文字にしてみましょう。こういう手順でやってみます:

+ +
    +
  1. input 変数に入っている文字列全体を小文字に変換し、それを新しい変数に格納します。
  2. +
  3. この新しい変数にある最初の文字を取り出し、さらに別の変数に格納します。
  4. +
  5. その新しい変数を部分文字列とし、小文字ばかりの文字列にある最初の文字を置換して、大文字化します。この置換処理の結果を別の新しい変数に格納します。
  6. +
  7. input 変数ではなく、最終結果が result 変数の値に代入されるよう修正します。
  8. +
+ +
+

: ヒント — 文字列メソッドのパラメーターは文字列リテラルである必要はありません。変数でもよいですし、メソッドが呼び出される変数であっても構いません。

+
+ + + +

{{ EmbedLiveSample('Playable_code_2', '100%', 550, "", "", "hide-codepen-jsfiddle") }}

+ +

既存の部分から新しい文字列を作成する

+ +

最後の課題では、北イングランドの駅に関する情報が入っている文字列を格納している配列を扱います。この文字列にはデータ項目として、アルファベット 3文字の駅コード、次にコンピューター読み取り用のデータ、次にセミコロン、そして人間が読める駅名が入っています。例:

+ +
MAN675847583748sjt567654;Manchester Piccadilly
+ +

駅コードと駅名を抽出し、それを文字列にまとめてこのような形にします:

+ +
MAN: Manchester Piccadilly
+ +

このようにプログラムしてみましょう:

+ +
    +
  1. アルファベット 3文字のコードを抽出し、新しい変数に格納します。
  2. +
  3. セミコロンの文字インデックス番号を検索します。
  4. +
  5. セミコロンの文字インデックス番号を参照位置にして、人が読める駅名を抽出し、新しい変数に格納します。
  6. +
  7. この 2 つの新しい変数と文字列リテラルとを連結し、最終的な文字列を作成します。
  8. +
  9. input 変数ではなく、この最終結果が result 変数の値に代入されるよう修正します。
  10. +
+ + + +

{{ EmbedLiveSample('Playable_code_3', '100%', 585, "", "", "hide-codepen-jsfiddle") }}

+ +

スキルをテストしよう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?移動する前に、情報を維持しているかを検証するテストを見ることができます— Test your skills: Strings を見てください。

+ +

結論

+ +

プログラミング、特に JavaScript では単語や文を処理できるようになることが大事であるという現実から逃れることはできません。それはウェブサイトは人とのコミュニケーションがすべてとなるためです。この記事では、文字列を処理するのに当面知っておくべき基礎を解説しました。今後もっと複雑なトピックに進んで行くときに役立つはずです。次に、配列を見てみます。重要なデータ型のうち、短期間で押さえておくべき最後の 1 つです。

+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/first_steps/variables/index.html b/files/ja/learn/javascript/first_steps/variables/index.html new file mode 100644 index 0000000000..80c3c5af57 --- /dev/null +++ b/files/ja/learn/javascript/first_steps/variables/index.html @@ -0,0 +1,342 @@ +--- +title: 必要な情報を保存する — 変数 +slug: Learn/JavaScript/First_steps/Variables +tags: + - Arrays + - Booleans + - JavaScript + - Numbers + - Objects + - Updating + - Variables + - declaring + - initializing + - 'l10n:priority' + - loose typing + - strings +translation_of: Learn/JavaScript/First_steps/Variables +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}
+ +

前回までの記事を読んで、高度な視点からその機能を概観し、JavaScript とは何なのか、それで何ができるのか、他の Web の技術とどう一緒に使うのか、そして、どのような機能があるのかが分かったのではないでしょうか。この記事では、本当の基本に立ち返り、JavaScript の基本的な構成要素である変数について見てみましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターの知識、HTML と CSS の基本についての理解、JavaScript が何かが分かっていること。
目的:JavaScript の変数についての基礎を会得する。
+ +

必要なツール

+ +

この記事を通じて、理解した内容を確認するために、コードを入力してもらうことがあるでしょう。デスクトップを使用しているのなら、JavaScript のサンプルコードを打ち込むのに最適なのはブラウザーの JavaScript コンソールでしょう(詳しくはブラウザーの開発者ツールとはをご覧ください)。

+ +

変数とは

+ +

変数は値の入れものです。数を合計したり、ある文章の一部を格納するのに使用します。変数が特別なのは、変数が持っている値を変更できることにあります。ちょっと例を見てみましょう。

+ +
<button>押してください</button>
+ +
const button = document.querySelector('button');
+
+button.onclick = function() {
+  let name = prompt('あなたの名前は何ですか?');
+  alert('こんにちは、' + name + 'さん、初めまして!');
+}
+ +

{{ EmbedLiveSample('What_is_a_variable', '100%', 50, "", "", "hide-codepen-jsfiddle") }}

+ +

この例では、ボタンを押すとちょっとしたコードが走ります。最初の行では、ボタンを押した人の名前を入力するボックスが画面に表示されます。そして入力された値を変数に保存します。2行目では、入力した人の名前を変数から取り出して、あいさつのメッセージに含めています。

+ +

なぜこれが便利なのかを理解するためには、変数を使用せずにこの例と同じことをするためにはどのようにすればよいのか考えてみましょう。恐らく次のようになるでしょう。

+ +
let name = prompt('あなたの名前は何ですか?');
+
+if (name === 'アダム') {
+  alert('こんにちは、アダムさん初めまして!');
+} else if (name === 'アラン') {
+  alert('こんにちは、アランさん初めまして!');
+} else if (name === 'ベラ') {
+  alert('こんにちは、ベラさん初めまして!');
+} else if (name === 'ビアンカ') {
+  alert('こんにちは、ビアンカさん初めまして!');
+} else if (name === 'クリス') {
+  alert('こんにちは、クリスさん初めまして!');
+}
+
+// ... さらに続く ...
+ +

もしかしたら、まだ完全にはコードの内容がわからないかもしれませんね!けれども、変数がなければ、適切なメッセージを表示するために、どんな名前が入力されたのかを延々と判定し続ける巨大なコードを書かなければならないことが、何となくでもわかるのではないでしょうか。これはまったくもって非効率です(このコードは 5人の名前しか表示できないのに既に大きくなっています)。さらに、すべての状況に対応するようには書くことはできないでしょう。

+ +

変数というのはとても合理的です。JavaScript に慣れていけばとても自然なものに感じられるでしょう。

+ +

変数についてもう一つ特筆すべき点は、変数には文字列や数字だけでなく、何でも格納できるということです。複雑なデータや、すごいことをする関数全体ですら保持できます。先に進めばさらに理解できるようになるでしょう。

+ +
+

メモ: 変数に値を「格納する」と言っていますが、これは重要な区別です。変数は値を保持するもので、値そのものではありません。つまり値の箱です。物を入れる段ボール箱のようなものだと思ってください。

+
+ +

+ +

変数を宣言する

+ +

変数を使用するためには、まずは変数を作らなければなりません。より正確には、「宣言する」といいます。そのためには var または let キーワードに続けて変数名を書きます。

+ +
let myName;
+let myAge;
+ +

ここでは 2 つの変数 myName と myAge を宣言しています。それではこの 2 つの行をブラウザーのコンソールに入力してみましょう。すぐ下のコンソールに入力することも可能です。続けて、好きな名前で変数を作ってみましょう。

+ +
+

: JavaScript では、命令の行末ごとにセミコロン (;) を書かなければなりません。1行ずつ書いているうちは動くかもしれませんが、複数行を書き始めたら動かなくなってしまうでしょう。いつでもセミコロンを書くようにして、慣れていきましょう。

+
+ +

今実行している環境に値が存在するかどうか、変数名を入力して確かめることができます。例えば、

+ +
myName;
+myAge;
+ +

これらの変数は現在、値を保持しておらず、空です。変数の名前を入力すると、undefined という値が表示されるでしょう。もし変数自体が存在していない場合はエラーメッセージが表示されます。以下の変数を入力してみてください。

+ +
scoobyDoo;
+ +
+

: 変数が存在していて値がないのと、変数自体が存在していないことを混同しないでください。この違いは重要です。上記の箱の例えでは、変数自体が存在しないということは値の箱(変数)がないということとなります。値がないということは、箱は確かにあるけれどその中に値がないということです。

+
+ +

変数を初期化する

+ +

変数を宣言したら、値を入れて初期化できます。初期化するには、変数名に続けて等号記号 (=) を入力し、変数に入れたい値を渡します。例えば次のように。

+ +
myName = 'Chris';
+myAge = 37;
+ +

コンソールに戻って上の行を入力してみてください。コンソール上に、変数に設定した値がその都度戻ってくることが確認できるでしょう。先ほど言ったように、変数の名前をコンソールに入力することで、その値が確認できます。もう一度、やってみましょう。

+ +
myName;
+myAge;
+ +

変数の宣言と初期化を一度にすることもできます。

+ +
let myDog = 'Rover';
+ +

2行で書くよりも簡単に書けるので、ほとんどの場合はこのように書くでしょう。

+ +

var と let の違い

+ +

ここまでで、「なぜ変数を定義するのに 2 つのキーワードが必要なのですか。なぜ var let があるのでしょうか」と考えるかもしれません。

+ +

その理由はやや歴史的なものです。JavaScript が最初に作成されたときには、var しかありませんでした。ほとんどの場合、基本的にはうまく機能しますが、その機能にはいくつかの問題があります。その設計は時々混乱したり、実に迷惑になることがあります。そこで、let を最新のバージョンの JavaScript で作成しました。これは、var とは多少異なる動作をする変数を作成するための新しいキーワードで、その過程での問題を修正しています。

+ +

一部の簡単な違いを以下に説明します。ここではすべての違いについて説明するわけではありませんが、JavaScript について詳しく学習するにつれてそれらの違いがわかるようになります (今すぐ読みたい場合は、let のリファレンスページを参照してください)。

+ +

はじめに、変数を宣言して初期化する複数行の JavaScript プログラムを作成した場合、変数を初期化した後で実際に変数を var で宣言することができます。例えば:

+ +
myName = 'Chris';
+
+function logName() {
+  console.log(myName);
+}
+
+logName();
+
+var myName;
+ +
+

メモ: Web コンソールで複数行の JavaScript を実行しているときだけでは、JavaScript コンソールに 1行ずつ入力してもうまくいきません。

+
+ +

これは巻き上げのために動作します。件名に関する詳細については var の巻き上げを読んでください。

+ +

巻き上げはもはや let で動作しません。上記の例で var を let に変更すると、エラーで失敗します。これは良いことです - 変数を初期化した後に宣言すると混乱しやすくなり、コードを理解するのが難しくなります。

+ +

第二に、var を使用するとき、好きなだけ同じ変数を何度でも宣言することができます、しかし let ではできません。次のようにします。

+ +
var myName = 'Chris';
+var myName = 'Bob';
+ +

しかし、次のようにすると 2行目でエラーが発生します。

+ +
let myName = 'Chris';
+let myName = 'Bob';
+ +

代わりにこれをしなければならないでしょう:

+ +
let myName = 'Chris';
+myName = 'Bob';
+ +

繰り返しますが、これは賢明な言語決定です。変数を再宣言する必要はありません。それは物事をより混乱させるだけです。

+ +

これらの理由などから、コードでは var ではなく可能な限り let を使用することをお勧めします。コードで古いバージョンの Internet Explorer をサポートする必要がない限り、var を使用する理由はありません (バージョン 11 まで let をサポートしていません。最近の Windows Edge ブラウザーでは、let をサポートしています)。

+ +

変数の値を変更する

+ +

変数を初期化して値が入ったら、もう一度値を入れなおすことで、変数の値を変更することができます。次の行を入力してみてください。

+ +
myName = 'Bob';
+myAge = 40;
+ +

変数の名前付けのルール

+ +

変数には制限はあるものの、大体どんな名前を付けることができます。ただし、一般的に、アルファベットと数字 (0-9, a-z, A-Z) やアンダースコアだけを使用すべきでしょう。

+ + + +
+

: 避けるべき予約語の一覧は字句文法 — キーワードで見つかるでしょう。

+
+ +

良い名前の例:

+ +
age
+myAge
+init
+initialColor
+finalOutputValue
+audio1
+audio2
+ +

悪い名前の例:

+ +
1
+a
+_12
+myage
+MYAGE
+var
+Document
+skjfndskjfnbdskjfb
+thisisareallylongstupidvariablenameman
+ +

さらにいくつかの変数を作成してみましょう。上記の内容をしっかりと覚えてください。

+ +

変数のデータ型

+ +

変数に保持する値にはいくつかの種類があります。このセクションでは、その種類について簡単に解説します。さらに詳細については、もっと先の記事で紹介します。

+ +

ここまで最初の 2 つは見てきましたが、他にもあります。

+ +

数値型

+ +

変数には数値を格納することができます。数値は 30 のような整数値や、2.456 のような実数値 (浮動小数点数とも呼ばれます ) が存在します。その他の言語とは違い、JavaScript ではデータ型を宣言する必要はありません。もし数値を変数に設定するならば、クォーテーションマークは付けてはいけません。

+ +
let myAge = 17;
+ +

文字列型

+ +

文字列とは文字が連なったもののことです。変数に文字列値を設定する場合、シングルクォーテーション (') またはダブルクォーテーション (") で文字を囲みます。囲み忘れると、JavaScript はその文字を変数名として解釈しようとしてしまいます。

+ +
let dolphinGoodbye = 'So long and thanks for all the fish';
+ +

真偽値

+ +

真偽値は true と false の二つの値だけを持ちます。どちらのコードを実行するべきかといった、条件を判定するためによく使います。例として、簡単なコードは以下のようなものです。

+ +
let iAmAlive = true;
+ +

実際には以下のように使われます。

+ +
let test = 6 < 3;
+ +

これは「小なり」演算子 (<) を使用して 6 が 3 より小さいかどうかを判定しています。想像の通り、6 は 3 より小さくないためにこれは false となります。このような演算子はまた今度じっくりと紹介します。

+ +

配列

+ +

配列とは角括弧 ([]) にカンマで区切った複数の値を格納できるオブジェクトです。コンソールに以下のように入力してみましょう。

+ +
let myNameArray = ['Chris', 'Bob', 'Jim'];
+let myNumberArray = [10, 15, 40];
+ +

配列を宣言したら、配列中の位置を指定することで、その値にアクセスすることができます。次のように入力してみましょう。

+ +
myNameArray[0]; // 'クリス'と表示されます
+myNumberArray[2]; // 40 と表示されます
+ +

角括弧で表示したい値の位置に応じたインデックス値を指定します。気づいたかもしれませんが JavaScript の配列は 0 始まりで、最初の要素のインデックスが 0 となります。

+ +

配列についても先の記事にて紹介します。

+ +

オブジェクト

+ +

プログラミングにおいて、オブジェクトとは現実のもの(オブジェクト)をモデルとしたコードの構造です。幅と長さについての情報をもつ駐車場を表す単純なオブジェクトもあれば、名前や身長、体重、話す言葉やあいさつもすることもできる、人を表すオブジェクトも作ることができます。

+ +

次の行をコンソールに入力してみましょう。

+ +
let dog = { name : 'ポチ', breed : 'ダルメシアン' };
+ +

オブジェクトに格納された情報を取得するには、以下のような書き方をします。

+ +
dog.name
+ +

とりあえずオブジェクトについて、今はここまでです。オブジェクトについてはもっと先のモジュールで紹介します。

+ +

動的型付け

+ +

JavaScript は他の言語と異なり、「動的型付け言語」という、格納するデータ型 (数値や文字列や配列など ) を変数に対して指定する必要のない言語です。

+ +

たとえば、もし変数を宣言して、クォーテーションマークで囲んだ値を渡すとします。すると、ブラウザーはこれを文字列として扱うでしょう。

+ +
let myString = 'Hello';
+ +

それが数字を含んでいたとしても、文字列になってしまうので、気を付けてください。

+ +
let myNumber = '500'; // oops, this is still a string
+typeof myNumber;
+myNumber = 500; // much better — now this is a number
+typeof myNumber;
+ +

上の 4行をコンソールに一つづつ入力して、結果を見てみてください。typeof という演算子に気づきましたか?これは渡した変数のその時点でのデータ型を返します。最初に使用したとき、myNumber には '500' という文字列が入っているため、string と返ってきます。2 回目に呼んだときに何が返ってくるかを見てみましょう。

+ +

JavaScript の定数

+ +

多くのプログラミング言語は定数の概念を持っています — 一度宣言されると変更できない値です。セキュリティ (サードパーティのスクリプトによってこのような値が変更された場合に問題が発生する可能性がある) からデバッグやコードの理解 (変更してはいけない値を誤って変更して混乱する) まで、実行するさまざまな理由があります。

+ +

JavaScript の初期の頃は、定数は存在しませんでした。現代の JavaScript では、const というキーワードがあります。これにより、絶対に変更できない値を格納できます。

+ +
const daysInWeek = 7;
+const hoursInDay = 24;
+ +

constlet と全く同じように動作しますが、const に新しい値を与えることはできません。次の例では、2行目でエラーが発生します。

+ +
const daysInWeek = 7;
+daysInWeek = 8;
+ +

スキルをテストしよう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?移動する前に、情報を取得したかのテストを見ることができます — Test your skills: variables を見てください。

+ +

まとめ

+ +

ここまでで JavaScript の変数の作り方について理解して、それ以外にもそれなりの知識を得ましたね。次の記事では、数値に焦点を当てて、JavaScript の数値計算の基礎について見ていきます。

+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/first_steps/what_is_javascript/index.html b/files/ja/learn/javascript/first_steps/what_is_javascript/index.html new file mode 100644 index 0000000000..4dc00a10e4 --- /dev/null +++ b/files/ja/learn/javascript/first_steps/what_is_javascript/index.html @@ -0,0 +1,434 @@ +--- +title: JavaScript とは +slug: Learn/JavaScript/First_steps/What_is_JavaScript +tags: + - 3rd party + - API + - Article + - Beginner + - Browser + - CodingScripting + - Core + - JavaScript + - Learn + - Script + - comments + - external + - inline + - 'l10n:priority' + - what +translation_of: Learn/JavaScript/First_steps/What_is_JavaScript +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}
+ +

MDN 初心者向け JavaScript コースへようこそ! この最初の記事では、高水準から JavaScript を見ていき、「JavaScript とは何か?」「これを使うと何ができるか?」などの質問に答えます。JavaScript の用途にきっちりと親しめるようになります。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターリテラシー、HTML および CSS の基本的な理解。
到達目標:JavaScript とは何か、何ができるか、どのようにウェブサイトに適用できるかについて親しむ。
+ +

高水準の定義

+ +

JavaScript はウェブページにて複雑な機能をできるようにするプログラミング言語です —ウェブページが読み込まれるたびに、単にあなたが見ている静的な情報を表示する以上のことをしています— 更新されたコンテンツの定期表示や、インタラクティブな地図や、2D/3D グラフィックのアニメーションや、ビデオジュークボックスのスクロールなど — たぶん JavaScript が組み込まれています。ウェブ技術をケーキだとするとこれは 3 つ目の層で、他の 2 つ (HTMLCSS) は学習エリアの他の部分でもっと詳しく扱ってきました。

+ +

+ + + +

この 3 層は素晴らしい構成です。例としてシンプルなテキストラベルを見てみます。HTML を使って構造と意図をマークアップできます:

+ +
<p>Player 1: Chris</p>
+ +

+ +

次に、CSS を加えて、見栄えをよくします:

+ +
p {
+  font-family: 'helvetica neue', helvetica, sans-serif;
+  letter-spacing: 1px;
+  text-transform: uppercase;
+  text-align: center;
+  border: 2px solid rgba(0,0,200,0.6);
+  background: rgba(0,0,200,0.3);
+  color: rgba(0,0,200,0.6);
+  box-shadow: 1px 1px 2px rgba(0,0,200,0.4);
+  border-radius: 10px;
+  padding: 3px 10px;
+  display: inline-block;
+  cursor: pointer;
+}
+ +

+ +

最後に、JavaScript を加えて動的なふるまいを実装します:

+ +
const para = document.querySelector('p');
+
+para.addEventListener('click', updateName);
+
+function updateName() {
+  let name = prompt('名前を入力して下さい');
+  para.textContent = 'Player 1: ' + name;
+}
+
+ +

{{ EmbedLiveSample('A_high-level_definition', '100%', 80, "", "", "hide-codepen-jsfiddle") }}

+ +

テキストラベルの最新バージョンをクリックしてみて、何が起きるのか見てみます (このデモは GitHub でも見られます— ソースコードまたはライブ実行を参照してください)。

+ +

JavaScript はそれ以上のことができます — もっと詳しく見てみましょう。

+ +

実際に何ができるのか

+ +

JavaScript は次のことを実現する一般的なプログラミング機能で構成されています。

+ + + +

さらにワクワクするのは、JavaScript からすぐに使えるように構築されている機能です。それは Application Programming Interface (API) と呼ばれ、JavaScript のコードにさらなる強力な力を与えてくれることでしょう。

+ +

API がなければ難しかったり、不可能であるようなコードを、すぐに使えるブロックのように、開発者がプログラムを作ることを可能にします。家を作るときの既製の家具と同じことを、プログラミングでしてくれるのです。自分で設計し、使用する木材を選定し、正しい形で板を切り出して、正しいサイズのネジを見つけて、自分で組み立てるよりも、既に切り出されたボードとネジを使って本棚を組み立てるだけの方がずっと簡単ですよね。

+ +

API は大まかに 2種類に分けられます。

+ +

+ +

ブラウザー API はウェブブラウザーに組み込まれていて、コンピューターを取り巻く環境からデータを取り出したり、複雑で便利なことをしてくれたりします。例えば、

+ + + +
+

: 上記の多くは古いブラウザーでは動作しません。試すには Firefox、Chrome、Edge、Opera といったモダンなブラウザーを使うのがよいでしょう。プロダクションコードを提供する (顧客に実際のコードを納品する) 段になったら、クロスブラウザーテストを読んでみるとよいでしょう。

+
+ +

サードパーティ API はブラウザーには組み込まれておらず、さらに普通はウェブ上のどこかからそのコードと情報を探さなければなりません。例えば、

+ + + +
+

: このような API は先進的ですが、このモジュールでは扱いません。詳しく知りたければ Client-side web APIs module で扱っています。

+
+ +

ワクワクすることはもっとたくさんあります! ですが、まだ興奮しすぎないでください。24 時間程度の勉強だけでは、Facebook や Google マップや Instagram は作れません。まずはやらなければならない基本がたくさんあるのです。さあ、先に進みましょう!

+ +

JavaScript は何をするのか

+ +

まずは実際にコードを見てみましょう。そしてページで JavaScript を動かすと何が起きるのか見てみましょう。

+ +

ブラウザーをウェブページに読み込んだときの話を簡単に説明します (How CSS works の記事で最初に出てきました)。ウェブページをブラウザーで見たとき、実行環境 (ブラウザーのタブ) の中で、コード (HTML、CSS そして JavaScript) が実行されます。これは素材 (コード) を加工して製品 (ウェブページ) を出力する工場のようなものです。

+ +

+ +

JavaScript のごく一般的な用途は、(先ほど例示した) Document Object Model API を介して動的に HTML と CSS を変更し、ユーザーインターフェイスを更新することです。なお、ウェブドキュメント上のコードは通常、ページ上に現れる順序で読み込まれて実行されます。もし JavaScript がロードされ、影響を受ける HTML および CSS がロードされる前に実行しようとすると、エラーが発生する可能性があります。この回避策については、記事の後半の「スクリプトの読み込み方針」セクションで学習します。

+ +

ブラウザーのセキュリティ

+ +

ブラウザーのそれぞれのタブは、コードを実行するための入れ物を個別に持ちます (この入れ物を技術的用語では「実行環境」と呼びます)。つまり、それぞれのタブ内でコードは完全に分かれて実行されており、あるタブで動いているコードは他のタブや他のウェブサイトのコードに、直接的には干渉できません。これは良いセキュリティ対策です。互いに干渉することが出来てしまえば、ウェブの悪党たちは、他のタブで開いているウェブサイトから情報を盗み出したり、もっとひどいことをするためにコードを書き始めることでしょう。

+ +
+

: 他のウェブサイトや、タブに安全にデータや実行可能なコードを送る方法はあります。けれども、このコースでは扱わない高度な技術です。

+
+ +

JavaScript の実行順序

+ +

ブラウザーが JavaScript のブロックを見つけたとき、たいていは先頭から最後に向かって順番に実行されます。つまりどの順番で実行されるかということに気を配らなければなりません。例えば、最初の例で見た JavaScript のブロックに戻りましょう。

+ +
const para = document.querySelector('p');
+
+para.addEventListener('click', updateName);
+
+function updateName() {
+  let name = prompt('名前を入力して下さい');
+  para.textContent = 'Player 1: ' + name;
+}
+ +

このコードでは文章段落を選択して (1 行目)、イベントリスナーを登録して (3 行目) 段落がクリックされたとき、updateName() というコードブロック (5 行目から 8 行目) が実行されるようにしています。updateName() というコードブロック (再利用可能なコードブロックで「関数」と呼びます) は、ユーザーに新しい名前を尋ねて、表示内容を変更するため、段落にその名前を挿入します。

+ +

もし、最初の 2行を入れ替えた場合、動かなくなってしまいます。代わりにブラウザーの開発者コンソールTypeError: para is undefined というエラーが出るでしょう。この意味は para オブジェクトがまだ存在しないため、イベントリスナーを設定できないということを表しています。

+ +
+

: これはとてもよくあるエラーです。オブジェクトに対して何かをする前にはそのオブジェクトへの参照が存在していることに気を配らなければなりません。

+
+ +

インタープリターとコンパイルコード

+ +

もしかしたら、インタープリターコンパイルという用語をプログラミングの文脈で聞いたことがあるかもしれませんね。インタープリターでは、コードが上から下に実行されてコードの実行結果がすぐに返ってきます。ブラウザーが実行する前にコードを何らかの形に変換する必要はありません。コードはプログラマーに親しみやすいテキストで受け取って、それから直接処理されます。

+ +

反対に、コンパイル言語はコンピューターで実行する前に他の形式に変換 (コンパイル) しなければなりません。例えば C/C++ は機械語にコンパイルされてから、コンピューターで実行されます。プログラムは、元のプログラムソースコードから生成されるバイナリーフォーマットで実行されます。

+ +

JavaScript は軽量なインタープリター型プログラミング言語です。ウェブブラウザーは元のテキストの形で JavaScript コードを受け取り、それからスクリプトを実行します。技術的な見地からは、たいていの JavaScript インタープリターは just-in-time compiling というテクニックを使ってパフォーマンスを向上させています; スクリプトが使われるときに、JavaScript コードが速いバイナリーフォーマットにコンパイルされて、可能な限り高速に実行されます。しかし、JavaScript は、事前ではなく実行時にコンパイルされるために、インタープリター言語と考えられています。

+ +

ここで詳細は話しませんが、どちらの方式も長所と短所があります。

+ +

サーバーサイドコードとクライアントサイドコード

+ +

サーバーサイドクライアントサイドという言葉も聞いたことがあるかもしれません。特にウェブ開発でよく聞かれます。クライアントサイドコードはユーザーのコンピューター上で実行されるコードです。ウェブページを見ているとき、ページのクライアントサイドコードがダウンロードされて、ブラウザーで実行されて表示されます。この JavaScript モジュールのことを明示的にクライアントサイド JavaScript と言います。

+ +

反対に、サーバーサイドコードはサーバー上で実行され、結果がブラウザーにダウンロードされて表示されます。ウェブで人気のあるサーバーサイドの言語は、PHP、Python、Ruby や ASP.NET など。そして JavaScript です! JavaScript はサーバーサイドの言語としても使われます。人気のある Node.js 環境がその例です。サーバーサイドの JavaScript については Dynamic Websites – Server-side programming のトピックを見てください。

+ +

動的コードと静的コード

+ +

クライアントサイドの JavaScript と、サーバーサイドの言語を説明するのに動的という言葉を使います。これはウェブページやウェブアプリが必要に応じてコンテンツを生成し、異なる状況において異なる表示ができるという能力を指しています。サーバーサイドのコードは、データベースからデータを取得して動的にコンテンツを生成します。一方、クライアントサイドの JavaScript はクライアント上のブラウザーで HTML のテーブルを生成したり、そのテーブルにサーバーから指示を受け、データを追加したり、ウェブページ上でユーザーにテーブルを表示したりするなどして、動的にコンテンツを生成します。それぞれの文脈で、少し異なる意味合いではありますが、関連しています。そしてどちらの方式も (サーバーサイドもクライアントサイドも) たいていは同時に使用されます。

+ +

動的に更新されるコンテンツを含まないウェブページは静的と表現されます。静的なウェブページとは常に同じコンテンツを表示するページのことです。

+ +

ページに JavaScript を追加する方法

+ +

JavaScript は CSS と同じような方法で、HTML ページに適用することができます。CSS では {{htmlelement("link")}} 要素を使用することで外部のスタイルシートを適用することができ、また、{{htmlelement("style")}} 要素を使用することで HTML 内部に書かれたスタイルシートを適用することが出来ました。しかし、JavaScript で HTML に書く必要があるのは {{htmlelement("script")}} 要素だけです。どのように書くのか見てみましょう。

+ +

内部の JavaScript

+ +
    +
  1. まずは apply-javascript.html ファイルを自分のコンピューターにコピーします。どこか適当な場所に保存してください。
  2. +
  3. テキストエディターとウェブブラウザーでそのファイルを開いてください。クリックできるボタンが 1 つあるウェブページを作る HTML だということがわかりますね。
  4. +
  5. 次に、テキストエディターで </head> タグの直前に以下のコードを追加します。 +
    <script>
    +
    +  // JavaScript をここに書きます
    +
    +</script>
    +
  6. +
  7. それでは {{htmlelement("script")}} 要素内に JavaScript を書いて、もうちょっと面白いことをしてみましょう。「// JavaScript をここに書きます」と書いてあるすぐ下に、以下のコードを追加してください。 +
    document.addEventListener("DOMContentLoaded", function() {
    +  function createParagraph() {
    +    let para = document.createElement('p');
    +    para.textContent = 'ボタンが押されました!';
    +    document.body.appendChild(para);
    +  }
    +
    +  const buttons = document.querySelectorAll('button');
    +
    +  for(let i = 0; i < buttons.length ; i++) {
    +    buttons[i].addEventListener('click', createParagraph);
    +  }
    +});
    +
  8. +
  9. ファイルを保存してブラウザーを更新してください。ボタンを押す度に新しい段落が作られて、下に表示されるようになりましたね。
  10. +
+ +
+

: もし上記の例が上手く動いていないとしたら、もう一度最初から手順を確認してください。コピーしてコードを書いたファイルは .html というファイル名ですか? {{htmlelement("script")}} 要素を </head> タグの直前に追加しましたか? JavaScript を上の例の通りに書きましたか? JavaScript は大文字小文字を区別しますので、見えている通りに書かなければなりません。正しく書いていなければ、動いてくれません。文字化けしているなら、テキストエディターの文字エンコーディングの設定が UTF-8 になっていることを確認してください。

+
+ +
+

: GitHub にあるこちらのバージョン、apply-javascript-internal.html (動くバージョンもあります) を見ることもできます。

+
+ +

外部の JavaScript

+ +

これで JavaScript が動きましたね。しかし、JavaScript を外部のファイルに書きたいときはどうすればよいでしょうか? 次の例を見てみましょう。

+ +
    +
  1. まず、先ほどの HTML ファイルと同じディレクトリーに新しいファイルを作ります。これを script.js と名付けます。.js という拡張子であることを確認してください。それで JavaScript であると認識されるのです。
  2. +
  3. {{htmlelement("script")}} 要素を以下のコードで置き換えます。 +
    <script src="script.js" defer></script>
    +
  4. +
  5. script.js に、次のスクリプトを追加します。 +
    function createParagraph() {
    +  let para = document.createElement('p');
    +  para.textContent = 'ボタンが押されました!';
    +  document.body.appendChild(para);
    +}
    +
    +const buttons = document.querySelectorAll('button');
    +
    +for(let i = 0; i < buttons.length ; i++) {
    +  buttons[i].addEventListener('click', createParagraph);
    +}
    +
  6. +
  7. HTML ファイルを保存して、ブラウザーを更新してください。同じページが見えますね! 同じように動いていますが、今回は外部の JavaScript ファイルです。コードを整理して、複数の HTML ファイルから再利用できるようにするには、このようにするのが良いでしょう。大きなスクリプトの塊がないほうが、HTML も読みやすくなります。
  8. +
+ +
+

: GitHub でこちらのバージョンも見られます。apply-javascript-external.htmlscript.js です (動いているバージョンもあります)。

+
+ +

インラインの JavaScript ハンドラー

+ +

たまに JavaScript のコードが HTML の途中に書かれているのを見かけます。こんな感じで。

+ +
+
function createParagraph() {
+  let para = document.createElement('p');
+  para.textContent = 'ボタンが押されました!';
+  document.body.appendChild(para);
+}
+ +
<button onclick="createParagraph()">押してください</button>
+
+ +

このバージョンのデモを下のボタンを押して確認してください。

+ +

{{ EmbedLiveSample('inline_js_example', '100%', 150, "", "", "hide-codepen-jsfiddle") }}

+ +

このデモは先ほどのセクションのものと同じ機能を持っていますが、{{htmlelement("button")}} 要素に onclick 属性を付けてボタンが押されたときに関数が実行されるようにハンドラーを直接書いています。

+ +

書けはしますが、このようにはしないでください。この書き方は HTML を JavaScript で汚してしまう悪い書き方です。さらに、onclick="createParagraph()" という属性を JavaScript を適用したいボタンすべてに書かなければなりませんので、とても非効率です。

+ +

純粋な JavaScript では、1 つの命令ですべてのボタンが取得できます。先ほど使用した、すべてのボタンを取得するためのコードは以下の通りでした。

+ +
const buttons = document.querySelectorAll('button');
+
+for(let i = 0; i < buttons.length ; i++) {
+  buttons[i].addEventListener('click', createParagraph);
+}
+ +

これは onclick 属性を用いて書くより少し長いように見えますが、どれだけそのページにボタンを追加し、削除し、いくつあろうとも期待通りに動くでしょう。コードを変更することなく。

+ +
+

: 自分の apply-javascript.html ファイルを編集して、いくつかボタンを追加してみて下さい。再度読み込むとどのボタンを押しても段落が作られるのがわかるでしょう。素敵でしょ!

+
+ +

スクリプトの読み込み方針

+ +

スクリプトを適切なタイミングで読み込むためには、いくつかの問題があります。 それは見掛けほど簡単ではありません! 一般的な問題は、ページ上のすべての HTML が、現れた順に読み込まれることです。JavaScript を使用してページ上の要素(またはより正確には、Document Object Model)を操作している場合、何かをしようとする HTML の前に JavaScript が読み込まれ、解析されてもコードは機能しません。

+ +

上のコード例では、内部の例と外部の例は、HTML 本文が解析される前に JavaScript が読み込まれて文書の head で実行されています。これによりエラーが発生する可能性があるため、いくつかの構文を使用して回避しています。

+ +

内部の例では、コードの周りにこの構造を見ることができます。

+ +
document.addEventListener("DOMContentLoaded", function() {
+  ...
+});
+ +

これはブラウザーの "DOMContentLoaded" イベントをリッスンするイベントリスナーで、HTML body が完全に読み込まれて解析されたことを示します。このブロック内の JavaScript はそのイベントが発生するまで実行されないため、エラーは回避されます (コースの後半でイベントについて学習します) 。

+ +

外部の例では、より現代的な JavaScript 機能の defer 属性を使用して問題を解決し、<script> 要素に達した後も HTML コンテンツのダウンロードを続行するようブラウザーに指示します。

+ +
<script src="script.js" defer></script>
+ +

この場合、スクリプトと HTML の両方が同時に読み込まれ、コードが機能します。

+ +
+

: 外部のケースでは、defer 属性が問題を解決したため、DOMContentLoaded イベントを使用する必要はありませんでした。defer は外部スクリプトに対してのみ機能するため、内部の例では defer による解決策を使用しませんでした。

+
+ +

この問題に対する昔ながらの解決策は、すべての HTML が解析された後に読み込まれるように、body の下部に(たとえば </body> タグの直前に)script 要素を置くことでした。この解決策(および上記の DOMContentLoaded による解決策)の問題点は、HTML DOM が読み込まれるまでスクリプトの読み込みと解析が完全にブロックされることです。JavaScript がたくさんある大規模なサイトでは、これは大きなパフォーマンス上の問題を引き起こす可能性があり、サイトを遅くします。

+ +

async と defer

+ +

実際には、スクリプトのブロッキングの問題を回避できるモダンな機能が 2 つあります — asyncdefer(すでに見てきました)。これらの 2 つの違いを見てみましょう。

+ +

async 属性を使って読み込むスクリプトは(下記を見てください)、ページのレンダリングをブロックせずにスクリプトをダウンロードし、スクリプトのダウンロードが終了すると直ちに実行します。複数のスクリプトが特定の順序で実行されるという保証はありませんが、ページの残りの部分の表示を停止することはありません。ページ内のスクリプトが互いに独立して実行され、ページ上の他のスクリプトに依存しない場合は、async を使用することをお勧めします。

+ +

たとえば、次のスクリプト要素があるとします。

+ +
<script async src="js/vendor/jquery.js"></script>
+
+<script async src="js/script2.js"></script>
+
+<script async src="js/script3.js"></script>
+ +

スクリプトが読み込まれる順序に依存することはできません。jquery.jsscript2.jsscript3.js に前後して読み込まれます。この場合、jquery に依存するこれらのスクリプトの関数は、スクリプトの実行時に jquery が定義されないため、エラーを生成します。

+ +

読み込むバックグラウンドスクリプトがいくつもあって、それらをできるだけ早く実行したい場合に async を使用するべきです。例えば、ゲームを実際に開始するときに必要になるいくつかのロードすべきゲームデータファイルがあるとして、今のところは、スクリプトのロードによってブロックされずに、ゲームのイントロ、タイトル、ロビーを表示したいだけ、という場合です。

+ +

defer 属性つきのスクリプト(下記のようなもの)は、ページに現れた順序でスクリプトを実行し、スクリプトとコンテンツがダウンロードされるとすぐにスクリプトを実行します。

+ +
<script defer src="js/vendor/jquery.js"></script>
+
+<script defer src="js/script2.js"></script>
+
+<script defer src="js/script3.js"></script>
+ +

defer 属性を持つすべてのスクリプトは、ページに現れた順序で読み込まれます。したがって、2番目の例では、jquery.jsscript2.jsscript3.js の前に読み込まれ、script2.jsscript3.js の前に読み込まれることは確実です。ページコンテンツがすべて読み込まれるまでは、実行せず、これはスクリプトが DOM配置に依存している場合に便利です(例: ページの要素を変更する場合)

+ +

要約すると、

+ + + +

コメント

+ +

HTML や CSS と同様に、JavaScript でもコード内にブラウザーが実行しない「コメント」を書くことができます。仲間の開発者 (または、6 カ月後のコードを忘れた自分自身) に対して動作方法を書くことができます。コメントはとても便利ですしたくさん書きましょう。大きなプログラムを書くのならなおのことです。コメントの書き方は 2 種類あります。

+ + + +

先ほどのデモでコメントを書くならば、以下のようにします。

+ +
// 関数: HTML の body タグ内の一番下に新しい段落を追加します。
+
+function createParagraph() {
+  let para = document.createElement('p');
+  para.textContent = 'ボタンが押されました!';
+  document.body.appendChild(para);
+}
+
+/*
+  1. ページ内のボタンへの参照をすべて取り出して配列に入れる。
+  2. すべてのボタンをループで回し、クリックイベントのリスナーを追加する
+
+  どのボタンが押されても、createParagraph() 関数が実行されるようにする。
+*/
+
+const buttons = document.querySelectorAll('button');
+
+for (let i = 0; i < buttons.length ; i++) {
+  buttons[i].addEventListener('click', createParagraph);
+}
+ +
+

メモ: 一般的にコメントは多いほうが少ないよりも優れていますが、変数が何であるかを説明する (変数名はおそらくもっと直感的にするべきです) ため、または非常に単純な操作を説明する (コードが複雑すぎるかもしれません) ために、多くのコメントを追加する場合は注意が必要です。

+
+ +

まとめ

+ +

さて、JavaScript の世界に足を踏み入れましたね。なぜ JavaScript を使い、何ができるのかということに慣れるため、まずは理論から始めました。進むにつれ、少しでしたが例を見て、何よりも JavaScript がどのようにウェブサイトの他のコードに組み込まれているかを学習しました。

+ +

JavaScript が少し大変だと思いましたか。でも心配は無用です。このコースを受講することで一歩ずつ、理解しながら前に進んで行きましょう。次の記事で、まっすぐに飛び込んで自分で JavaScript のページを作って実践に飛び込んでいきましょう

+ +

{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/first_steps/what_went_wrong/index.html b/files/ja/learn/javascript/first_steps/what_went_wrong/index.html new file mode 100644 index 0000000000..accce26c15 --- /dev/null +++ b/files/ja/learn/javascript/first_steps/what_went_wrong/index.html @@ -0,0 +1,265 @@ +--- +title: 何が間違っている? JavaScript のトラブルシューティング +slug: Learn/JavaScript/First_steps/What_went_wrong +tags: + - Article + - Beginner + - CodingScripting + - Debugging + - Developer Tools + - Error + - JavaScript + - Learn + - Tutorial + - console.log + - 'l10n:priority' +translation_of: Learn/JavaScript/First_steps/What_went_wrong +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}
+ +

前の記事の「数字当てゲーム」を作っていて、動かないことはありませんでしたか?恐れることはありません。この記事では、そんな心配をしなくて済むように、JavaScript のエラーを見つけて直す方法を伝授します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、HTML および CSS の基本的な理解、JavaScript についての理解。
目的:コード内のシンプルな問題を修正し始める能力と自信を得る。
+ +

エラーの種類

+ +

コードに誤りがある場合、一般的に以下の 2 つのうち、どちらかの誤りであることがよくあります。

+ + + +

まあ、こんなに単純ではありません。もっと深く追及していくと違う種類のエラーも出てくることでしょう。しかし、見習いのうちは上の分類で十分です。上記2 つの種類のエラーについて見ていきましょう。

+ +

誤りの例

+ +

始めるにあたり、数字当て (今回は当たらない) ゲームに戻りましょう。わざとエラーになるバージョンを見ていきます。Github に行って number-game-errors.html をローカルにコピーしてください。(ライブ実行はこちらを見てください)

+ +
    +
  1. 始めるには、コピーしたファイルをお好みのテキストエディターとブラウザで開きます。
  2. +
  3. ゲームで遊んでみてください。気づきましたか。"予想を入力" ボタンを押しても動きません!
  4. +
+ +
+

: もしかしたら、あなたにも直したいと思っているバージョンがあるかもしれませんね。ですが、まずはこちらで用意したバージョンを直してみてください。そうすれば、ここで教えるテクニックが身につきます。それから、あなた自身のプログラムに戻って直してみてください。

+
+ +

それでは、開発者コンソールで文法エラーがあるか調べてみましょう。それからエラーを修正します。どうやって修正すればいいかは今から教えます。

+ +

文法エラーを修正する

+ +

以前に開発者ツールの JavaScript コンソールで、簡単なコマンドを入力してもらったことがあったと思います。(思い出せなければ、リンクを見て開き方を調べてください。) コンソールの何が便利かといえば、ブラウザの JavaScript エンジンに読み込ませようとしている JavaScript コードに文法エラーがあれば、すべて教えてくれるのです。さあ、バグを潰していきましょう。

+ +
    +
  1. number-game-errors.html ファイルを開いているタブを選択して、JavaScript コンソールを開いてください。以下のメッセージが表示されていますね。
  2. +
  3. これは分かりやすいエラーです。ブラウザからもいくつか情報が出ています。(上のスクリーンショットは FireFox のものですが、他のブラウザでも同様の情報が表示されるでしょう。) 左から順に説明します。 +
      +
    • 赤色の 「x」 ボタンはエラーがあることを示しています。
    • +
    • 「TypeError: guessSubmit.addeventListener is not a function」というエラーメッセージが、何が問題かを示しています。
    • +
    • 「Learn More」 のリンクがエラー内容についてもっと詳細に説明する MDN のページを指しています。
    • +
    • JavaScript のファイルの名前が出ています。このリンクをクリックすると、開発者ツールのデバッガータブで問題のあるファイルが開きます。ハイライトされているエラーの箇所が見えるでしょう。
    • +
    • エラーがある行の行番号と、最初の文字が始まる番号が出ています。上の例では 86行目の 3文字目です。
    • +
    +
  4. +
  5. テキストエディターで 86行目を見てみましょう。 +
    guessSubmit.addeventListener('click', checkGuess);
    +
  6. +
  7. エラーでは、"guessSubmit.addeventListener is not a function" とあり、これは JavaScript インタープリタに呼び出している関数が認識されないという意味です。しばしば、このエラーメッセージは、スペルミスをしたということです。もし正しい綴りがわからなければ、MDN のサイトで使用している機能を調べてみてください。きっと見つかります。いつもはお好みの検索エンジンで「mdn 機能の名前」と検索してみるのがよいでしょう。今回は代わりに addEventListener() のリンクを張っておきます。
  8. +
  9. ページによると、関数の名前を間違えたみたいですね!JavaScript は大文字・小文字を区別しますので、ちょっとでも違うとエラーの原因になることを覚えておきましょう。それでは addeventListener を addEventListener に修正してエラーを直しましょう。
  10. +
+ +
+

: TypeError: "x" is not a function のリファレンスページで、このエラーに関する詳細な説明が見られます。

+
+ +

文法エラーその 2

+ +
    +
  1. ファイルを保存してブラウザを更新すると、エラーが消えています。
  2. +
  3. 予想を入力して、予想を入力ボタンを押してみると、...別のエラーが起きています!
  4. +
  5. 今回のエラーを見ると、78行目で"TypeError: lowOrHi is null"が起きています。 +
    : Null は「何もない」ことや「値がない」ことを表す特別な値です。つまり lowOrHi が宣言されて初期化されているけれど、意味のある値ではない — つまり型も値もないということです。
    + +
    : このエラーは関数内部 (checkGuess() { ... } ブロックの中) で発生したため、ページを読み込んだだけでは出てきませんでした。後に続く関数の記事を読み進めていけば分かりますが、内側の関数のスコープは外側の関数のスコープとは異なります。今回のケースでは、86行目の checkGuess() 関数が実行されるまで実行されず、エラーも発生していませんでした。
    +
  6. +
  7. 78行目を見てください。以下のコードが書かれています。 +
    lowOrHi.textContent = '今の予想は大きすぎです!';
    +
  8. +
  9. この行は lowOrHi 定数の textContent プロパティに文字列を設定しようとしていますが、lowOrHi 定数に適切な値が設定されていないため上手く動きません。lowOrHi が使用されている箇所をコードのほかの部分から探してみましょう。最初に見つかるのは 48行目でしょう。 +
    const lowOrHi = document.querySelector('lowOrHi');
    +
  10. +
  11. ここでは、HTML の要素を参照する変数を作ろうとしています。この行の後ろで、値が null になっているか確認するため以下のコードを直後の 49行目に追加します。 +
    console.log(lowOrHi);
    + +
    +

    : console.log() は値をコンソールに出力する、デバッグするときにとても便利な関数です。これで 48行目で lowOrHi にセットしたはずの値がコンソールに出力されるでしょう。

    +
    +
  12. +
  13. ファイルを保存して再度ブラウザで読み込みます。そして console.log() の結果をコンソールで見てみましょう。 わかりましたね。lowOrHi の値は null でした。これで問題が 48行目にあることがわかりました。
  14. +
  15. それでは何が問題となり得るか考えてみましょう。48行目では要素への参照を CSS セレクタを使用して取得する document.querySelector() メソッドが使用されています。ファイルの少し上のほうにある、問題となる{{htmlelement("p")}} 要素を見てみましょう。 +
    <p class="lowOrHi"></p>
    +
  16. +
  17. ここではクラスセレクタが必要です。クラスセレクタはドット (.) で始まりますが、48行目で querySelector() メソッドに渡された文字列にはドットがありません。これが問題でしょう!48行目の lowOrHi を .lowOrHi に変更してみてください。
  18. +
  19. ファイルを保存して再度読み込むと、console.log() の文は求めていた <p> 要素を表示しています。何とか次のエラーを潰すことができました!console.log() の行は削除してもいいですし、後で使うために残しておいても大丈夫です。
  20. +
+ +
+

: TypeError: "x" is (not) "y"  のリファレンスページで、このエラーに関する詳細な説明が見られます。

+
+ +

文法エラーその 3

+ +
    +
  1. さて、もう一度ゲームをプレイしてみましょう。ゲームは問題なく動いているようです。正解するか、残りの予想回数がなくなって、ゲームが終わるまでは...。
  2. +
  3. ここで、またゲームが止まってしまいました。最初のエラーと同じく "TypeError: resetButton.addeventListener is not a function" というエラーです!しかし、今回は 94行目から発生していると表示されています。
  4. +
  5. 94行目を見ると、同じ間違いを犯したことがわかります。もう一度 addeventListener を .addEventListener に直してください。
  6. +
+ +

論理のエラー

+ +

今回はゲームは上手く動いているようです。しかし、何度か動かしていると、予想すべき「ランダムな」数字が常に 1 であることに気づくでしょう。これはあまりやりたくないゲームですね!

+ +

これはゲームのロジックに間違いなく問題があります。ゲームはエラーとはなっていませんが、正しく動いてはいません。

+ +
    +
  1. randomNumber 変数にランダムな数値が最初にセットされる場所を検索してみましょう。ゲームの開始で推測するランダムな数字を保存しようとしているのは 44行目のあたりです。 + +
    let randomNumber = Math.floor(Math.random()) + 1;
    + そして、それぞれのゲームの合間に次のランダムな数字を設定しているのは 113行目のあたりです。
  2. +
  3. +
    randomNumber = Math.floor(Math.random()) + 1;
    +
  4. +
  5. これらの行が問題となるかを確認するため、console.log() にもう一度登場してもらいましょう。先ほどのそれぞれの行の直下に以下のコードを追加します。 +
    console.log(randomNumber);
    +
  6. +
  7. 保存して再度読み込んで、何度かプレイしてみましょう。コンソールに出力される randomNumber の値が常に 1 であることに気づきます。
  8. +
+ +

ロジックを何とかする

+ +

これを直すには、この行が何をしているのか考えなければなりません。まず Math.random() を呼んでいます。これは 0 から 1 までのランダムな実数値を生成します。例えば 0.5675493843 などです。

+ +
Math.random()
+ +

次に Math.random() の実行結果を Math.floor() に渡して、一番近い整数に切り捨てています。そしてその結果に 1 を加えます。

+ +
Math.floor(Math.random()) + 1
+ +

0 から 1 のランダムな実数を切り捨てると、結果は常に 0 となり、それに 1 を加えることで常に 1 となります。ランダムな数を切り捨てる前に 100 を乗算しなければなりません。次のコードは 0 から 99 を返すでしょう。

+ +
Math.floor(Math.random()*100);
+ +

さらに 1 を加えることで、1 から 100 のランダムな数字を返してくれるようになります。

+ +
Math.floor(Math.random()*100) + 1;
+ +

先ほどの 2行をそれぞれ修正してください。保存して再度読み込むと、思い通りに動くようになっているでしょう!

+ +

その他のよくあるエラー

+ +

コードを書いていると、よくあるエラーは他にもあります。このセクションではそれらを紹介してみましょう。

+ +

SyntaxError: missing ; before statement

+ +

たいてい、このエラーはコード行のどこかの末尾にセミコロン (;) がないことを意味しています。しかし、時にはかなり難解です。例えば checkGuess() 関数内の、この行を

+ +
var userGuess = Number(guessField.value);
+ +

以下のように変更してみます。

+ +
var userGuess === Number(guessField.value);
+ +

そうすると、このエラーが吐かれます。違うことをやろうとしているように見えるのでしょう。値を変数にセットする代入演算子 (=) と、ある値が別の値と同じかどうかを判定して true または false を返す等値演算子 (===) を間違わないようにしてください。

+ +
+

: SyntaxError: missing ; before statement  のリファレンスページで、このエラーに関する詳細な説明が見られます。

+
+ +

プログラムが入力の内容に関わらずいつでも勝ちだと言ってくる

+ +

これは代入と比較を混同する別の症状でしょう。たとえば、checkGuess() 関数内の、この行を

+ +
if (userGuess === randomNumber) {
+ +

以下のように変更してみます。

+ +
if (userGuess = randomNumber) {
+ +

判定で常に true が返るようになり、常にプレイヤーが勝ったことになってしまいます。気を付けましょう!

+ +

SyntaxError: missing ) after argument list

+ +

これは単純です。大体は関数やメソッドの呼び出しで閉じ括弧を忘れたことを表しています。

+ +
+

: SyntaxError: missing ) after argument list のリファレンスページで、このエラーに関する詳細な説明が見られます。

+
+ +

SyntaxError: missing : after property id

+ +

たいてい、このエラーは JavaScript のオブジェクトの書き方が正しくないことに関連しているのですが、

+ +
function checkGuess() {
+ +

上記のコードを以下のように変えても起きるでしょう。

+ +
function checkGuess( {
+ +

この変更でブラウザは関数の内容を関数の引数として渡しているように勘違いしてしまいます。括弧には気を付けましょう!

+ +

SyntaxError: missing } after function body

+ +

これは簡単ですね。たいていの場合、関数や条件ブロックの終わりの閉じ波括弧が抜けていることを表します。checkGuess() 関数の最後の閉じ波括弧を消すと発生します。

+ +

SyntaxError: expected expression, got 'string' または SyntaxError: unterminated string literal

+ +

これらのエラーは文字列の始まりもしくは終わりのクォーテーションマークが抜けていることを表します。最初のエラーは、文字列の始めのクォーテーションマークの代わりに、ブラウザが予期しない文字列を見つけた (string には実際に見つけた文字列が入ります) ことを表し、2 つ目のエラーは文字列がクォーテーションマークで終わっていないことを表します。

+ +

どのエラーにも言えることですが、上の例でも見たように、考えてください。エラーが起きた時に、エラーが起きた行の番号をみて、その行にエラーがあるか見てみます。エラーはその行に存在しないこともありますし、上述した理由以外で起きることもあるということを心に留めておいてください。

+ +
+

: SyntaxError: Unexpected token と SyntaxError: unterminated string literal のリファレンスページで、これらエラーに関する詳細な説明が見られます。

+
+ +

まとめ

+ +

やっとここまで来ましたね。簡単な JavaScript プログラムのエラーを見つけ出すための基本が理解できました。コードの間違いを解決するのがいつも簡単とは限りませんが、特に学習の最初の過程では、うまくいかない時にも寝る時間を数時間節約し、多少早く進捗をあげられるでしょう。

+ +

あわせて参照

+ +
+ +
+ +

{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/javascript/howto/index.html b/files/ja/learn/javascript/howto/index.html new file mode 100644 index 0000000000..528ce80fe4 --- /dev/null +++ b/files/ja/learn/javascript/howto/index.html @@ -0,0 +1,302 @@ +--- +title: JavaScriptのコードのよくある問題を解決する +slug: Learn/JavaScript/Howto +tags: + - Beginner + - JavaScript + - Learn +translation_of: Learn/JavaScript/Howto +--- +
{{LearnSidebar}}
+ +

JavaScript のコードが正しく動作しないので修正したい、というような場合にみられる、よくある問題の解決方法へのリンクを以下に示します。

+ +

初学者がよく陥る誤り

+ +

スペル、大文字小文字を訂正する

+ +

コードが正しく動かない場合や、何かが未定義であるとブラウザーがエラーを出した場合、変数名や関数名のスペルが正しいか確認してください。

+ +

ブラウザーの組み込み関数についての正誤例:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
getElementsByTagName()getElementbyTagName()
getElementsByName()getElementByName()
getElementsByClassName()getElementByClassName()
getElementById()getElementsById()
+ +

セミコロンの位置

+ +

セミコロンの位置に誤りがないか確認してください。

+ +

例:

+ + + + + + + + + + + + +
elem.style.color = 'red';elem.style.color = 'red;'
+ +

関数

+ +

関数についての誤りは何点かあります。

+ +

よくある誤りの一つとして、関数を定義したがどこからも呼び出していない、というものがあります。

+ +

例:

+ +
function myFunction() {
+  alert('This is my function.');
+};
+ +

上記のコードで定義した関数は、例えば以下のように呼び出さないかぎり何もしません。

+ +
myFunction();
+ +

関数のスコープ

+ +

関数は関数自身のスコープを持ちます。変数をグローバルに(関数の外で)定義するか、戻り値として変数の値を関数の外に返さないかぎり、関数の外から関数の中で定義された変数にアクセスすることはできません。

+ +

return 文の後ろのコードの実行

+ +

return文で関数から値を返したとき、JavaScript のインタプリタはその関数を終了します。return文の後ろのコードは実行されません。

+ +

Firefox などのいくつかのブラウザーは、return文の後ろにコードが存在する場合、開発者ツールのコンソールにエラーメッセージを出力します。Firefox が出力するメッセージは "unreachable code after return statement" です。

+ +

オブジェクトリテラル記法 vs 代入

+ +

通常、JavaScript で代入する場合、等号を使います。

+ +

例:

+ +
var myNumber = 0;
+ +

オブジェクトの場合は、メンバー名とその値をコロンで区切り、メンバー間をカンマで区切る必要があります。

+ +

例:

+ +
var myObject = {
+  name : 'Chris',
+  age : 38
+}
+ +

基本的な定義

+ +
+ + + +
+ +

初級のユースケース

+ +
+ + +
+

配列

+ + + +

JavaScript のデバッグ

+ + + +

JavaScript のデバッグに関する詳細については、JavaScript のよくある問題を扱うを参照してください。よくあるエラーの説明についてはその他のよくあるエラーを参照してください。

+ +

コード内での決定

+ + + +

ループ/イテレーション

+ + +
+
+ +

中級のユースケース

+ +
+ + + +
diff --git a/files/ja/learn/javascript/index.html b/files/ja/learn/javascript/index.html new file mode 100644 index 0000000000..eee3009b7a --- /dev/null +++ b/files/ja/learn/javascript/index.html @@ -0,0 +1,93 @@ +--- +title: JavaScript +slug: Learn/JavaScript +tags: + - CodingScripting + - JavaScript + - JavaScripting beginner + - Landing + - Module + - Topic + - 'l10n:priority' + - 初心者 +translation_of: Learn/JavaScript +--- +
{{LearnSidebar}}
+ +

{{Glossary("JavaScript")}} はウェブページ上に複雑なものを実装することを可能にするプログラミング言語です。ウェブページが表示されるたびに静的な情報が表示されるだけでなく、タイムリーにコンテンツを更新したり、インタラクティブマップや 2D/3D グラフィックスのアニメーションを表示したり、またはビデオジュークボックスが流れたりします。ほかにもありますが、これらは 間違いなく JavaScript が関係しています。

+ +
+

フロントエンドの Web 開発者になりたいですか?

+ +

目標に向かって頑張るために必要な情報をまとめたコースをご用意しました。

+ +

Get started

+
+ +

学習の道筋

+ +

JavaScript は HTML や CSS などの関連技術よりもきっと学ぶのが難しいでしょう。JavaScript を習得する前に、まずこれらの 2 つの技術、そしておそらく他の技術を熟知しておくことを強くおすすめします。先ず次のモジュールを実施してください :

+ + + +

以前の他の言語での経験は手助けになるでしょう。

+ +

JavaScript の基本をよく理解できたら、より高度なトピックについて学ぶことができることでしょう。高度なトピックは例えば次のものです:

+ + + +

モジュール

+ +

このトピックでは次のモジュールが含まれます。これらは推奨順です。

+ +
+
JavaScript の第一歩
+
最初の JavaScript の項目では、まず JavaScript を書く初めての実践的な体験に進む前に、「 JavaScript とは何か」、「どのように見えるか」、「何ができるのか?」などの基本的な質問に答えます。その後、変数、文字列、数値、配列などの JavaScript の主要機能について詳しく説明します。
+
JavaScript の構成要素
+
このモジュールでは、条件文、ループ、関数、イベントなど一般的に発生するコードブロックの種類に注目し、JavaScript の重要な基本機能をすべてカバーしていきます。これまでにみたか、どこかで目にしたことでしょうが、ここではすべて明示的に説明を行います。
+
JavaScript オブジェクトの紹介
+
JavaScript では、文字列や配列などの JavaScript のコア機能から、JavaScript の上に構築されたブラウザー API まで、ほとんどのものがオブジェクトです。 関連する関数や変数を効率的なパッケージにカプセル化して独自のオブジェクトを作成することもできます。 JavaScript のオブジェクト指向の性質は、言語に関する知識をさらに深め、より効率的なコードを書く場合に理解するために重要です。それゆえ、このモジュールを用意しました。 ここではオブジェクトの理論と構文を詳しく説明し、独自のオブジェクトを作成する方法を見て、JSON のデータとその使い方を説明します。
+
非同期 JavaScript
+
+

このモジュールでは、非同期の JavaScript を見ていき、これがなぜ重要であるかや、サーバーからのリソース取得といった、ブロッキングの可能性のある操作を効率的に扱う方法を見ていきます。

+
+
クライアントサイドの Web API
+
ウェブサイトやアプリケーション用のクライアントサイド JavaScript を記述するときは、API を使い始める前に、サイトが実行されているブラウザーやオペレーティングシステムのさまざまな側面、または他のウェブサイトやサービスのデータを操作するためのインターフェイスといったものがあるので、すぐには進みません。このモジュールでは、API が何であるか、開発作業で頻繁に出くわす最も一般的な API を使用する方法について説明します。
+
+ +

よくある JavaScript の問題を解決する

+ +

よくある JavaScript の問題を解決する では、ウェブページの作成時に、とてもよくある問題を解決するために JavaScript を使用する方法を説明するコンテンツのセクションへのリンクを提供します。

+ +

関連情報

+ +
+
MDN の JavaScript
+
+
+
+
MDN の主要な JavaScript ドキュメントの主要なエントリポイントです。ここでは、JavaScript 言語のあらゆる側面に関する広範なリファレンスドキュメント、および経験豊富な JavaScripter を対象とした高度なチュートリアルがあります。
+
+
+
+
+ +
+
JavaScript の学習
+
ウェブ開発者になりたい人向けのすばらしいリソース — JavaScript をインタラクティブな環境と、短いレッスンやインタラクティブなテスト、自動化された評価つきで学ぶことができる。最初の 40 レッスンは無料で、完全なコースは少額の支払いで利用できる。
+
+ +

JavaScript Fundamentals on EXLskills

+ +
+
JS でアプリケーションを構築するために必要なすべてを紹介する EXLskills オープンソースコースで、無料で JavaScript を学んでください。
+
Coding math
+
Keith Peters による、有能なプログラマーを理解するのに必要な数学の優れたビデオチュートリアルのシリーズ。
+
diff --git a/files/ja/learn/javascript/objects/adding_bouncing_balls_features/index.html b/files/ja/learn/javascript/objects/adding_bouncing_balls_features/index.html new file mode 100644 index 0000000000..8390797c5b --- /dev/null +++ b/files/ja/learn/javascript/objects/adding_bouncing_balls_features/index.html @@ -0,0 +1,223 @@ +--- +title: バウンスボールに機能を追加する +slug: Learn/JavaScript/Objects/Adding_bouncing_balls_features +tags: + - Assessment + - Beginner + - CodingScripting + - JavaScript + - Learn + - OOJS + - Object-Oriented + - Objects + - 'l10n:priority' +translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}
+ +

この評価では、前の記事のバウンスボールのデモを出発点として用い、いくつかの面白い機能を新たに追加してもらいます。

+ + + + + + + + + + + + +
前提条件:この評価を試みる前に、このモジュールのすべての記事を学習済みであること。
+

目的:

+
JavaScript オブジェクトとオブジェクト指向のインスタンス生成を理解しているかテストする。
+ +

出発点

+ +

この評価をスタートするためには、私たちの最新記事からローカル PC の新しいディレクトリーに index-finished.htmstyle.cssmain-finshed.js をコピーします。

+ +

または、あなたの評価のために、JSBinGlitch を使うことができます。これらのオンラインエディターに HTML、CSS や JavaScript を貼り付けることができます。もしあなたが使用しているオンラインエディタが、別々の JavaScript/CSS のパネルを持っていない場合は、HTML内の <script>/<style> 要素を使って、インラインで書くことができます。

+ +
+

: もし行き詰った場合は、サポートを依頼してください。このページの下部にある{{anch("Assessment or further help", "評価とさらなる支援")}}セクションを参照してください。

+
+ +

ヒントと tips

+ +

始める前にいくつかの助言です。

+ + + +

プロジェクト概要

+ +

このバウンスボールのデモは面白いですが、ここではもう少しインタラクティブにするため、バウンスボールを捕まえたら食べてしまう、ユーザー制御された邪悪な円を追加します。また、バウンスボールや邪悪な円が継承できる一般的な Shape() オブジェクトを作ることで、あなたのオブジェクト構築スキルも試してみましょう。最後に、残ったボールが数えられるスコアカウンターも追加してみましょう。

+ +

次のスクリーンショットでは、完成したプログラムがどのように見えるかのイメージを掴めるでしょう: 

+ +

+ + + +

さらにヒントを差し上げます。完成デモを見てみましょう。(ソースコードをチラ見しないように!)

+ +

完成までの手順

+ +

次のセクションでは、必要な操作について説明します。

+ +

新しいオブジェクトを作る

+ +

まず初めに、既存の Ball() コンストラクターを Shape() コンストラクターに変更し、新しい Ball() コンストラクターを追加します:

+ +
    +
  1. Shape() コンストラクターは、xyvelX、および、velY プロパティを、Ball() コンストラクターが最初に行ったのと同じ方法で定義する必要がありますが、色とサイズのプロパティは指定しません。
  2. +
  3. また、新しいプロパティとして、ボールが存在するか(邪悪な円に食べられていないか)どうかを追跡するために使用される exists を新しく定義する必要があります。これはブール値 (true/false) である必要があります。
  4. +
  5. Ball() コンストラクターは、xyvelXvelY、および exists プロパティを Shape() コンストラクターから継承する必要があります。
  6. +
  7. また、元の Ball() コンストラクターのように、colorsize プロパティを定義する必要があります。
  8. +
  9. Ball() コンストラクターの prototypeconstructor を適切に設定してください。
  10. +
+ +

ボールの draw()update()、と collisionDetect() メソッドの定義は、前とまったく同じである必要があります。

+ +

また、new Ball() ( ... ) コンストラクターの呼び出しに新しいパラメーターを追加する必要があります。exists パラメーターは 5番目のパラメーターにする必要があり、true の値を指定する必要があります。

+ +

この時点で、コードをリロードしてみてください。再設計されたオブジェクトで、前と全く同じように動作するはずです。

+ +

EvilCircle() の定義

+ +

さあ、悪者 EvilCircle() の出番です! 私たちのゲームに邪悪な円は1つしか登場しませんが、練習のためにあえて、Shape() から継承するコンストラクターを使用して定義します。後で、他のプレイヤーによって制御される円、あるいは、コンピューター制御の別の邪悪な円をいくつか加えたいと思うかもしれません。おそらく、あなたは単一の邪悪な円の世界を引き継いでいくつもりはないでしょうが、今回の評価のためにはこれで十分です。

+ +

EvilCircle() コンストラクターは、x, y, velX, velYexistsShape() から継承しますが、velXvelY は常に20です。

+ +

これは Shape.call(this, x, y, 20, 20, exists);のように呼び出します。

+ +

次のように、独自のプロパティも定義する必要があります:

+ + + +

ここでも、継承したプロパティをコンストラクターのパラメーターとして定義し、prototypeconstractor のプロパティを正しく設定することを忘れないでください。

+ +

EvilCircle() のメソッドの定義

+ +

EvilCircle() には、以下に示す 4 つのメソッドがあります。

+ +

draw()

+ +

このメソッドは、Ball()draw() メソッドと同じく、キャンバス上にオブジェクトインスタンスを描画するという目的を持ちます。とても良く似た動作をするので、Ball.prototype.draw の定義をコピーすることから始めます。次に、以下の変更を行います。

+ + + +

checkBounds()

+ +

このメソッドは、Ball()update() 関数の最初の部分と同じ機能、すなわち、邪悪な円が画面の端から出そうになったら出ないようにする機能を持ちます。先ほどと同様に、Ball.prototype.update 定義をほぼコピーするだけでできますが、いくつか変更する必要があります。

+ + + +

setControls()

+ +

このメソッドは、onkeydown イベントリスナーを window オブジェクトに追加し、特定のキーボードキーが押されたときに、邪悪な円を動かします。次のコードブロックは、メソッド定義の中に置く必要があります。

+ +
let _this = this;
+window.onkeydown = function(e) {
+    if (e.key === 'a') {
+      _this.x -= _this.velX;
+    } else if (e.key === 'd') {
+      _this.x += _this.velX;
+    } else if (e.key === 'w') {
+      _this.y -= _this.velY;
+    } else if (e.key === 's') {
+      _this.y += _this.velY;
+    }
+  }
+ +

キーが押されると、イベントオブジェクトの key プロパティを調べて、どのキーが押されているかを確認します。押されたキーが、指定された4つのキーの 1 つである場合、邪悪な円は左/右/上/下に移動します。

+ +

おまけとして、let _this = this;をこの場所で設定しなければならない理由を教えてください。関数スコープと関係があります。

+ +

collisionDetect()

+ +

このメソッドは Ball()collisionDetect()メソッドと非常によく似た方法で動作するので、そのコピーをこの新しいメソッドの基礎として使用することができます。しかし、いくつかの違いがあります。

+ + + +

プログラムに邪悪な円を持ち込む

+ +

さて、邪悪な円を定義したので、実際にそれをシーンに表示させる必要があります。そのためには、loop() 関数をいくつか変更する必要があります。

+ + + +

スコアカウンターの実装

+ +

スコアカウンターを実装するには、次の手順に従います。

+ +
    +
  1. HTML ファイルの{{HTMLElement("h1")}}要素の直下に、"Ball count:" というテキストを含む{{HTMLElement( "p")}}要素を追加します。
  2. +
  3. あなたの CSS ファイルに、次のスタイルを追加します: +
    p {
    +  position: absolute;
    +  margin: 0;
    +  top: 35px;
    +  right: 5px;
    +  color: #aaa;
    +}
    +
  4. +
  5. JavaScript では、次の更新を行います: +
      +
    • 段落への参照を格納する変数を作成します。
    • +
    • 何らかの方法で画面上のボールの数をカウントしてください。
    • +
    • ボールをシーンに追加するたびにカウントを増加させ、更新されたボールの数を表示します。
    • +
    • 邪悪な円がボールを食べる(存在を消す)たびにカウントを減らし、更新されたボールの数を表示します。
    • +
    +
  6. +
+ +

評価とさらなる支援

+ +

If you would like your work assessed, or are stuck and want to ask for help:

+ +
    +
  1. Put your work into an online shareable editor such as CodePen, jsFiddle, or Glitch.
  2. +
  3. Write a post asking for assessment and/or help at the MDN Discourse forum Learning category. Your post should include: +
      +
    • A descriptive title such as "Assessment wanted for Adding bouncing balls features".
    • +
    • Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.
    • +
    • A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.
    • +
    • A link to the actual task or assessment page, so we can find the question you want help with.
    • +
    +
  4. +
+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/basics/index.html b/files/ja/learn/javascript/objects/basics/index.html new file mode 100644 index 0000000000..0c97e391d3 --- /dev/null +++ b/files/ja/learn/javascript/objects/basics/index.html @@ -0,0 +1,277 @@ +--- +title: JavaScript オブジェクトの基本 +slug: Learn/JavaScript/Objects/Basics +tags: + - API + - Article + - Beginner + - CodingScripting + - JavaScript + - Syntax + - bracket notation + - dot notation + - instance + - object literal + - this + - オブジェクト + - 学習 + - 理論 +translation_of: Learn/JavaScript/Objects/Basics +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}
+ +

この記事では、基本的な JavaScript オブジェクトの構文を学び、このコースで以前に見た一部の JavaScript の機能を復習し、すでに提供された多くの機能がオブジェクトであるという事実を再確認します。

+ + + + + + + + + + + + +
前提知識:基本的なコンピューターを操作する能力、基本的な HTML と CSS に対する理解、基本的な JavaScript に親しんでいること(JavaScript の第一歩JavaScript の構成要素を参照してください)。
到達目標:オブジェクト指向プログラミングについての基本的な理論、どのように JavaScript に関連するか、JavaScript の作業を始める方法を理解できること。
+ +

オブジェクトの基本

+ +

オブジェクトとは関連のあるデータと機能の集合です。(機能はたいていは変数と関数で構成されており、オブジェクトの中ではそれぞれプロパティとメソッドと呼ばれます。) どんなものか例を見てみましょう。

+ +

最初に oojs.html ファイルを手元にコピーしてください。このファイルにはちょっとした内容 — ソースコードを書き込むための {{HTMLElement("script")}} 要素が一つ含まれています。このファイルをオブジェクトを書くための元として使います。作業中は開発者ツールの JavaScript コンソールを開いておいて、すぐにコマンドを入力できるようにしておくとよいでしょう。

+ +

他の JavaScript の書き方と同じように、オブジェクトの生成は変数の宣言と初期化から始まります。手始めに、ファイルにある JavaScript コードの下に次のものを書いてみてください。それから保存して再読み込みしましょう。

+ +
const person = {};
+ +

ブラウザの JavaScript コンソールを開いて、person と入力して、 Enter/Return を押してください。以下のいずれかの行に似た結果が得られるはずです。

+ +
[object Object]
+Object { }
+{ }
+ +

よくやりましたね! まずは最初のオブジェクトができました。でもこれだけでは空のオブジェクトであまり役には立ちません。さらにオブジェクトを変更してみましょう。

+ +
const person = {
+  name: ['Bob', 'Smith'],
+  age: 32,
+  gender: 'male',
+  interests: ['music', 'skiing'],
+  bio: function() {
+    alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
+  },
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name[0] + '.');
+  }
+};
+
+ +

保存して再読み込みした後で、JavaScript コンソールにいくつか入力してみましょう。

+ +
person.name
+person.name[0]
+person.age
+person.interests[1]
+person.bio()
+person.greeting()
+ +

オブジェクトから、データと機能を追加することができました。これで簡単な書き方で情報が引き出せます。

+ +
+

: もし動かないようなら、完成版のソースコードと見比べてみてください (完成版: oojs-finished.html さらにライブ版もあります) 。ライブ版は空白の画面ですが、それで OK です。また開発ツールを開いて上記のコマンドを入力してオブジェクトの構造を見てみます。

+
+ +

さて、何が起きているのでしょうか。オブジェクトには複数のメンバーがあり、それぞれに名前がついていて(例えば上の例では nameage)、それぞれに値 (['Bob', 'Smith'] や 32) があります。それぞれの名前と値の組はカンマ ( , ) で区切られていて、名前と値はコロン ( : ) で区切られています。常にそのように書きます。

+ +
const objectName = {
+  member1Name: member1Value,
+  member2Name: member2Value,
+  member3Name: member3Value
+}
+ +

メンバーの値はほとんど何でも大丈夫です。例えば、先ほどの例では文字列、数値、2 つの配列に 2 つの関数でした。最初の 4 つはデータ項目でそのオブジェクトのプロパティと呼ばれます。後ろの 2 つはオブジェクトの持つデータを使用して何かをする関数でオブジェクトのメソッドと呼ばれます。

+ +

このように記号を使って書くオブジェクトは後で出てくるクラスを使用して生成する方法と対比してオブジェクトリテラルと呼ばます。

+ +

オブジェクトリテラルを使用してオブジェクトを生成する方法はとても一般的で、ある法則に則って構造化、関連付けられたデータをやり取りするときによく使います。(例えばサーバーにリクエストを送ったり、データベースに保存したり。) ある一つのオブジェクトを送るほうが複数の項目を何回かに分けて送るよりも効率的で、名前を用いて検索するときなどには、配列よりも扱いやすいときがあります。

+ +

ドットによる記述

+ +

先ほどの例では、オブジェクトのプロパティとメソッドに対して、ドット記法を用いてアクセスしました 。オブジェクト名 (person) は名前空間として機能します。オブジェクト内にカプセル化されたものにアクセスするには、まずこのオブジェクト名を入力する必要があります。次に、ドット ( . ) を書いて、それからアクセスしたい項目を記述します。項目になりうるのは、単純なプロパティの名前や、配列の要素や、そのオブジェクトのメソッドの 1 つへの呼び出しなどです。次に例を示します:

+ +
person.age
+person.interests[1]
+person.bio()
+ +

サブ名前空間

+ +

オブジェクトの内部にさらにほかのオブジェクトを持つことも可能です。例えば、先の例で、name メンバーを、

+ +
name: ['Bob', 'Smith'],
+ +

以下のように変更してみましょう。

+ +
name : {
+  first: 'Bob',
+  last: 'Smith'
+},
+ +

これで簡単にサブ名前空間を作り出すことができました。難しそうに聞こえるかもしれませんが、ただ単に項目をドットを用いて数珠つなぎにつないでいけばいいのです。コンソールで試してください。

+ +
person.name.first
+person.name.last
+ +

重要: この時点で下の書き方をしていたところは、以下のように変えなければなりません。

+ +
name[0]
+name[1]
+ +

を、

+ +
name.first
+name.last
+ +

のようにしなければ、メソッドが動かなくなってしまうでしょう。

+ +

角括弧による記述

+ +

オブジェクトのプロパティにアクセスするもう一つの手段として角括弧を用いた記法があります。

+ +
person.age
+person.name.first
+ +

このように書く代わりに、

+ +
person['age']
+person['name']['first']
+ +

のように書きます。

+ +

これは配列の添え字によく似ています。数字の代わりに、名前を用いて関連付けられたメンバーの値にアクセスするだけで、実はほとんど同じなのです。このようなオブジェクトを連想配列といい、配列が数字によって値を格納しているように、文字列によって値を格納しています。

+ +

オブジェクトメンバーの設定

+ +

今まではオブジェクトメンバーからの引き出す (取得する) 方法だけを見てきましたが、値を設定するメンバーを宣言することで、オブジェクトのメンバーに値を設定 (更新) することもできます。(ドットを使用した書き方でも、角括弧を使用した書き方でも構いません。)

+ +
person.age = 45;
+person['name']['last'] = 'Cratchit';
+ +

これらの行を入力してみて、実際に値が変わったか調べてみましょう。

+ +
person.age
+person['name']['last']
+ +

メンバーの値を設定するのは存在するプロパティやメソッドの更新だけにはとどまりません。まったく新しいメンバーを追加することもできるのです。JS コンソールで次のものを試してみてください。

+ +
person['eyes'] = 'hazel';
+person.farewell = function() { alert("Bye everybody!"); }
+ +

新しいメンバーが追加されたことを確認してみましょう。

+ +
person['eyes']
+person.farewell()
+ +

角括弧での書き方の良いところは、動的にメンバーの値を設定できるだけでなく、メンバーの名前も追加できるところです。例えば、ユーザーの情報として 2 つのテキストフィールドに名前と値を入力してもらい、人により個別のデータを設定したいとします。そういった値を以下のように取得します。

+ +
let myDataName = nameInput.value;
+let myDataValue = nameValue.value;
+ +

そうして、取得したメンバー名と値を次のように person オブジェクトに設定します。

+ +
person[myDataName] = myDataValue;
+ +

この動作を確認するため、先ほどのコードの person オブジェクトの中括弧に続いて、次の行をコードに追加してみてください。

+ +
let myDataName = 'height';
+let myDataValue = '1.75m';
+person[myDataName] = myDataValue;
+ +

そして、保存して再度読み込んで、次の行をテキストボックスに入力してみてください。

+ +
person.height
+ +

上記の方法を使用してオブジェクトにプロパティを追加することは、ドット記法ではできません。ドット記法は、名前を指す変数ではなく、書いたとおりのメンバー名のみ受け入れることができます。

+ +

"this" とは何か

+ +

メソッドの中で、少し見慣れない点に気付いたかもしれません。 次の例でその点について考えてみましょう。

+ +
greeting: function() {
+  alert('Hi! I\'m ' + this.name.first + '.');
+}
+ +

"this" とは何だろうと思ったことでしょう。 この this キーワードはコードの中がその中で書かれている、現在のオブジェクトを参照しています。なので、この場合では  person を指します。 なぜ this の代わりに単に person と書かないのでしょうか。 この後 初心者のためのオブジェクト指向 の記事で見るように、コンストラクター等を書き始めるときに this は非常に便利です。メンバーのコンテキストが変わったとき(例えば 2 つの異なる person オブジェクトのインスタンスは、異なる名前を持っているが、greeting メソッドでそれぞれ自身の名前を使用したいとき)に常に正しい値を保証してくれます。

+ +

それでは、簡略化した person オブジェクトを使って、その意味を説明していきましょう。

+ +
const person1 = {
+  name: 'Chris',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+
+const person2 = {
+  name: 'Deepti',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+ +

この場合、person1.greeting() は "Hi! I'm Chris." を出力します。一方、person2.greeting() は "Hi! I'm Deepti." を出力します。しかし、どちらの場合も、そのメソッド部分のコードは全く同じです。先に述べたように this はそのコードが中にあるオブジェクトと等しいです — これは手作業でオブジェクトリテラルを書くときにはそれ程便利ではありませんが、動的にオブジェクトを生成する(例えばコンストラクターを使う)ときにとても効果的です。これは、この後によりはっきりとするでしょう。

+ +

ずっとオブジェクトを使ってきた

+ +

これらの例を通して、既に使ってきたドット記述と非常に似ていると考えたかもしれません。なぜならこのコースを通してそのような方法を使用してきたからです。組み込みのブラウザー API や JavaScript オブジェクトを使う例への取り組みを通していつもオブジェクトを使用してきました。なぜならそのような機能は、基本的なカスタム例よりも複雑ではありますが、ここまで見てきたものと全く同種のオブジェクト構造を使うことで構築されているからです。

+ +

だから、このように文字列のメソッドを使うとき:

+ +
myString.split(',');
+ +

String クラスのインスタンスで利用できるメソッドを使用しています。コードの中で文字列を作成するときにはいつでも、その文字列は自動的に String クラスのインスタンスとして生成されます。そしてそのために、いくつかの共通なメソッドやプロパティを使用することができます。

+ +

次の行のようにドキュメントオブジェクトモデルにアクセスするときは、

+ +
const myDiv = document.createElement('div');
+const myVideo = document.querySelector('video');
+ +

Document クラスのインスタンスで使用可能なメソッドを使っています。各ウェブページが読み込まれると、document と呼ばれる Document のインスタンスが作られ、それはウェブページ全体の構造、コンテンツ、その URL 等その他の機能を表現します。もう一度述べますが、これはいくつかの共通なメソッドやプロパティを使用できることを意味します。

+ +

今まで使用してきた、Array や Math 等の、他の多くの組み込みのオブジェクトや API でも全く同じです。

+ +

組み込みのオブジェクトと API では常に自動でオブジェクトのインスタンスが生成される訳ではないことを注意する必要があります。例えば、モダンなブラウザーがシステム通知を発行することを許可する Notifications API では、発行したい各通知のためにコンストラクターを使用した新しいオブジェクトを生成する必要があります。JavaScript コンソールに次を入力してみてください。

+ +
const myNotification = new Notification('Hello!');
+ +

コンストラクターは後の記事でもう一度見ることができます。

+ +
+

: オブジェクトのやり取りをメッセージの受け渡しと考えると便利です。オブジェクトが他のオブジェクトにある処理の実行を要求したとき、そのオブジェクトはメソッドを通じて他のオブジェクトにメッセージを送信して、そして応答を待ちます。ご存知の通り、応答とは返り値のことです。

+
+ +

スキルをテストしましょう!

+ +

この記事の最後に到達しましたが、最も大事な情報を覚えていますか?次に移動する前に、この情報を保持しているか検証するテストがあります — Test your skills: Object basics を見てください。

+ +

おさらい

+ +

お疲れ様でした。最初の JS オブジェクトの記事の終わりまで到達しました。JavaScript のオブジェクトがどのように機能するかについて、良い考えを得ることができたのではないでしょうか。記事では、簡単なオリジナルオブジェクトの作成を含んでいました。オブジェクトは関連するデータと機能を保存する構造として非常に便利であることも理解しなければいけません。もし別々の変数と関数として、person オブジェクトのすべてのプロパティとメソッドを記録していくとすると、非効率でありストレスが溜まります。そして同じ名前の他の変数や関数をクラッシュしてしまう危険性も抱えてしまいます。オブジェクトは有害な方法を避けて、パッケージの中で安全に鍵をして情報を守ってくれます。

+ +

次の記事ではオブジェクト指向プログラミング (OOP) 理論を見ていきます。そして、JavaScript ではそのような素晴らしい技術を使うことができます。

+ +

{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/index.html b/files/ja/learn/javascript/objects/index.html new file mode 100644 index 0000000000..65df0e0ece --- /dev/null +++ b/files/ja/learn/javascript/objects/index.html @@ -0,0 +1,53 @@ +--- +title: JavaScript オブジェクト入門 +slug: Learn/JavaScript/Objects +tags: + - Article + - Assesment + - Beginner + - CodingScripting + - Guide + - JavaScript + - Learn + - Objects + - Tutorial + - 学習 +translation_of: Learn/JavaScript/Objects +--- +
{{LearnSidebar}}
+ +

JavaScript では、文字列や配列などの JavaScript のコア機能から、JavaScript の最上部に構築されたブラウザ API まで、ほとんどのものがオブジェクトです。関連する関数や変数を効率的なパッケージにカプセル化して、便利なデータコンテナーとして動作する独自のオブジェクトを作成することもできます。JavaScript のオブジェクトベースの性質を理解することは、言語に関する知識をさらに深め、より効率的なコードを書く場合に重要です。したがって、この役立つモジュールを用意しました。ここではオブジェクトの理論と構文を詳しく説明し、独自のオブジェクトを作成する方法を見ていきます。

+ +

前提条件

+ +

このモジュールを始める前に、 HTML と CSS にいくらか精通している必要があります。JavaScript を始める前に HTML 入門CSS 入門をひととおり学習することをオススメします。

+ +

また、JavaScript オブジェクトを詳細に調べる前に、JavaScript の基本についていくらか精通している必要があります。このモジュールを試す前に、JavaScript の第一歩JavaScript の構成要素を通して学習してください。

+ +
+

注記 : もしあなたが作業しているコンピューター・タブレットやその他のデバイスで自分でファイルを作れない場合は、JSBinThimble といったようなオンラインコーディングプログラムで (ほとんどの場合) 試すことができます。

+
+ +

ガイド

+ +
+
オブジェクトの基本
+
JavaScript オブジェクトについて記載している最初の記事では、基本的な JavaScript オブジェクト構文を見てみます。コースの初期段階で既に見た JavaScript の機能を再び見てみたり、すでに扱っている機能の多くは実際にオブジェクトであるという事実を繰り返し述べています。
+
初心者のためのオブジェクト指向 JavaScript
+
まずオブジェクト指向 JavaScript (OOJS) に焦点を当てます — この記事では、オブジェクト指向プログラミング (OOP) 理論の基本ビューを示し、次に JavaScript がコンストラクタ関数を介してオブジェクトクラスをエミュレートする方法と、オブジェクトインスタンスを作成する方法について説明します。
+
オブジェクトプロトタイプ
+
プロトタイプは、JavaScript オブジェクトが互いに機能を継承するメカニズムであり、古典的なオブジェクト指向プログラミング言語の継承メカニズムとは異なる働きをします。この記事では、その違いを探り、プロトタイプチェーンの仕組みを説明し、prototype プロパティを使用して既存のコンストラクタにメソッドを追加する方法を見ていきます。
+
JavaScript での継承
+
OOJS の大部分の詳細がこれまで説明されているため、この記事では、「親」クラスから機能を継承する「子」オブジェクトクラス (のコンストラクタ) を作成する方法を示します。また OOJS をいつどこで使用するかについてのアドバイスも提供しています。
+
JSON データの操作
+
JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいて構造化されたデータを表現するための標準のテキストベースのフォーマットであり、ウェブサイト上でデータを表現し、送信するために一般的に使用されます (すなわち、サーバーからクライアントへデータを送信して、その結果ウェブページ上に表示することができます)。これはとても良く見るものなので、この記事では、JSON を解析してその中のデータ項目にアクセスしたり、独自の JSON を記述したりするなど、JavaScript を使用して JSON を操作するために必要なことをすべて説明します。
+
オブジェクト構築の練習
+
これまでの記事では、基本的な JavaScript オブジェクトの理論と構文の詳細をすべて見てもらい、あなたには出発できるしっかりとした基本が与えられました。この記事では実践的なエクササイズを行い、もっと楽しい色とりどりの色付きのボールを作成するカスタム JavaScript オブジェクトを作る練習をしていきます。
+
+ +

評価

+ +
+
バウンスボールのデモへの機能の追加
+
この評価では、前の記事のバウンスボールデモを出発点として使用し、新しい興味深い機能を追加する予定です。
+
diff --git a/files/ja/learn/javascript/objects/inheritance/index.html b/files/ja/learn/javascript/objects/inheritance/index.html new file mode 100644 index 0000000000..7830f5a676 --- /dev/null +++ b/files/ja/learn/javascript/objects/inheritance/index.html @@ -0,0 +1,412 @@ +--- +title: JavaScript での継承 +slug: Learn/JavaScript/Objects/Inheritance +tags: + - Article + - CodingScripting + - Inheritance + - JavaScript + - OOJS + - OOP + - Object + - Prototype + - 'l10n:priority' + - 初心者 + - 学習 +translation_of: Learn/JavaScript/Objects/Inheritance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}
+ +

OOJS のぞっとするような細部はほとんど説明されたので、ここでは”親”クラスからの機能を継承する”子供”のオブジェクトクラス (コンストラクタ) の生成方法について解説します。さらに、いつ、どこで OOJS を使うかについてのアドバイスを提示し、最新の ECMAScript の構文でクラスがどのように扱われるかを見ていきます。

+ + + + + + + + + + + + +
前提知識基本的なコンピュータの知識および利用能力、HTML と CSS への基本的な理解、JavaScript の基本 (第一歩構成要素を参照) と OOJS の基本 (オブジェクト入門) に慣れている。
目的:JavaScript でどのように継承ができるようになっているかを理解していること。
+ +

プロトタイプでの継承

+ +

ここまで動作している継承 ー プロトタイプチェーンがどのように動作するか、どのようにメンバーが繋がるチェーンから継承されるのかを見てきました。しかし、これらの大半はブラウザーの組み込み関数で実行されています。我々が他のオブジェクトから継承したオブジェクトを作成するには JavaScript でどのようにするのでしょうか。

+ +

具体的な例をjj使ってどのようの継承が行われているかを見てゆきましょう。

+ +

さあ始めてみよう

+ +

まず、oojs-class-inheritance-start.html ファイルをローカルにコピーしましょう (あるいはライブ版の実行でも確認できます)。ここでこのモジュールで幅広く使用されてきた Person() というコンストラクタの例を見つけることができます。わずかな違いがあって、コンストラクタ内部にプロパティのみが定義されています。

+ +
function Person(first, last, age, gender, interests) {
+  this.name = {
+    first,
+    last
+  };
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+};
+ +

メソッドはすべてコンストラクタのプロトタイプとして定義されています。例えば、

+ +
Person.prototype.greeting = function() {
+  alert('Hi! I\'m ' + this.name.first + '.');
+};
+ +
+

注意: ソースコードに、bio() と farewell() が定義されています。後ほどこれらのメソッドがどのようにほかのコンストラクタで継承されるのかを確認します。

+
+ +

Teacher クラスを作成したい場合を考えましょう。これは最初のオブジェクト指向の特徴にて述べたもののようなクラスで、Person からすべてのメンバーを継承しますが、次のものも内包しています。

+ +
    +
  1. 新しいプロパティの subject — これはその先生の教える科目を格納します。
  2. +
  3. 上書きされた greeting() メソッド、標準の greeting() メソッドよりわずかに固く感じられる — 学校で生徒に語りかける先生により相応しい。
  4. +
+ +

Teacher() コンストラクタの機能を定義しよう

+ +

われわれのまずすべき事は Teacher() コンストラクタを作成する事です — 以下に続くコードを既存コードの下に追加してください。

+ +
function Teacher(first, last, age, gender, interests, subject) {
+  Person.call(this, first, last, age, gender, interests);
+
+  this.subject = subject;
+}
+ +

これは多くの点で Person コンストラクタと似ていますが、これまでに見てきたものと異なったものがあります—  call() 関数です。この関数は基本的にその他の場所 (ただし現在のコンテキスト) で定義された関数から呼ぶことができます。最初の引数は関数を実行するときに使用することのできる this の値を表します、また他の引数は実行される関数に渡されるべき値です。

+ +

Teacher() コンストラクタは継承元の Person() コンストラクタと同じ引数を取りたいため、 call() を呼び出して、すべての引き数を引数として渡します。

+ +

コンストラクタの最後の行は、先生が行うべきであり、一般の人が持たない新たな subject(授業) のプロパティを定義しています。

+ +

注意として、下記のソースのように、このようにシンプルにも書けます。

+ +
function Teacher(first, last, age, gender, interests, subject) {
+  this.name = {
+    first,
+    last
+  };
+  this.age = age;
+  this.gender = gender;
+  this.interests = interests;
+  this.subject = subject;
+}
+ +

しかしながらこれはただ改めてプロパティを再定義しているだけで、 Person() から継承していません、そのため、説明しようとしたポイントが伝わりません。またコード行数が多くもなります。

+ +

引数なしのコンストラクタからの継承

+ +

もし継承したコンストラクタがパラメータからプロパティの値を取得しない場合、 call() の呼び出しで追加の引数を指定する必要がないことを示しておきます。そのため、例えば、このような本当にシンプルなものがある場合、

+ +
function Brick() {
+  this.width = 10;
+  this.height = 20;
+}
+ +

このように書くことで width と height プロパティを継承することができます(もちろん、下に挙げる数行のステップの様にすることもできます)。

+ +
function BlueGlassBrick() {
+  Brick.call(this);
+
+  this.opacity = 0.5;
+  this.color = 'blue';
+}
+ +

 call() の中に this だけを記載していることに注意して下さい— 引数を介して親より設定されるどのプロパティも継承しないので他の引数は不要です。

+ +

Teacher()のプロトタイプ とコンストラクタの参照への設定方法

+ +

今まではすべて順調でしたが、1点問題があります。新しいコンストラクタを定義して、その中に 1 つの prototype プロパティを持たせ、これはデフォルトでただ自身のコンストラクタ関数への参照を保持しています。Person のコンストラクタの prototype プロパティへのメソッド群は持っていません。このことを見てみたいのならば Object.getOwnPropertyNames(Teacher.prototype)  をテキスト入力フィールドや JavaScript コンソールへ入力を試してみてください。そして再度入力する時には、Teacher を Person で置き換えてみてください。新しいコンストラクタもそれらのメソッドを継承していません。このことを確認するために、Person.prototype.greeting と Teacher.prototype.greeting の出力結果を比べてみてください。Person()  のプロトタイプに定義されたメソッドを継承するために Teacher() を生成する必要があります。ではどのようにすればよいのでしょうか。

+ +
    +
  1. 前回追加した部分の下に以下の行を追加してみましょう: +
    Teacher.prototype = Object.create(Person.prototype);
    + ここで我々に馴染み深い create() に再度助けてもらいましょう。この場合に新しいオブジェクトを作ってそれを Teacher.prototype の値とするのに使います。新しいオブジェクトは Person.prototype を自身のプロトタイプとして保持し、それがゆえに(必要となる時には) Person.prototype 上で利用できるすべてのメソッドを継承します。
  2. +
  3. 先に進む前にもう一つやることがあります。
    + 最後の行を追加した後、Teacher.prototypeconstructor プロパティは Person() と同じになりました。なぜなら、Person.prototype からプロパティを継承するオブジェクトを参照するように Teacher.prototype を設定しただけだからです。コードを保存し、ブラウザでページを読み込み、コンソールに Teacher.prototype.constructor と入力して確認してみてください。
  4. +
  5. これは問題になるかもしれません、なので以下の内容をすぐに設定しましょう。 ソースコードにまた戻って最後に以下の行を追加しましょう。 +
    Object.defineProperty(Teacher.prototype, 'constructor', {
    +    value: Teacher,
    +    enumerable: false, // 'for in'ループで現れないようにする
    +    writable: true });
    +
  6. +
  7. ソースコードを保存およびページの再読み込みを行って、 Teacher.prototype.constructor と入力したならば Teacher() と返すでしょう、希望した通りに Person() から継承することができました!
  8. +
+ +

Teacher() に greeting() ファンクションを付け加える

+ +

コードを完成させる前に、Teacher() コンストラクタに新たに greeting() 関数を追加する必要があります。

+ +

このようにする一番簡単な方法は Teacher() のプロトタイプに定義することです — コードの最後に以下のコードを追加します。

+ +
Teacher.prototype.greeting = function() {
+  let prefix;
+
+  if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
+    prefix = 'Mr.';
+  } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
+    prefix = 'Mrs.';
+  } else {
+    prefix = 'Mx.';
+  }
+
+  alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
+};
+ +

これは性別を基にした適切な敬称を使う教師の挨拶を通知します。条件文を使うことで実現します。

+ +

例を試してみよう

+ +

これまでのコードをすべて入力し終えているなら、ソースコード(もしくはあなたの用意した同じようなコードに)の最後に続けて Teacher() からオブジェクトインスタンスを生成してみましょう。

+ +
let teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
+ +

保存し、再読み込みをしたなら、新たな teacher1 オブジェクトのプロパティとメソッドにアクセスしてみましょう、例えば。

+ +
teacher1.name.first;
+teacher1.interests[0];
+teacher1.bio();
+teacher1.subject;
+teacher1.greeting();
+teacher1.farewell();
+ +

これらはすべて正常に動作するはずです。1, 2, 3, 6 行目のクエリは、ジェネリックな Person() コンストラクタ (クラス) から継承されたメンバにアクセスします。4 行目のクエリは、より特殊な Teacher() コンストラクタ (クラス) でのみ利用可能なメンバにアクセスしています。5 行目のクエリは Person() から継承したメンバにアクセスしていますが、Teacher() には同じ名前の独自のメンバがあるため、そのメンバにアクセスしています。

+ +
+

注記: もしここまでの例がうまく動作しないなら、あなたのコードと完成版(ライブ版も参照)を比較してみてください。

+
+ +

ここで述べている手法は JavaScript でクラスを継承する唯一の方法ではなく、問題なく動作し、JavaScript でのどのように実装するかの良いアイデアを提示しています。

+ +

また JavaScript でより明瞭に継承を行えるようにした新しい{{glossary("ECMAScript")}}の機能(Classes を参照)にも興味を持つかもしれません。ここではそれらについて言及はしませんでした、それはまだブラウザー間で幅広くサポートされていないためです。一連の記事で検討してきた他のコード構造はすべて、IE9 やそれ以前のバージョンといった、はるか以前よりサポートされており、それより早くからのサポートを確認する方法となります。

+ +

一般的な方法は JavaScript ライブラリを使用することです — よく知られた選択肢のうちの大部分は、よりたやすく素早く利用できる簡易な機能セットを持っています。例えば CoffeeScript は class, extends などを提供します。

+ +

追加の特訓

+ +

OOP 理論のセクションでは、概念として Student クラスも取り上げました。このクラスは Person のすべての機能を継承しており、また Person とは異なる Teacher の greeting よりもはるかにくだけた greeting() メソッドを持っています。このセクションで生徒の挨拶がどのように見えるかを見て、Person() のすべての機能を継承し、異なる greeting() 関数を実装した独自の Student() コンストラクタを実装してみてください。

+ +
+

注記: もしここまでの例がうまく動作しないなら、あなたのコードと完成版(動作するライブ版も参照)を比較してみてください。

+
+ +

Object メンバーの概要

+ +

要約すると、気になるプロパティ/メソッドは4種類あります。

+ +
    +
  1. コンストラクタ関数の内部で定義され、オブジェクトインスタンスに与えられるもの。独自のカスタムコードでは、コンストラクタの内部で this.x = x 型の行を使用して定義されたメンバです。組み込みのブラウザコードでは、オブジェクトインスタンス (通常は new キーワードを使用してコンストラクタを呼び出すことで作成されます。例:  let myInstance = new myConstructor()) のみが利用可能なメンバです
  2. +
  3. コンストラクタ自身で直接定義されたもので、コンストラクタ上でのみ利用可能なもの。これらは一般的に組み込みのブラウザオブジェクトでのみ利用可能であり、インスタンスではなくコンストラクタに直接連結されていることで認識されます。たとえば Object.keys() などです。これらは静的プロパティ/メソッドとしても知られています
  4. +
  5. コンストラクタのプロトタイプに定義されているもので、すべてのインスタンスに継承され、オブジェクトクラスを継承しているもの。これらには、コンストラクタの prototype プロパティに定義されている任意のメンバ (例: myConstructor.prototype.x()) が含まれます
  6. +
  7. これらは、上で見たようにコンストラクタがインスタンス化されたときに作成されるオブジェクト (例えば let teacher1 = new Teacher('Chris'); の後に teacher1.name)、またはオブジェクトリテラル (let teacher1 = { name : 'Chris' } の後に teacher1.name) のいずれかであることができます
  8. +
+ +

もしどれがどれを指すかを区別できないのであれば、まだ気にしないでください — あなたはまだ学習中で、実践を通じて精通することでしょう。

+ +

ECMAScript 2015 のクラス

+ +

ECMAScript 2015では、C++ や Java のクラスに似た、より簡単で洗練された構文を使用して再利用可能なクラスを記述する方法として、JavaScript にクラス構文を導入しています。このセクションでは、Person と Teacher の例をプロトタイプの継承からクラスに変更して、どのようにして行うかを示します。

+ +
+

メモ: この近代的なクラスの作成方法は現在のすべてのブラウザでサポートされていますが、この構文をサポートしていないブラウザ (特に Internet Explorer) をサポートする必要があるプロジェクトで作業する場合に備えて、基本的なプロトタイプの継承の仕組みについて知っておくことはまだ価値があります。

+
+ +

Person の例を class-style で書き直したバージョンを見てみましょう:

+ +
class Person {
+  constructor(first, last, age, gender, interests) {
+    this.name = {
+      first,
+      last
+    };
+    this.age = age;
+    this.gender = gender;
+    this.interests = interests;
+  }
+
+  greeting() {
+    console.log(`Hi! I'm ${this.name.first}`);
+  };
+
+  farewell() {
+    console.log(`${this.name.first} has left the building. Bye for now!`);
+  };
+}
+ +

classステートメントは、新しいクラスを作成していることを示します。 このブロックの中で、クラスのすべての機能を定義します。

+ + + +

以前と同じようにnew演算子を使用してオブジェクトインスタンスをインスタンス化できるようになりました。

+ +
let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);
+han.greeting();
+// Hi! I'm Han
+
+let leia = new Person('Leia', 'Organa', 19, 'female', ['Government']);
+leia.farewell();
+// Leia has left the building. Bye for now
+ +
+

メモ: 内部ではクラスはプロトタイプの継承モデルに変換されています。これはシンタックスシュガーです。しかし、私たちはあなたがそれを書く方が簡単だと考えるだろうと確信しています。

+
+ +

クラス構文による継承

+ +

上記では人を表すクラスを作成しました。彼らはすべての人々に共通の一連の属性を持っています。このセクションでは、特殊なTeacherクラスを作成し、現代のクラス構文を使用してPersonから継承します。これはサブクラス、またはサブクラスの作成と呼ばれます。
+
+ サブクラスを作成するには extends キーワードを使用して、クラスの基底となるクラスをJavaScriptに通知します。

+ +
constructor(first, last, age, gender, interests) {
+   this.name = {
+     first,
+     last
+   };
+   this.age = age;
+   this.gender = gender;
+   this.interests = interests;
+} 
+ +

super() 演算子を constructor() 内の最初の項目として定義することで、コードをより読みやすくすることができます。これは親クラスのコンストラクタを呼び出し、そこに定義されている限り、指定したメンバーをsuper() のパラメータとして継承します。

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+
+    // 科目と学年は教師によって決まっている
+    this.subject = subject;
+    this.grade = grade;
+  }
+}
+ +

Teacherのオブジェクトをインスタンス化するときには、TeacherPersonの両方で定義されたメソッドとプロパティを呼び出すことができます。

+ +
let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5);
+snape.greeting(); // Hi! I'm Severus.
+snape.farewell(); // Severus has left the building. Bye for now.
+snape.age // 58
+snape.subject; // Dark arts
+ +

Teachers と同じように、基本クラスを変更せずに Person をさらに特化したものにするために、他のサブクラスを作成できます。

+ +
+

メモ: この例は、GitHub で es2015-class-inheritance.html として見つけることができます(これも実際に参照してください)。

+
+ +

Getter と Setter

+ +

作成するクラスの属性の値を変更したい場合や、属性の最終値がわからない場合があります。Teacher の例を使用すると、教師が教材を作成する前にどの教科を教えるか分からないことがあります。
+
+ getter や setter でこのような状況を処理できます。
+
+ getter と setter で Teacher クラスを強化しましょう。私たちが最後に見たときと同じようにクラスが始まります。
+
+ getter と setter はペアで動作します。getter は変数の現在の値を返し、対応する setter は変数の値をひとつの値に変更します。
+
+ 変更された Teacher クラスは次のようになります。

+ +
class Teacher extends Person {
+  constructor(first, last, age, gender, interests, subject, grade) {
+    super(first, last, age, gender, interests);
+    // 科目と学年は教師によって決まっている
+    this._subject = subject;
+    this.grade = grade;
+  }
+
+  get subject() {
+    return this._subject;
+  }
+
+  set subject(newSubject) {
+    this._subject = newSubject;
+  }
+}
+ +

上のクラスでは、subject プロパティの getter と setter があります。 Nameプロパティを格納するために _ を使用して別の値を作成します。この規約を使用しないと、get または set を呼び出すたびにエラーが発生します。 この時点で:

+ + + +

以下の例は、動作している2つの機能を示しています。

+ +
// デフォルトの値をチェックする
+console.log(snape.subject) // Returns "Dark arts"
+
+// 値を変更する
+snape.subject = "Balloon animals" // Sets _subject to "Balloon animals"
+
+// 新しい値と一致しているか再度チェックする
+console.log(snape.subject) // Returns "Balloon animals"
+ +
+

メモ: この例は、GitHub で es2015-class-inheritance.html として見つけることができます(これも実際に参照してください)。

+
+ +
+

メモ: ゲッターやセッターは、プロパティが要求されたり設定されたりするたびにコードを実行したい場合など、非常に便利な場合があります。しかし、単純なケースでは、ゲッターやセッターを使用しないプレーンなプロパティアクセスで十分です。

+
+ +

JavaScript でいつ継承を使用するのでしょうか?

+ +

特にこの最後の記事を読み終えた後、「うーん、これはややこしいな。」と考えることでしょう。ええ、それは正しい感想です。プロトタイプと継承は JavaScript のもっとも複雑な面のいくつかに当たります、しかし多くの JavaScript の能力と柔軟性はそのオブジェクトの構造と継承に由来します、そしてそれがどのように動作するかは理解するに値します。

+ +

ある意味では、常に継承を使用しています。Web API の様々な機能、文字列や配列といったブラウザーに組み込まれたオブジェクトで定義されているメソッド/プロパティを使用するときはいつも、暗黙の内に継承を使用しています。

+ +

コードに継承を使用していることに関して、特に開始時には、そして小さなプロジェクトでは多分頻繁には使っていないでしょう。不要にも関わらず、継承のためだけにオブジェクトおよび継承を使用するのは時間の浪費です。しかしコードの母体が大きくなればなるほど、継承についての必要性が目に付きやすくなってきます。同じような機能を持ついくつものオブジェクトを作成していることに気付いた場合は、共有機能を持つ汎化オブジェクトタイプを作成し、特化オブジェクトタイプでそれらの機能を継承させるのがお手軽であり、便利です。

+ +
+

注記: プロトタイプチェーンなどを使って JavaScript が動作する方法のために、オブジェクト間での機能の共有をしばしば 移譲 と呼ぶ事があります。特化オブジェクトは汎化オブジェクトタイプから機能的に移譲されています。

+
+ +

継承を使用している時、継承をやたら多いレベルに行わないように、メソッドとプロパティをどこに定義したかを注意深く追跡し続けるようにアドバイスされるでしょう。組み込みブラウザーのオブジェクトのプロトタイプを一時的に変更するコードを書き始めることは可能ですが、実際に良い理由がないのであれば、そうすべきではありません。過剰な継承は終わりない混乱や、そんなコードをデバックする時は終わりない痛みに繋がりかねません。

+ +

究極的には、オブジェクトは関数やループのような、自身の固有の役割や長所を活かした、コードの再利用の単なる別の形でもあります。もし関連のある変数や関数の一団を作成していることに気付き、それらすべてを追跡して適切にパッケージ化したいのであれば、オブジェクトは良いアイデアです。オブジェクトはまた、ある所から別の所にデータの集合を渡したい場合にも大変便利です。これらの事柄の両方がコンストラクタや継承を使用する事なく達成できます。もしオブジェクトの単一のインスタンスが必要なだけであれば、オブジェクトリテラルを使用するのが多分より良く、確実に継承は必要ないでしょう。

+ +

プロトタイプチェーンを拡張するための代替案

+ +

JavaScript では、上で示したものとは別に、オブジェクトのプロトタイプを拡張する方法がいくつかあります。その他の方法についての詳細は、継承とプロトタイプチェーンの記事を参照してください。

+ +

あなたのスキルをテストしてみましょう!

+ +

この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストがいくつかあります - あなたのスキルをテストする: オブジェクト指向 JavaScript を参照してください。

+ +

まとめ

+ +

この記事は今知っておくべき考えられる OOJS の核となる理論および文法の残りの部分をカバーしています。この時点で、 JavaScript オブジェクトおよび オブジェクト指向プログラミングの基本、プロトタイプとプロトタイプにおける継承、クラス(コンストラクタ)とオブジェクトのインスタンスの生成、クラスへの機能の追加、他のクラスから継承されたサブクラスの生成をどのように行うか、を理解しているでしょう。

+ +

次の記事では JavaScript Object Notaion (JSON) 、つまり  JavaScript オブジェクトを使用して書かれた共通データ交換フォーマット、がどのように動作するかをを見て行きましょう。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/json/index.html b/files/ja/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..c72a38744b --- /dev/null +++ b/files/ja/learn/javascript/objects/json/index.html @@ -0,0 +1,357 @@ +--- +title: JSON データの操作 +slug: Learn/JavaScript/Objects/JSON +tags: + - Article + - Beginner + - CodingScripting + - Guide + - JSON + - JavaScript + - Learn + - Objects + - Tutorial + - 'l10n:priority' +translation_of: Learn/JavaScript/Objects/JSON +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}
+ +

JavaScript Object Notation (JSON) は表現用の標準的なテキストベースの構造データ表現フォーマットで、JavaScript 構造データオブジェクトの表記法をベースとしています。一般的にはウェブアプリケーションでデータを転送する場合に使われます。(例えば、データをサーバーからクライアントへ送信する場合などで、ウェブページに表示されたりすることもあり、その逆もあります)。頻繁に見かけるデータフォーマットですので、この節では JavaScript を使って JSON をパースする、JSON のデータを参照する、JSON を作るなど、JSON を扱うために必要となる操作を説明します。

+ + + + + + + + + + + + +
前提条件:基礎的なコンピュータの知識、HTML と CSS への基本的な理解、基礎的な JavaScript の理解 (JavaScript の第一歩JavaScript の構成要素を参照) とオブジェクト指向JavaScript の基本 (JavaScript オブジェクトの基本を参照)。
目的:JSON内のデータの扱い方、JSON 文字列の作成方法について理解できること。
+ +

JSON とは何か

+ +

{{glossary("JSON")}} は JavaScript オブジェクトの構文に従ったテキストベースのフォーマットで、Douglas Crockford によって普及されました。JSON は JavaScript オブジェクトの構文に似ていますが、JavaScript とは独立して扱われることがあり、多くのプログラミング言語環境には JSON を読み込む(パースする)したり生成したりする機能があります。

+ +

JSON は文字列です。ですので、ネットワークを通してデータを転送したい場合に便利です。JSON データへアクセスしたい場合は、JavaScript オブジェクトへ変換する必要があります。JavaScript には JSON と JavaScript オブジェクトを相互に変換できるメソッドを持った JSON というグローバルなオブジェクトがあるので、その変換は大きな問題ではありません。

+ +
+

注記: 文字列をネイティブオブジェクトへ変換することはデシリアライゼーション (deserialization) と呼ばれており、ネイティブオブジェクトをネットワークを通して転送できように文字列へ変換することはシリアライゼーション (serialization) と呼ばれています。

+
+ +

JSON 文字列はそれ自身をファイルとして格納することもできます。それは {{glossary("MIME type")}} が application/json で、.json という拡張子の付いたただのテキストファイルです。

+ +

JSON の構造

+ +

上で説明したように、JSON は JavaScript オブジェクトにとても似ているフォーマットを持った文字列です。JSON では通常の JavaScript オブジェクトと同様な基本データ型(文字列、数値、配列、ブーリアンやその他のリテラル型)を使うことができます。これにより、以下のように階層的にデータを構成することができます。

+ +
'{
+  "squadName": "Super hero squad",
+  "homeTown": "Metro City",
+  "formed": 2016,
+  "secretBase": "Super tower",
+  "active": true,
+  "members": [
+    {
+      "name": "Molecule Man",
+      "age": 29,
+      "secretIdentity": "Dan Jukes",
+      "powers": [
+        "Radiation resistance",
+        "Turning tiny",
+        "Radiation blast"
+      ]
+    },
+    {
+      "name": "Madame Uppercut",
+      "age": 39,
+      "secretIdentity": "Jane Wilson",
+      "powers": [
+        "Million tonne punch",
+        "Damage resistance",
+        "Superhuman reflexes"
+      ]
+    },
+    {
+      "name": "Eternal Flame",
+      "age": 1000000,
+      "secretIdentity": "Unknown",
+      "powers": [
+        "Immortality",
+        "Heat Immunity",
+        "Inferno",
+        "Teleportation",
+        "Interdimensional travel"
+      ]
+    }
+  ]
+}'
+ +

もし、この文字列を JavaScript プログラムへ読み込んだ場合(例えば、例えば変数superHeroes へ代入する)、JavaScript オブジェクトの基本の節で見たのと同様に ドットや角括弧を使ってデータへアクセスすることができます。例としては以下のようになります。

+ +
superHeroes.homeTown
+superHeroes['active']
+ +

さらに深い階層のデータへアクセスする場合は、単純にプロパティ名や配列のインデックスを連結します。例えば、メンバーリスト中2番目のヒーローの 3番目の能力を参照する場合は、以下のようになります。

+ +
superHeroes['members'][1]['powers'][2]
+ +
    +
  1. まず、変数名superHeroes を指定します。
  2. +
  3. その中の members プロパティへアクセスしたいので、["members"]と指定します。
  4. +
  5. members にはオブジェクトの配列が格納されています. ここでは、配列内の 2番目のオブジェクトへアクセスするので、[1]を指定します。
  6. +
  7. そのオブジェクト内で、powers プロパティへアクセスするため, ["powers"]と指定します。
  8. +
  9. powers プロパティは選択したヒーローの能力を含んだ配列となっており、その中の 3番目が欲しいので、[2]と記述します。
  10. +
+ +
+

注記: 上記の JSON は JSONTest.html で参照することができます。(ページ内の source code を参照してください)。ページを読み込んで見て、ブラウザーのコンソールで変数内のデータにアクセスしてみてください。

+
+ +

JSON 配列

+ +

上記で、JSON テキストは基本的に文字列に入った JavaScript オブジェクトのように見えることを説明しました。配列を JSON との間で変換することもできます。以下も有効な JSON です。例:

+ +
'[
+  {
+    "name": "Molecule Man",
+    "age": 29,
+    "secretIdentity": "Dan Jukes",
+    "powers": [
+      "Radiation resistance",
+      "Turning tiny",
+      "Radiation blast"
+    ]
+  },
+  {
+    "name": "Madame Uppercut",
+    "age": 39,
+    "secretIdentity": "Jane Wilson",
+    "powers": [
+      "Million tonne punch",
+      "Damage resistance",
+      "Superhuman reflexes"
+    ]
+  }
+]'
+ +

これも有効な JSON であり、パースしたデータには配列のインデックスを指定するだけです。例えば、[0]["powers"][0]のように表記できます。

+ +

その他の注意点

+ + + +

手を動かして学ぼう: JSON をさわってみる

+ +

それでは、Web サイト上でどのように JSON 形式のデータを使うことができるか例を通して見てみましょう。

+ +

はじめに

+ +

まず、heroes.html と style.css のコピーをローカルに作成してください。後者は例題ページをスタイリングするための CSS であり、前者は簡単な形式の HTML です。

+ +
<header>
+</header>
+
+<section>
+</section>
+ +

他には、この演習で書く JavaScript を含んだ {{HTMLElement("script")}} 要素があります。この時点では、{{HTMLElement("header")}} 要素と {{HTMLElement("section")}} 要素 を取得して、変数へ代入している 2行コードのみが書かれています。

+ +
const header = document.querySelector('header');
+const section = document.querySelector('section');
+ +

演習用の JSON データは https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json に用意してあります。

+ +

そのデータを演習ページに読み込んで、それを表示するのにいくらかの DOM操作を行います。最終的には、以下の画像のようになります。

+ +

+ +

JSON の取得

+ +

JSON を取得するには、{{domxref("XMLHttpRequest")}} (しばしば XHR と呼ばれる) という API を使用します。これは非常に便利な JavaScript オブジェクトで、JavaScript を使用してサーバからリソース (例:画像、テキスト、JSON、さらには HTML スニペットなど) を取得するネットワークリクエストを行うことができます。つまりページ全体を再読み込みせずに、小さな部分のコンテンツを更新することができます。これにより、よりレスポンシブな Web ページを作成できますが、それをもっと詳細に教えるのはこの記事の範囲を超えています。

+ +
    +
  1. まず、取得したい JSON がある URL を変数へ代入します。次のコードを JavaScript の最後の行へ追加してください。 +
    let requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
    +
  2. +
  3. HTTP リクエストを作成するのに、new を使って XMLHttpRequest から新しいリクエストオブジェクトをつくる必要があります。先ほどのコードの下に、次のコードを追加してください。 +
    let request = new XMLHttpRequest();
    +
  4. +
  5. 新しいリクエストを開始するのには open() メソッドを使います。 次のコードを追加してください。 +
    request.open('GET', requestURL);
    + +

    このメソッドは最低2つのパラメータを引数として取ります(他に任意の引数を与えることもできます)。今回の簡単な例では、次の2つの必須パラメータのみを利用します。

    + +
      +
    • リクエストを開始する際に HTTP のメソッドを決める必要があります。今回のケースでは、単純にデータを取得するだけですので GET が良いでしょう。
    • +
    • リクエストを送る先の URL。今回は JSON ファイルが置かれている URL です。
    • +
    +
  6. +
  7. 次に、以下の2行のコードを追加してください。XHR オブジェクトがサーバーから返されるデータを判断できるように responseType に JSON を指定します。すると、ブラウザ側で JavaScript オブジェクトへ変換してくれます。それから、send() メソッドでリクエストを送信します。 +
    request.responseType = 'json';
    +request.send();
    +
  8. +
  9. 最後に、サーバーからのレスポンスを待ち、それを処理するコードを用意するので、以下のコードをこれまでのコードの下に追加してください。 +
    request.onload = function() {
    +  const superHeroes = request.response;
    +  populateHeader(superHeroes);
    +  showHeroes(superHeroes);
    +}
    +
  10. +
+ +

ここでは、先ほどのリクエストに対するレスポンス (response プロパティから取得できます) を superHeroes という変数へ代入しています。つまり、この変数に JSON を元に生成された JavaScript オブジェクトが格納されているということです! それから 2 つの関数をそのオブジェクトを引数として与えて呼び出しています。最初の関数は引数のデータを <header> へ埋め込み、2 つ目は各ヒーローごとのインフォメーションカードを作り、<section> へ埋め込みます。

+ +

上記の処理は、リクエストオブジェクトで load イベントが発生した時に呼び出される関数 (onload を参照) に記述しました。このイベントはレスポンスがうまく取得できた場合に呼び出されるので、 request.response を使って何か処理をしようとしたときに、それが必ず利用できることが保証されています。

+ +

ヘッダーへの値のセット

+ +

ここまでで、JSON の取得と JavaScript オブジェクトへの変換ができました、先ほどの 2 つの関数を実装して使ってみましょう。まずはじめに、以下のコードをこれまでのコードの下に追加してください。

+ +
function populateHeader(obj) {
+  const myH1 = document.createElement('h1');
+  myH1.textContent = obj['squadName'];
+  header.appendChild(myH1);
+
+  const myPara = document.createElement('p');
+  myPara.textContent = 'Hometown: ' + obj['homeTown'] + ' // Formed: ' + obj['formed'];
+  header.appendChild(myPara);
+}
+ +

まず、createElement() で {{HTMLElement("h1")}} 要素を生成、その textContent プロパティにそのオブジェクトの squadName プロパティをセット、そしてそれを appendChild() を使いヘッダーに追加します。そして要素の生成、テキストのセット、ヘッダーへの追加という同じような操作をパラグラフ要素でも行います。セットするテキストの値が homeTownformed プロパティの文字列を結合したものであるという点だけが異なります。

+ +

ヒーローインフォメーションカードの作成

+ +

次に、以下の関数をコードの下へ追記してください。この関数はスーパーヒーローカードの作成と画面表示を行います。

+ +
function showHeroes(jsonObj) {
+  const heroes = jsonObj['members'];
+
+  for (let i = 0; i < heroes.length; i++) {
+    const myArticle = document.createElement('article');
+    const myH2 = document.createElement('h2');
+    const myPara1 = document.createElement('p');
+    const myPara2 = document.createElement('p');
+    const myPara3 = document.createElement('p');
+    const myList = document.createElement('ul');
+
+    myH2.textContent = heroes[i].name;
+    myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
+    myPara2.textContent = 'Age: ' + heroes[i].age;
+    myPara3.textContent = 'Superpowers:';
+
+    const superPowers = heroes[i].powers;
+    for (let j = 0; j < superPowers.length; j++) {
+      const listItem = document.createElement('li');
+      listItem.textContent = superPowers[j];
+      myList.appendChild(listItem);
+    }
+
+    myArticle.appendChild(myH2);
+    myArticle.appendChild(myPara1);
+    myArticle.appendChild(myPara2);
+    myArticle.appendChild(myPara3);
+    myArticle.appendChild(myList);
+
+    section.appendChild(myArticle);
+  }
+}
+ +

始めに、JavaScript オブジェクトの members プロパティを新しい変数に保存します。
+ この配列は複数のオブジェクトを持ち、オブジェクトはそれぞれのヒーローについての情報を持ちます。

+ +

次に、for ループを使って配列の個々のオブジェクトについてループしていきます。それぞれについて:

+ +
    +
  1. 新しい要素をいくつか作ります: <article> 1つ、<h2> 1つ、3つの <p> と1つの <ul> です。
  2. +
  3. <h2> の中身を今のヒーローの名前 (name) にします。
  4. +
  5. 3つの <p> の中身を、それぞれの secretIdentityage、リストにある情報を紹介していくために「超能力 ("Superpowers:")」で始まる行とします。
  6. +
  7. powers プロパティを superPowers という新しい定数に保存します — この定数は今のヒーローの超能力のリストを持つ配列です。
  8. +
  9. 別の for ループをつかって、今のヒーローの超能力をループします — それぞれに対する <li> 要素を作成し、超能力をこの要素の中身とし、<ul>要素(myList変数)の listItemappendChild() を使って追加します。
  10. +
  11. 最後の最後にやるのは、<h2><p><ul><article> (myArticle) の中身に追加し、それから <article><section> の中身に追加します。HTML の中身として表示される順序になりますので、これらの要素が追加された順序は重要です。
  12. +
+ +
+

付記: 例を動かしてみるのに問題があったら、heroes-finished.html ソースコードを参照して見て下さい(こちらで ライブ実行 もできます)。

+
+ +
+

付記: もし JavaScript オブジェクトにアクセスするのに使っているドット/ブラケット記法をなぞっていくのが難しければ、superheroes.json  のファイルを別のタブやテキストエディタで開いておいて、JavaScript と並べて読んでいくとわかりやすいかもしれません。JavaScript オブジェクトの基本 記事にも戻って、ドット/ブラケット記法について読み返してみてください。

+
+ +

オブジェクトとテキスト間の変換

+ +

上の例は XHR リクエストで JSON レスポンスを直接JavaScript オブジェクトに変換していたので、JavaScript オブジェクトへのアクセスという面では単純でした。次の部分です:

+ +
request.responseType = 'json';
+ +

時にはこんなにツイていない場合もあります — 時には生の  JSON 文字列を受けとり、自分でオブジェクトに変換しなければならない場合もあるでしょう。また JavaScript オブジェクトをネットワーク越しに送信したい場合、送信する前に JSON 文字列に変換しなければならないでしょう。ツイている事に、ウェブ開発でこの二つの問題にはしょっちゅう出くわすので、ブラウザには組込みの JSON  オブジェクトが備わっていて、これは以下二つのメソッドを備えています:

+ + + +

一つめの方の動作例が heroes-finished-json-parse.html にあります (ソース を見て下さい) — ここでは前の方で作成した例と全く同じ事をしていますが、XHR では生の JSON 文字列を返させて、それを parse() で JavaScript オブジェクトに変換しているところだけが異なります。コードの重要な箇所はこの部分です:

+ +
request.open('GET', requestURL);
+request.responseType = 'text'; // now we're getting a string!
+request.send();
+
+request.onload = function() {
+  const superHeroesText = request.response; // get the string from the response
+  const superHeroes = JSON.parse(superHeroesText); // convert it to an object
+  populateHeader(superHeroes);
+  showHeroes(superHeroes);
+}
+ +

で、ご想像の通り stringify()  は全く反対の向きに動作します。次の行をブラウザーの JavaScript コンソールに一つずつ打ち込んでいって、実際に動かしてみて下さい:

+ +
let myObj = { name: "Chris", age: 38 };
+myObj
+let myString = JSON.stringify(myObj);
+myString
+ +

JavaScript オブジェクトを作成してその中身を確認し、次に stringify() を使って JSON 文字列に変換し — 戻り値を新しい変数に保存しています — その値も確認しています。

+ +

あなたのスキルをテストしてみましょう!

+ +

この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するためのテストがいくつかあります — Test your skills: JSON を参照してください。

+ +

まとめ

+ +

この節では、プログラム内で、JSON を生成する、JSON をパースする、JSON データを参照するなど、JSON を扱う方法について簡単に説明しました。次の節では、オブジェクト指向 JavaScript について見ていくことにします。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/object-oriented_js/index.html b/files/ja/learn/javascript/objects/object-oriented_js/index.html new file mode 100644 index 0000000000..ab99282acb --- /dev/null +++ b/files/ja/learn/javascript/objects/object-oriented_js/index.html @@ -0,0 +1,291 @@ +--- +title: 初心者のためのオブジェクト指向 JavaScript +slug: Learn/JavaScript/Objects/Object-oriented_JS +tags: + - Beginner + - Create + - JavaScript + - OOJS + - OOP + - オブジェクト + - オブジェクト指向 + - 学習 + - 記事 +translation_of: Learn/JavaScript/Objects/Object-oriented_JS +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}
+ +

基礎が片付いたところで、オブジェクト指向 JavaScript (OOJS) について取り上げます。この記事ではオブジェクト指向プログラミング (OOP) の基本的な視点を説明し、 JavaScript がどのようにコンストラクター関数を通じてオブジェクトクラスをエミュレートしているか、またどのようにオブジェクトインスタンスを生成しているかを紹介します。

+ + + + + + + + + + + + +
前提知識:基礎的なコンピュータリテラシー、基礎的な HTML と CSS の理解、JavaScript (JavaScript の第一歩JavaScript の構成要素を参照) および OOJS (JavaScript オブジェクトの基本を参照)の基礎知識。
目標:オブジェクト指向プログラミングの基本理論、どのようにそれが JavaScript (「すべてはオブジェクトである」) に関連しているか、どのようにコンストラクターがオブジェクトインスタンスを生成しているかを理解する。
+ +

オブジェクト指向プログラミング - その基本

+ +

はじめに、オブジェクト指向プログラミング (OOP) とは何か、シンプルかつ高レベルな視点を提示します。シンプルと述べたのは、OOP はあっという間にひどく複雑になり得るためで、現時点でそのすべてを論じてしまうと、助けとなるよりもむしろ混乱を生んでしまうことでしょう。OOP の基本的な考え方は、プログラムの中で扱いたい、現実世界の事物を模るためにオブジェクトを使用すること、またはそうしなければ使うことが難しいあるいは不可能だった機能にアクセスするための、シンプルな方法を提供することです。

+ +

オブジェクトは、モデル化しようとしている事物に関する情報および、持たせたい機能や動作を表現する、関連したデータとコードを持つことができます。オブジェクトのデータ (しばしば関数も含む) はオブジェクトのパッケージの中 (名前空間と呼ばれることがある) に適切に格納されます (カプセル化)。オブジェクトは一般に、ネットワークを通じて容易に送信することが可能な、データストアとしても使われます。

+ +

オブジェクトのテンプレートを定義する

+ +

学校の生徒と教師の情報を表示する、シンプルなプログラムを考えてみましょう。特定のプログラミング言語の文脈ではなく、OOP 一般の理論を眺めていきます。

+ +

はじめに、オブジェクト入門の最初の記事にある、人物の包括的なデータや機能を定義した、Person オブジェクトに戻りましょう。ある人物について知り得る事柄は数多くあります (住所、身長、靴のサイズ、DNA 情報、パスポート番号、顕著な人格特性など) が、このケースでは名前、年齢、性別、趣味を表示することに興味があるだけです。また、このデータに基づいた短い自己紹介や、挨拶をさせられるようにもしましょう。これは抽象化 — より複雑な事物を、プログラムの目的に沿って簡単に操作できるように、その最も重要な側面を表現する、シンプルなモデルを作ること — として知られています。

+ +

+ +

実際のオブジェクトの生成

+ +

このクラスから、オブジェクトインスタンスを生成することができます。オブジェクトインスタンスは、クラスで定義されたデータや機能を持ったオブジェクトです。 Person クラスから、何名かの実際の人物を生成します。

+ +

+ +

クラスからオブジェクトインスタンスが生成されるとき、クラスのコンストラクター関数が生成のために実行されます。クラスからオブジェクトインスタンスが生成される過程をインスタンス化と呼びます。オブジェクトインスタンスは、クラスをインスタンス化したものです。

+ +

専門のクラス

+ +

このケースで求めているのは、包括的な人物ではなく、より特定のタイプである、教師と生徒です。OOP では、他のクラスを元にした新しいクラスを作ることができます。これらの新しい子クラスは、親クラスからデータやコード機能を継承することができ、すべてのオブジェクトタイプに共通する機能を、重複させるのではなく、再利用することができます。クラス間で機能が異なる場合は、必要に応じて特殊化された機能を直接定義することができます。

+ +

+ +

これは実に役立ちます。教師と生徒は名前、性別、年齢のように多数の共通機能を共有しており、これらの機能を一度だけ定義すればいいので便利です。異なるクラスで、同じ機能を分けて定義することもでき、その機能の各定義は異なる名前空間に置かれます。例えば、生徒の挨拶は "Yo, I'm [firstName]" (例:Yo, I'm Sam) という形式とし、一方の教師の挨拶は、より形式的に "Hello, my name is [Prefix] [lastName], and I teach [Subject]." (例:Hello, My name is Mr Griffiths, and I teach Chemistry) のように。

+ +
+

: 同じ機能を複数のオブジェクトタイプが実装する能力のことを示す用語に、ポリモーフィズムがあります。不思議に感じているかも知れないので念のため。

+
+ +

子クラスのオブジェクトインスタンスを生成しましょう。例:

+ +

+ +

記事の続きでは、OOP 理論が JavaScript でどのように実践されているかを見ていきます。

+ +

コンストラクターとオブジェクトインスタンス

+ +

JavaScript では、オブジェクトやその機能を定義し初期化するためにコンストラクター関数と呼ばれる特殊な関数を使用します。これは便利です。なぜならオブジェクトをいくつ作成することになるか分からない状況に出くわすでしょうから。コンストラクターは必要な数のオブジェクトを効率的な方法で作成し、必要に応じてデータや関数を付加する手段を提供します。

+ +

JavaScript でコンストラクターを通じてクラスを作り、そこからオブジェクトのインスタンスを生成するところを見ていきましょう。まずは、最初のオブジェクトの記事で見た oojs.html ファイルの新しいコピーを、ローカルに作成したおいてください。

+ +

シンプルな例

+ +
    +
  1. どのように通常の関数で人物を定義できるかを見てみるところから始めましょう。この関数を script 要素の中に加えてください。 + +
    function createNewPerson(name) {
    +  const obj = {};
    +  obj.name = name;
    +  obj.greeting = function() {
    +    alert('Hi! I\'m ' + obj.name + '.');
    +  };
    +  return obj;
    +}
    +
  2. +
  3. この関数を呼び出すことで、新しい人物を生成することができます。次の 3 行をブラウザーの JavaScript コンソールで試してみてください。 +
    const salva = createNewPerson('Salva');
    +salva.name;
    +salva.greeting();
    + これも十分上手くいっていますが、やや長ったらしいです。オブジェクトを生成したいと知っているなら、なぜ明示的に空のオブジェクトを生成し、返すことが必要なのでしょうか?幸いにも、 JavaScript はコンストラクター関数という形で、便利なショートカットを提供してくれます。早速作ってみましょう!
  4. +
  5. 前の関数を、以下のもので置き換えてください。 +
    function Person(name) {
    +  this.name = name;
    +  this.greeting = function() {
    +    alert('Hi! I\'m ' + this.name + '.');
    +  };
    +}
    +
  6. +
+ +

コンストラクター関数は、 JavaScript 版のクラスです。それは関数に期待される全ての機能を持っていますが、何も返さないし、明示的にオブジェクトを生成しもしないという点に注意してください。基本的には、プロパティとメソッドを定義するだけです。加えて、 this キーワードが使われていることにも注意してください。基本、オブジェクトインスタンスの 1 つが作成されるときにはいつでも、オブジェクトの name プロパティはコンストラクター呼び出しに渡される name 値と等しくなり、 greeting() メソッドもコンストラクター呼び出しに渡される name 値を使用します。

+ +
+

メモ: 通常、コンストラクター関数の名前は大文字で始まります。コードの中で、コンストラクター関数がより容易に認識されるようにするための慣習です。

+
+ +

では、オブジェクトを生成するために、どのようにコンストラクターを呼び出したらよいでしょうか?

+ +
    +
  1. 次の 2 行を、前のコードの続きに加えてください。 +
    let person1 = new Person('Bob');
    +let person2 = new Person('Sarah');
    +
  2. +
  3. コードを保存し、ブラウザーをリロードして、以下の 4 行を JavaScript コンソールに入れて試してみてください。 +
    person1.name
    +person1.greeting()
    +person2.name
    +person2.greeting()
    +
  4. +
+ +

素晴らしい!2 つの新しいオブジェクトが、異なる名前空間の下でページに格納されていることが確認できます。それらのプロパティとメソッドにアクセスするときには、 person1 または person2 を呼び出すことから始めなければなりません。中に含まれている機能は適切にパッケージ化されており、他の機能と衝突しないようになっています。しかしながら、それらは同じように name プロパティと greeting() メソッドが利用可能です。 2 つのオブジェクトはそれぞれ、生成されたときに割り当てられた、自身の name 値を使っていることに注意してください。これが this を使うことがとても重要である理由の 1 つであり、他の値ではなく、自身の値を使っているのです。

+ +

コンストラクターをもう一度呼び出してみましょう。

+ +
let person1 = new Person('Bob');
+let person2 = new Person('Sarah');
+ +

いずれのケースでも、新しいオブジェクトインスタンスを生成したいとブラウザーに伝えるために new キーワードが使われており、その後に、括弧に必要なパラメーターを入れた関数名が続き、その結果が変数に格納されていて、一般的な関数の呼ばれ方とよく似ています。どちらのインスタンスも、次の定義によって生成されています。

+ +
function Person(name) {
+  this.name = name;
+  this.greeting = function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  };
+}
+ +

新しいオブジェクトが生成された後、 person1 および person2 変数は、次のオブジェクトを格納しています。

+ +
{
+  name: 'Bob',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+
+{
+  name: 'Sarah',
+  greeting: function() {
+    alert('Hi! I\'m ' + this.name + '.');
+  }
+}
+ +

コンストラクター関数を呼び出すとき、毎回 greeting() メソッドを定義していることに注意してください。これは理想的ではありません。これを回避するために、代わりにプロトタイプに関数を定義することができます。後で見てみましょう。

+ +

最終的なコンストラクターの作成

+ +

上で見てきた例は、スタートのためのシンプルな例に過ぎません。次は最終的な Person() コンストラクター関数を作りましょう。

+ +
    +
  1. ここまでに挿入したコードを削除し、代わりとなるコンストラクターを追加してください。これはシンプルな例とほぼ同じもので、ほんのわずか複雑になっているだけです。 +
    function Person(first, last, age, gender, interests) {
    +  this.name = {
    +     first : first,
    +     last : last
    +  };
    +  this.age = age;
    +  this.gender = gender;
    +  this.interests = interests;
    +  this.bio = function() {
    +    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    +  };
    +  this.greeting = function() {
    +    alert('Hi! I\'m ' + this.name.first + '.');
    +  };
    +}
    +
  2. +
  3. ではその下に、コンストラクターからオブジェクトインスタンスを生成するため、次の行を追加してください。 +
    let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
    +
  4. +
+ +

ちょうど以前行ったように、プロパティやメソッドにアクセスできることを確認できます。 JavaScript コンソールの中でやってみましょう。

+ +
person1['age']
+person1.interests[1]
+person1.bio()
+// etc.
+ +
+

メモ: もしこの工程で何らかのトラブルがあった場合は、あなたのコードを我々のバージョン (oojs-class-finished.htmlライブサンプルも) と比べてみてください。

+
+ +

さらなる練習

+ +

まずはじめに、さらにいくつかのオブジェクトを生成する独自の行を追加し、オブジェクトインスタンスのメンバーの取得や設定をしてみてください。

+ +

加えて、 bio() メソッドにはいくつかの問題点があります。人物が女性である、あるいは他の優先される性別分類の場合でも、その出力には常に "He" という代名詞が含まれています。また、 bio は interests 配列により多くのものが列挙されていても、2 つの趣味しか含みません。このクラス定義 (コンストラクター) の問題を、あなたはどのように修正することができますか?コンストラクター内に任意のコード (恐らく、いくつかの条件分岐やループが必要となるでしょう) を入れてみてください。性別や、趣味の数が 1、2、あるいは 2 よりも多いかどうかによって、文がどのように構築されるべきか考えてみてください。

+ +
+

: もし行き詰まってしまった場合は、GitHub に答えとなるリポジトリ (ライブ) があります。最初はあなた自身で書いてみてください!

+
+ +

オブジェクトインスタンスを生成する他の方法

+ +

ここまで、オブジェクトインスタンスを生成する 2 つの異なる方法を見てきました。オブジェクトリテラルの宣言と、上で見たコンストラクター関数の使用です。

+ +

これで十分かもしれませんが、他にも方法はあります。ウェブを巡る際に遭遇したときに備えて、よく知っておいてください。

+ +

Object() コンストラクター

+ +

まず最初に、 Object() コンストラクターを新しいオブジェクトの生成のために使うことができます。はい、一般的なオブジェクトにも、空のオブジェクトを生成するコンストラクターがあります。

+ +
    +
  1. このコードを JavaScript コンソールに入力してみましょう。 +
    let person1 = new Object();
    +
  2. +
  3. person1 変数に空のオブジェクトが格納されました。このオブジェクトに、ドット記法とブラケット記法を使ってプロパティを追加することができます。次の例を JavaScript コンソールで試してみましょう。 +
    person1.name = 'Chris';
    +person1['age'] = 38;
    +person1.greeting = function() {
    +  alert('Hi! I\'m ' + this.name + '.');
    +};
    +
  4. +
  5. あらかじめプロパティやメソッドを設定するため、Object() コンストラクターに引数としてオブジェクトリテラルを渡すことも可能です。次のコードを JavaScript コンソールで試してみてください。 +
    let person1 = new Object({
    +  name: 'Chris',
    +  age: 38,
    +  greeting: function() {
    +    alert('Hi! I\'m ' + this.name + '.');
    +  }
    +});
    +
  6. +
+ +

create() メソッドの使用

+ +

コードの順序についてもコンストラクターが助けとなります。コンストラクターを一箇所で作っておくと、必要に応じてインスタンスを生成することができ、それらがどこから来たものであるか、明瞭です。

+ +

しかしながら、特に少数のインスタンスのみを生成する場合に、最初にコンストラクターを作らずにインスタンスを生成することを好む人もいます。JavaScript にはそれを可能とする、create() と呼ばれる組み込みメソッドがあります。それにより、既存のオブジェクトを基にして、新しいオブジェクトを生成することができます。

+ +
    +
  1. 前のセクションの練習をブラウザーで終えた状態で、こちらを JavaScript コンソールで試してみてください。 +
    let person2 = Object.create(person1);
    +
  2. +
  3. 次は以下のコードです。 +
    person2.name;
    +person2.greeting();
    +
  4. +
+ +

person1 を基に person2 が生成され、person2 では同じプロパティとメソッドが利用可能であることを確認することができます。

+ +

create() には、IE8 が対応していないという制限があります。つまり、コンストラクターは古いブラウザーに対応したい場合により効果的かもしれません。

+ +

いずれ、create() の効果についてより詳細に紹介するつもりです。

+ +

あなたのスキルをテストしてみましょう!

+ +

この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するために、さらにいくつかのテストを見つけることができます。あなたのスキルをテストする: オブジェクト指向 JavaScript を参照してください。

+ +

この一連のテストは次の記事で紹介する知識に依存していることに注意してください。なので、試してみる前に、まずそれを読んでみるといいかもしれません。

+ +

まとめ

+ +

この記事はオブジェクト指向の理論の概略を見てきました。これですべてではありませんが、ここで扱っていることに関する考えを提示しました。加えて、オブジェクトのインスタンスを生成する様々な方法を見始めたところです。

+ +

次の記事では、 JavaScript オブジェクトのプロトタイプについて紹介します。

+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/javascript/objects/object_building_practice/index.html b/files/ja/learn/javascript/objects/object_building_practice/index.html new file mode 100644 index 0000000000..af94a8eede --- /dev/null +++ b/files/ja/learn/javascript/objects/object_building_practice/index.html @@ -0,0 +1,314 @@ +--- +title: オブジェクト構築の練習 +slug: Learn/JavaScript/Objects/Object_building_practice +tags: + - Article + - Beginner + - Canvas + - CodingScripting + - Guide + - JavaScript + - Learn + - Objects + - Tutorial + - 'l10n:priority' +translation_of: Learn/JavaScript/Objects/Object_building_practice +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}
+ +

ここまでの記事で JavaScript オブジェクトの根幹部に関する理論と文法の詳細についてすべてを見てきて、始めていくのに十分な基礎固めをしました。この記事では実練習を行ない、独自の JavaScript オブジェクトを作っていくための実践をしていきましょう — 楽しくてカラフルなものを。

+ + + + + + + + + + + + +
前提条件:基礎的なコンピューターの知識、HTML と CSS への基本的な理解、基礎的な JavaScript の理解 (JavaScript の第一歩JavaScript の構成要素を参照) とオブジェクト指向JavaScript の基本 (JavaScript オブジェクトの基本を参照)。
目的:オブジェクトの使い方とオブジェクト指向のテクニックを実世界のコンテストで練習する。
+ +

ボールを弾ませよう

+ +

この記事では伝統的な「弾むボール」のデモを作ってみて、JavaScript でどれほどオブジェクトが役に立つかお見せしましょう。小さなボールは画面じゅうを跳ねまわり、それぞれがぶつかると色が変わります。完成したものはこんな風に見えることでしょう:

+ +

+ +
    +
+ +

この例では画面にボールを描くのに Canvas API を使い、画面をアニメーションさせるのに requestAnimationFrame を使います — これらの API について事前の知識は不要です。この記事を読み終わる頃にはこれら API についてもっと知りたくなっているだろうと期待してますが。道中では、イカしたオブジェクトを活用して、ボールを壁で弾ませる、それぞれがぶつかった事を判定する(衝突判定という呼び名で知られています)といった上手いテクニックをいくつかお見せしていきます。

+ +

始めに

+ +

始める前に index.html, style.css, と main.js ファイルのローカルコピーを作成してください。これらにはそれぞれ、以下が含まれています:

+ +
    +
  1. とても簡素な HTML文書で、{{HTMLElement("h1")}} 要素と、ボールを描画するための {{HTMLElement("canvas")}} 要素と、この HTML に CSS と JavaScript を適用するための要素だけからなります。
  2. +
  3. とても簡単なスタイル、主には<h1>のスタイルとポジションを指定し、スクロールバーやページ端周辺のマージンを消す(素敵にきれいに見せるため)ためのもの。
  4. +
  5. <canvas>要素を設定し、これから使うことになる汎用の関数を提供する若干の JavaScript。
  6. +
+ +

スクリプトの最初の部分はこんな具合です:

+ +
const canvas = document.querySelector('canvas');
+
+const ctx = canvas.getContext('2d');
+
+const width = canvas.width = window.innerWidth;
+const height = canvas.height = window.innerHeight;
+ +

このスクリプトでは<canvas>要素への参照を取得し、これに対して getContext() メソッドを使って描画していくためのコンテキストを取得します。得られる定数 (ctx) はキャンバスの描画可能領域を直接表現しており、ここに二次元の形状を書き込む事ができます。

+ +

次に widthheight 二つの定数をセットし、キャンバス要素の幅と高さ(canvas.widthcanvas.height プロパティで表わされます)をブラウザーのビューポートの幅と高さ(ウェブページが表示される領域です — {{domxref("Window.innerWidth")}} と{{domxref("Window.innerHeight")}} プロパティから取得できます)に等しくします。

+ +

変数値をさっと全部同じにするのに、代入が連鎖している事に注意してください — これで全く問題ありません。

+ +

初期化スクリプトの最後の部分はこんなのです:

+ +
function random(min, max) {
+  const num = Math.floor(Math.random() * (max - min + 1)) + min;
+  return num;
+}
+ +

この関数は二つの数を引数に取り、二つ数の範囲内の乱数を戻します。

+ +

我々のプログラム用のボールを一つモデル化する

+ +

我々のプログラムでは画面中を跳ねまわるたくさんのボールがあります。これらのボールはどれも同じルールで動くので、1つのオブジェクトで表わすのが理に叶っています。まずはコードの最後に以下のコンストラクターを追加するところから始めましょう。

+ +
function Ball(x, y, velX, velY, color, size) {
+  this.x = x;
+  this.y = y;
+  this.velX = velX;
+  this.velY = velY;
+  this.color = color;
+  this.size = size;
+}
+ +

ここではいくつかの引数を用意し、我々のプログラムの中で個々のボールが動作するのに必要なプロパティを定義しています:

+ + + +

これはプロパティを取り扱いましたが、メソッドはどうしましょう? プログラムの中ではボールに実際に何かさせたいわけです。

+ +

ボールを描画する

+ +

まず以下の draw() メソッドを Ball() のプロトタイプ(prototype)に追加しましょう:

+ +
Ball.prototype.draw = function() {
+  ctx.beginPath();
+  ctx.fillStyle = this.color;
+  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
+  ctx.fill();
+}
+ +

この関数を使って、以前定義した 2D キャンバスコンテキスト(ctx)のメンバーを順に呼び出す方法で、ボール自身が画面に自分を描画する方法を教え込みます。コンテキストは紙のようなもので、ペンを使って何か描くように指示したいわけです:

+ + + +

これでオブジェクトをテストしてみられるようになりました。

+ +
    +
  1. コードを保存し、HTML ファイルをブラウザーで読み込みます。
  2. +
  3. ブラウザーの JavaScript コンソールを開いて、ページをリフレッシュし、キャンバスのサイズがコンソール分小さくなったビューポート領域に合うようにします。
  4. +
  5. 次をタイプして、新しいボールのインスタンスを作成します: +
    let testBall = new Ball(50, 100, 4, 4, 'blue', 10);
    +
  6. +
  7. そのメンバを呼び出して見てください: +
    testBall.x
    +testBall.size
    +testBall.color
    +testBall.draw()
    +
  8. +
  9. 最後の行を入力すると、キャンバスのどこかにボールが表示されたはずです。
  10. +
+ +

ボールのデータを更新する

+ +

ボールを座標に表示できるようになりましたが、ボールを実際に移動させるには、何らかの更新するための関数が必要です。JavaScript ファイルの最後に以下のコードを追加し、update() メソッドを Ball()prototype に追加します:

+ +
Ball.prototype.update = function() {
+  if ((this.x + this.size) >= width) {
+    this.velX = -(this.velX);
+  }
+
+  if ((this.x - this.size) <= 0) {
+    this.velX = -(this.velX);
+  }
+
+  if ((this.y + this.size) >= height) {
+    this.velY = -(this.velY);
+  }
+
+  if ((this.y - this.size) <= 0) {
+    this.velY = -(this.velY);
+  }
+
+  this.x += this.velX;
+  this.y += this.velY;
+}
+ +

関数の頭から 4 つの部分でボールがキャンバスの端に達したかどうかチェックします。もしそうであれば、関連する速度の向きを反転してボールが反対の向きに移動するようにします。つまり例えば、ボールが上方向に移動していたならば(velY が正)、垂直方向の速度をボールが下方向に移動するように変更します(velY を負に)。(訳注: 左上が原点、右下が座標の正方向ならば、ボールが上に移動する時の velY は負のはずだけど…)

+ +

4 つの場合で、次のことを確認しています:

+ + + +

それぞれの場合で計算にボールの size を含めていますが、これは x/y座標はボールの中心ですが、ボールの端のところで周囲から跳ね返って欲しいからです — 跳ね返る前に画面外にめり込んで欲しくないからです。

+ +

最後の二行では velXx 座標に、velYy 座標に加算しています — 結果ボールはこのメソッドが呼ばれる毎に移動します。

+ +

とりあえずはここまでで、ちょいとアニメーションさせてみよう!

+ +

ボールのアニメーション

+ +

さあ、楽しい事をやりましょう。では、キャンバスにボールを追加し、アニメーションさせるところから始めましょう。

+ +
    +
  1. 最初に、ボールを全部保存しておく場所がどこかに必要です。以下がこれをやってくれます — あなたのコードの最後に追加してください: +
    let balls = [];
    +
    +while (balls.length < 25) {
    +  let size = random(10,20);
    +  let ball = new Ball(
    +    // ball position always drawn at least one ball width
    +    // away from the edge of the canvas, to avoid drawing errors
    +    random(0 + size,width - size),
    +    random(0 + size,height - size),
    +    random(-7,7),
    +    random(-7,7),
    +    'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')',
    +    size
    +  );
    +
    +  balls.push(ball);
    +}
    + +

    while ループは、我々の random()関数で作成したランダムな値を使った新しい Ball() のインスタンスを作成し、ボールの配列の後ろに push() して追加していきますが、これは配列中のボールの数が 25 に満たない間まで繰り返されます。balls.length < 25 の数字をいろいろ変えれば表示されるボールの数を増やしたり減らしたりできます。あなたのコンピューターとブラウザーがどれだけ速いかによりますが、ボールを数千にするとアニメーションはかなり遅くなります! 注意してね。

    +
  2. +
  3. 以下をあなたのコードの末尾に追加してください: +
    function loop() {
    +  ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
    +  ctx.fillRect(0, 0, width, height);
    +
    +  for (let i = 0; i < balls.length; i++) {
    +    balls[i].draw();
    +    balls[i].update();
    +  }
    +
    +  requestAnimationFrame(loop);
    +}
    + +

    ものをアニメーションさせるすべてのプログラムには、大概アニメーションループがあり、プログラム内の情報を更新して、アニメーションの各フレームでその結果を表示します。これは大半のゲームや類似するプログラムの基本になります。コード中の loop() 関数は以下の事を行ないます:

    + +
      +
    • キャンバスの塗り潰し色を半透明の黒にし、その色でキャンバスの幅と高さいっぱいの長方形を fillRect() で描きます(これの 4 つの引数は始点の座標と、描画する長方形の幅と高さになります)。これで次のフレームを描く前に、前のフレームで描いた内容を見えなくします。これをしないと、ボールじゃなくて長い蛇がキャンバスの中を這い回る様を見る事になります! 塗り潰す色は半透明の rgba(0,0,0,0.25) なので、以前の何フレーム分かがかすかに残り、ボールが移動した後の軌跡を表現します。もし 0.25 を 1 に変更すると、軌跡は全く見えなくなります。この値を変えて、どんな効果になるか見てみてください。
    • +
    • ループで balls配列のボール全部をなめてそれぞれのボールの draw()update() 関数を実行し、それぞれを画面に描画してから、次のフレームに備えて必要な位置と速度の更新を行います。
    • +
    • この関数を requestAnimationFrame() メソッドを使って再実行します — このメソッドが繰り返し実行され同じ関数名を与えられると、その関数がスムースなアニメーションを行なうために毎秒設定された回数実行されます。これはたいてい再帰的に行われます — つまり関数は毎回その関数自身を呼び出すので、何度も何度も繰り返し実行されます。
    • +
    +
  4. +
  5. 最後に、あなたのコードの最後に次の行を追加します — アニメーションを開始するために、一旦は関数を呼ぶ必要があるのです。 +
    loop();
    +
  6. +
+ +

基本としてはこんなところ — セーブしてリフレッシュして、ボールがはずむのをテストしてみてください!

+ +

衝突判定を追加する

+ +

さあ、もうちょっと面白くするため、プログラムに衝突判定を追加して、ボールに他のボールとぶつかったらどうするのか教えましょう。

+ +
    +
  1. 最初に、以下のメソッド定義を update() メソッドを定義した箇所(つまり Ball.prototype.update ブロック)の下に追加します + +
    Ball.prototype.collisionDetect = function() {
    +  for (let j = 0; j < balls.length; j++) {
    +    if (!(this === balls[j])) {
    +      const dx = this.x - balls[j].x;
    +      const dy = this.y - balls[j].y;
    +      const distance = Math.sqrt(dx * dx + dy * dy);
    +
    +      if (distance < this.size + balls[j].size) {
    +        balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')';
    +      }
    +    }
    +  }
    +}
    +
  2. +
  3. +

    このメソッドはちょっとばかり複雑なので、今はどんな動作をしているのか正確に理解できなくても構いません。説明していきます:

    + +
      +
    • それぞれのボールで、他のボールそれぞれとこのボールが衝突していないか調べなければなりません。そのために、balls[]配列すべてのボールを回すために別の for ループを始めます。
    • +
    • 内側のループに入ってすぐ、if文でループで回しているボールがチェックしているボールと同じか調べています。ボールがそれ自体とぶつかっているかチェックしたくないですから! これのために、現在のボール(collisionDetect メソッドが実行されているボールです)がループ中のボール(現在の collisionDetect メソッド内のループのくりかえし中で参照されているボール)と一致しているかチェックします。!を使って等価性チェックを逆にしているので、if 文の中のコードはボールが同じでないときだけ実行されます。
    • +
    • そして二つの円が衝突していないか調べるための一般的なアルゴリズムを使っています。基本的には円ないの領域が重なっているかチェックしています。これについて詳しくは 2次元の衝突判定で解説されています。
    • +
    • もし衝突が検出されたら、内側の if文の中のコードが実行されます。この場合では、両方のボールの color プロパティをランダムな新しい色に設定しているだけです。もっと複雑なこと、現実っぽくボールを互いに跳ね返らせたりもできたでしょうが、これを実装したとするともっとずっとに複雑なったでしょう。そのような物理シミュレーションには、PhysicsJS, matter.js, Phaser などのゲームや物理用のライブラリを使う開発者が多いです。
    • +
    +
  4. +
  5. あなたはアニメーションの各フレーム毎にこのメソッドを呼ばなければなりません。以下を balls[i].update(); の行の後に追加してください: +
    balls[i].collisionDetect();
    +
  6. +
  7. 保存とデモのリフレッシュをして、ボールがぶつかった時に色が変わるのを見てください!
  8. +
+ +
+

注記: この例題を動かすのに困った時は、あなたの JavaScript コードを私たちの完成版と比べてみてください(ライブ実行版も見られます)。

+
+ +

まとめ

+ +

自分版の実世界で跳ね回るランダムボール例作り、この全単元で出てきた様々なオブジェクトやオブジェクト指向テクニックを使ったものをあなたに楽しんでいただけていれば、と思います。オブジェクトの実践的な使い方の練習や、実世界のコンテキストについて得られるものがあったはずです。

+ +

オブジェクトに関する記事は以上です — 残るのは、あなが自分のスキルをオブジェクトの評価問題で試してみる事だけです。

+ +

参考文献

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/object_prototypes/index.html b/files/ja/learn/javascript/objects/object_prototypes/index.html new file mode 100644 index 0000000000..4e9419e49d --- /dev/null +++ b/files/ja/learn/javascript/objects/object_prototypes/index.html @@ -0,0 +1,314 @@ +--- +title: Object のプロトタイプ +slug: Learn/JavaScript/Objects/Object_prototypes +tags: + - Beginner + - CodingScripting + - JavaScript + - Learn + - OOJS + - OOP + - Object + - Prototype + - create() + - 'l10n:priority' + - コンストラクタ + - 記事 +translation_of: Learn/JavaScript/Objects/Object_prototypes +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}
+ +

プロトタイプは、JavaScript オブジェクトが互いに機能を継承するメカニズムです。この記事では、プロトタイプチェーンの仕組みを説明し、prototype プロパティを使って既存のコンストラクタにメソッドを追加する方法を見ていきます。

+ +
+

Note: この記事では、伝統的な JavaScript のコンストラクタとクラスを取り上げます。次の記事では、同じことを実現するためのより簡単な構文を提供する現代的な方法について話します - ECMAScript 2015 のクラスを参照してください。

+
+ + + + + + + + + + + + +
前提条件:JavaScript 関数の理解、JavaScript の基礎知識 (JavaScript の第一歩JavaScript の構成要素を参照)、OOJS の基礎 (JavaScript オブジェクトの基本を参照)
目的:JavaScript のオブジェクトのプロトタイプ、プロトタイプチェーンの動作方法、prototype プロパティに新しいメソッドを追加する方法を理解する。
+ +

プロトタイプベースの言語とは?

+ +

JavaScript はしばしばプロトタイプベースの言語として記述されます - 継承を提供するために、オブジェクトはメソッドやプロパティを継承するテンプレートオブジェクトとして機能する prototype オブジェクトを持つことができます。

+ +

オブジェクトのプロトタイプオブジェクトは、メソッドやプロパティを継承するプロトタイプオブジェクトを持つことができます。これはしばしばプロトタイプチェーンと呼ばれ、異なるオブジェクトが他のオブジェクトに定義されたプロパティやメソッドを持つ理由を説明しています。

+ +

JavaScript では、オブジェクトのインスタンスとプロトタイプ (コンストラクタの prototype プロパティから派生した __proto__ プロパティ) の間にリンクが張られており、プロパティとメソッドはプロトタイプの連鎖を辿って見つけられます。

+ +
+

Note: オブジェクトの prototype (Object.getPrototypeOf(obj) または非推奨の __proto__ プロパティで取得可能) とコンストラクタ関数のprototype プロパティの違いを理解することが重要です。

+ +

前者は各インスタンス上のプロパティ、後者はコンストラクタ上のプロパティです。つまり、Object.getPrototypeOf(new Foobar())Foobar.prototypeと同じオブジェクトを参照しています。

+
+ +

これを少し明確にするための例を見てみましょう。

+ +

プロトタイプオブジェクトの理解

+ +

ここでは、Person() コンストラクタを書き終えた例に戻ります - ブラウザで例を読み込んでください。前回の記事で紹介した oojs-class-further-exercises.html の例を使うことができます (ソースコードも参照してください)。

+ +

この例では、次のようにコンストラクタ関数を定義しています。

+ +
function Person(first, last, age, gender, interests) {
+
+  // property and method definitions
+  this.name = {
+    'first': first,
+    'last' : last
+  };
+  this.age = age;
+  this.gender = gender;
+  //...see link in summary above for full definition
+}
+ +

次に、このようなオブジェクトインスタンスを作成します。

+ +
let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
+ +

JavaScript コンソールに "person1." と入力すると、ブラウザがこのオブジェクトで利用可能なメンバ名でこれを自動補完しようとするはずです:

+ +

+ +

このリストでは、person1 のコンストラクタである Person() で定義されているメンバ - nameagegenderinterestsbiogreeting - が表示されています。しかし、他にも toStringvalueOf などのメンバがあり、これらのメンバは person1 の prototype オブジェクトの prototype オブジェクト (Object.prototype) で定義されています。

+ +

+ +

実際に Object.prototype で定義されている person1 のメソッドを呼び出すとどうなりますか?例えば

+ +
person1.valueOf()
+ +

valueOf() は、呼び出されたオブジェクトの値を返します。この場合、何が起こるかというと

+ + + +
+

Note: プロトタイプチェーンの中では、メソッドやプロパティはあるオブジェクトから別のオブジェクトにコピーされないことを再確認しておきましょう。これらのメソッドやプロパティは、上で説明したようにチェーンを上っていくことでアクセスされます。

+
+ +
+

Note: プロトタイプチェーンは、プロパティを取得している間のみ巡回されます。プロパティがオブジェクトに直接設定されたり削除されたりした場合は、プロトタイプチェーンは走査されません。

+
+ +
+

Note: ECMAScript 2015 以前は、オブジェクトの prototype に直接アクセスする方法は公式にはありませんでした - チェーン内のアイテム間の「リンク」は、JavaScript 言語の仕様で [[prototype]] と呼ばれる内部プロパティで定義されています ({{glossary("ECMAScript")}}}を参照してください)。

+ +

しかし、ほとんどの最新のブラウザでは、オブジェクトのコンストラクタのプロトタイプオブジェクトを含む __proto__ (アンダースコア2個分) というプロパティを提供しています。例えば、person1.__proto__person1.__proto__.__proto__ を試してみてください。

+ +

ECMAScript 2015 からは、Object.getPrototypeOf(obj) を介して間接的にオブジェクトのプロトタイプオブジェクトにアクセスすることができます。

+
+ +

prototypeプロパティ:継承されたメンバーが定義されている場所

+ +

では、継承されたプロパティとメソッドはどこに定義されているのでしょうか? Objectリファレンスページを見ると、左側に多数のプロパティとメソッドが表示されます。上のスクリーンショットでperson1オブジェクトで使用できた継承されたメンバーの数を超えています。いくつかは継承されており、一部は継承されていません。これはなぜでしょうか?
+
+ 上で述べたように、継承されたものは prototype プロパティ (サブネームスペースと呼ぶこともできます) で定義されたものであり、それは Object.prototype. で始まるものであって、Object. だけで始まるものではありません。prototype プロパティの値はオブジェクトであり、基本的には、プロトタイプチェーンのさらに下のオブジェクトに継承させたいプロパティやメソッドを格納するためのバケットです。
+
+ そのため、Object.prototype.toString()Object.prototype.valueOf() などは、Person() コンストラクタから作成された新しいオブジェクトインスタンスを含め、Object.prototype を継承するあらゆるオブジェクトタイプで利用できます。

+ +

Object.is()Object.keys() など、prototype バケット内で定義されていないメンバは、Object.prototype を継承するオブジェクトインスタンスやオブジェクトタイプには継承されません。これらは、Object() コンストラクタ自身でのみ利用可能なメソッド/プロパティです。

+ +
+

Note: コンストラクタ上で定義されたメソッドが、それ自体が関数であるというのは不思議な感じがします。

+ +

まあ、関数はオブジェクトの型でもあります。信じられないかもしれませんが、Function() のコンストラクタリファレンスを参照してください。

+
+ +
    +
  1. 既存のプロトタイプのプロパティを自分でチェックすることができます。先ほどの例に戻って、JavaScript コンソールに次のように入力してみてください +
    Person.prototype
    +
  2. +
  3. カスタムコンストラクタのプロトタイプに何も定義していないので、出力はあまり表示されません。デフォルトでは、コンストラクタの prototype は常に空から始まります。では、次のようにしてみてください +
    Object.prototype
    +
  4. +
+ +

先ほど示したように、Objectprototype プロパティに定義された多数のメソッドが、Object を継承するオブジェクトで利用できるようになっています。

+ +

プロトタイプチェーン継承の他の例は、JavaScript の至る所で見ることができます。例えば、StringDateNumberArray などのグローバルオブジェクトのプロトタイプに定義されているメソッドやプロパティを探してみてください。これらはすべて、プロトタイプに定義されたいくつかのメンバを持っており、例えばこのように文字列を作るとき

+ +
let myString = 'This is my string.';
+ +

myStringが最初から、split()indexOf()replace()などの便利なメソッドを多数持っている理由です。

+ +
+

Note: このセクションを理解して、もっと知りたいと思ったら、JavaScript でのプロトタイプの使用 についてのより詳細なガイドを読む価値があります。このセクションは、これらの概念に初めて出会ったときに少しでも理解しやすくするために、意図的に簡略化しています。

+
+ +
+

重要: prototype プロパティは JavaScript の中でも最も紛らわしい名前がついている部分の一つです (this__proto__ でアクセスできる内部オブジェクトです、覚えていますか?)。代わりに prototype は、継承したいメンバを定義したオブジェクトを含むプロパティです。

+
+ +

create() の再訪

+ +

先ほど、Object.create() メソッドを使用して新しいオブジェクトのインスタンスを作成する方法を紹介しました。

+ +
    +
  1. 例えば、先ほどの例の JavaScript コンソールでこれを試してみてください +
    let person2 = Object.create(person1);
    +
  2. +
  3. create() が実際に行うことは、指定したプロトタイプオブジェクトから新しいオブジェクトを作成することです。ここでは、person1 をプロトタイプオブジェクトとして使用して person2 を作成しています。これはコンソールで以下のように入力することで確認できます +
    person2.__proto__
    +
  4. +
+ +

これで person1 オブジェクトが返されます。

+ +

コンストラクタのプロパティ

+ +

すべてのコンストラクタ関数は prototype プロパティを持ち、その値は constructor プロパティを含むオブジェクトとなります。この constructor プロパティは、元のコンストラクタ関数を指します。

+ +

次のセクションでお分かりのように、Person.prototype プロパティ (あるいは上のセクションで述べたように、一般的にはコンストラクタ関数の prototype プロパティに定義されているオブジェクト) は、Person() コンストラクタを使用して作成されたすべてのインスタンスオブジェクトで利用可能になります。したがって、コンストラクタプロパティは person1person2 の両方のオブジェクトでも利用可能です。

+ +
    +
  1. 例えば、コンソールで次のコマンドを試してみてください +
    person1.constructor
    +person2.constructor
    + +

    これらのインスタンスの元の定義を含む Person() コンストラクタを返します。

    + +

    巧妙なトリックとしては、constructor プロパティの最後に括弧を付けて (必要なパラメータを含む)、そのコンストラクタから別のオブジェクトのインスタンスを作成することができます。コンストラクタは結局のところ関数なので、括弧を使用して呼び出すことができます。関数をコンストラクタとして使用したい場合は、new キーワードを含めて指定する必要があります。

    +
  2. +
  3. これをコンソールで試してみてください +
    let person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);
    +
  4. +
  5. では、新しいオブジェクトの機能にアクセスしてみましょう +
    person3.name.first
    +person3.age
    +person3.bio()
    +
  6. +
+ +

これはよく機能します。頻繁に使用する必要はありませんが、新しいインスタンスを作成したいときに、何らかの理由で元のコンストラクタへの参照が簡単に利用できない場合に非常に便利です。

+ +

constructor プロパティには他の用途もあります。たとえば、オブジェクトのインスタンスがあり、そのインスタンスのコンストラクタの名前を返したい場合は次のようにします。

+ +
instanceName.constructor.name
+ +

たとえば、これを試してみてください:

+ +
person1.constructor.name
+
+ +
+

Note: constructor.name の値は (プロトタイプの継承、バインディング、プリプロセッサ、トランスパイラなどによる) 変わる可能性があります。そのため、より複雑な例では、代わりに instanceof 演算子を使用することになります。

+
+ +
    +
+ +

プロトタイプの変更

+ +

コンストラクタ関数の prototype プロパティを変更する例を見てみましょう - メソッドは、コンストラクタから作成されたすべてのオブジェクトインスタンスで利用可能になります。この時点で、最後に Person() コンストラクタのプロトタイプに何かを追加します。

+ +
    +
  1. oojs-class-further-exercises.html の例に戻り、ソースコードのローカルコピーを作成します。既存の JavaScript の下に、コンストラクタの prototype プロパティに新しいメソッドを追加する次のコードを追加します + +
    Person.prototype.farewell = function() {
    +  alert(this.name.first + ' has left the building. Bye for now!');
    +};
    +
  2. +
  3. コードを保存してブラウザでページを読み込み、テキスト入力に以下のように入力してみてください +
    person1.farewell();
    +
  4. +
+ +

コンストラクタ内で定義されている人の名前を特徴とする警告メッセージが表示されるはずです。これは本当に便利ですが、さらに便利なのは継承チェーン全体が動的に更新され、コンストラクタから派生したすべてのオブジェクトインスタンスでこの新しいメソッドが自動的に利用できるようになったことです。

+ +

ちょっと考えてみましょう。このコードでは、コンストラクタを定義し、そのコンストラクタからインスタンスオブジェクトを作成し、コンストラクタのプロトタイプに新しいメソッドを追加しています。

+ +
function Person(first, last, age, gender, interests) {
+
+  // プロパティおよびメソッドを定義する
+
+}
+
+let person1 = new Person('Tammi', 'Smith', 32, 'neutral', ['music', 'skiing', 'kickboxing']);
+
+Person.prototype.farewell = function() {
+  alert(this.name.first + ' has left the building. Bye for now!');
+};
+ +

しかし、farewell() メソッドは person1 オブジェクトのインスタンスで利用可能です。そのメンバーは、新たに定義された farewell() メソッドを含むように自動的に更新されます。

+ +
+

Note: 逆に、コンストラクタのプロトタイプに定義されたプロパティを delete 演算子を使用して削除すると、他のすべてのクラスインスタンスからもそれぞれのプロパティが削除されます。

+ +

上記の例では、delete person1.__proto__.farewell または delete Person.prototype.farewell を実行すると、すべての Person インスタンスから farewell() メソッドが削除されます。

+ +

この問題を軽減するために、代わりに Object.defineProperty() を使用することができます。

+
+ +
+

Note: この例がうまく動作しない場合は、oojs-class-prototype.html の例を見てください (ライブでも参照してください) 。

+
+ +

このように定義されたプロパティは柔軟性に欠けるため、prototype プロパティで定義されることはほとんどありません。例えば、次のようなプロパティを追加することができます。

+ +
Person.prototype.fullName = 'Bob Smith';
+ +

これはその person がその名前で呼ばれていないかもしれないので、あまり柔軟性がありません。name.firstname.last から fullName を作成する方がずっと良いでしょう。

+ +
Person.prototype.fullName = this.name.first + ' ' + this.name.last;
+ +

しかし、これではうまくいきません。この場合、this は関数スコープではなくグローバルスコープを参照するからです。このプロパティを呼び出すと undefined を返します。これは、先ほどプロトタイプで定義したメソッドでは問題なく動作したのはそれがオブジェクトのインスタンススコープに正常に転送される関数スコープ内にあるためです。そのため、プロトタイプ上で不変の(つまりだれも変更する必要のない)プロパティを定義することもできますが、一般的にはコンストラクタ内でプロパティを定義する方がうまくいきます。

+ +

実際、多くのオブジェクト定義でよく見られるパターンは、コンストラクタ内でプロパティを定義し、プロトタイプ上でメソッドを定義することです。これにより、コンストラクタにはプロパティの定義のみが含まれ、メソッドは別のブロックに分割されるため、コードが読みやすくなります。例えば、以下のようになります。

+ +
// Constructor with property definitions
+
+function Test(a, b, c, d) {
+  // プロパティ定義
+}
+
+// 最初のメソッド定義
+
+Test.prototype.x = function() { ... };
+
+// 第二のメソッド定義
+
+Test.prototype.y = function() { ... };
+
+// など
+ +

このパターンは、Piotr Zalewa 氏の学校計画のアプリの例で実際に見られます。

+ +

あなたのスキルをテストしてみましょう!

+ +

この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するために、さらにいくつかのテストを見つけることができます。あなたのスキルをテストする: オブジェクト指向 JavaScript を参照してください。

+ +

この一連のテストは次の記事で紹介する知識に依存していることに注意してください。なので、試してみる前に、まずそれを読んでみるといいかもしれません。

+ +

まとめ

+ +

この記事では、プロトタイプオブジェクトチェーンによってオブジェクトが互いに機能を継承する方法、プロトタイププロパティとそれを使ってコンストラクタにメソッドを追加する方法など、JavaScript オブジェクトのプロトタイプを取り上げてきました。

+ +

次の記事では、2つのカスタムオブジェクト間で機能の継承を実装する方法を見ていきます。

+ +

{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/javascript/objects/test_your_skills_colon__object_basics/index.html b/files/ja/learn/javascript/objects/test_your_skills_colon__object_basics/index.html new file mode 100644 index 0000000000..d284729df3 --- /dev/null +++ b/files/ja/learn/javascript/objects/test_your_skills_colon__object_basics/index.html @@ -0,0 +1,101 @@ +--- +title: 'スキルテスト: オブジェクトの基本' +slug: 'Learn/JavaScript/Objects/Test_your_skills:_Object_basics' +translation_of: 'Learn/JavaScript/Objects/Test_your_skills:_Object_basics' +--- +
{{learnsidebar}}
+ +

このスキルテストの目的は、JavaScript オブジェクトの基本の理解度をテストすることです。

+ +
+

注意: 以下のインタラクティブなエディターでソリューションを試すこともできますが、コードをダウンロードし、CodePen, jsFiddleGlitchのようなオンラインツールを使用してタスクを実行すると役立つ場合があります。
+
+ 行き詰まった場合は、助けを求めてください —  このページの下部にある評価またはさらなる支援セクションを参照してください。

+
+ +
+

注意: 以下の例では、コードにエラーがある場合、ページの結果パネルに出力され、答えを見つけ出すのに役立ちます(ダウンロード可能なバージョンの場合は、ブラウザーのJavaScriptコンソールに)

+
+ +

オブジェクトの基本 1

+ +

このタスクでは、オブジェクトリテラルが与えられます。あなたのタスクは下記です。

+ + + +

以下のライブコードを更新して、完成した例を再現してみてください。

+ +

{{EmbedGHLiveSample("learning-area/javascript/oojs/tasks/object-basics/object-basics1.html", '100%', 400)}}

+ +
+

このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

+
+ +

オブジェクトの基本 2

+ +

次のタスクでは、お気に入りのバンドの1つを表す、自分だけのオブジェクトリテラルを作成してみましょう。必要な要素は次のとおりです。

+ + + +

albums 配列には、少なくとも2つのアルバムを含めること。

+ +

​これが終わったら、変数bandInfoに、名前、国籍、活動年数、スタイル、最初のアルバムのタイトルと発売日などの少しの詳細を書き込みます。

+ +

以下のライブコードを更新して、完成した例を再現してみてください。

+ +

{{EmbedGHLiveSample("learning-area/javascript/oojs/tasks/object-basics/object-basics2.html", '100%', 400)}}

+ +
+

このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

+
+ +

オブジェクトの基本 3

+ +

最後に、「オブジェクトの基本」のまとめとして、タスク#1のcatオブジェクトリテラルに戻りましょう。 「Hello, said Bertie the Cymric.」と記録されるように、greeting()メソッドを書き直してください。 ブラウザのDevToolsのコンソールにアクセスしますが、名前や品種に関係なく、同じ構造のすべてのcatオブジェクトで機能します。

+ +

完了したら、cat2という独自のオブジェクトを作成します。このオブジェクトは、同じ構造、まったく同じgreeting()メソッドを持ちますが、名前、品種、色が異なります。

+ +

両方のgreeting()メソッドを呼び出して、適切なあいさつ(greeting)がコンソールに記録されることを確認します。

+ +

コードはあまりDRYではありません(それぞれは1回だけ定義すること)—たとえば、同じメソッドを2回定義しています。 どうすればもっとDRYにすることができますか? よくわからない場合でも、心配しないでください。これは、シリーズの今後の記事で取り上げる予定です。

+ +

以下のライブコードを更新して、完成した例を再現してみてください。

+ +

{{EmbedGHLiveSample("learning-area/javascript/oojs/tasks/object-basics/object-basics3.html", '100%', 400)}}

+ +
+

このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

+
+ +

まとめとヘルプ

+ +

自分のコードの評価が欲しい、または行き詰まって助けを求めたい場合:

+ +
    +
  1. CodePen、jsFiddle、Glitchなどのオンライン共有可能なエディターで作業をします。コードを自分で作成することも、上記のセクションでリンクされているスターティングポイントファイルを使用することもできます。
  2. +
  3. MDNDiscourseフォーラムの学習カテゴリで評価や支援を求める投稿を書いてください。投稿には次のものを含める必要があります。
  4. +
+ + diff --git a/files/ja/learn/performance/business_case_for_performance/index.html b/files/ja/learn/performance/business_case_for_performance/index.html new file mode 100644 index 0000000000..106a517a8f --- /dev/null +++ b/files/ja/learn/performance/business_case_for_performance/index.html @@ -0,0 +1,83 @@ +--- +title: ウェブパフォーマンスのビジネスケース +slug: Learn/Performance/business_case_for_performance +tags: + - Web パフォーマンス + - Web 開発 +translation_of: Learn/Performance/business_case_for_performance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Performance/Mobile", "Learn/Performance")}}
+ +

{{draft}}

+ +

ここまで、ウェブパフォーマンスの重要性についてお話してきました。ウェブパフォーマンスを最適化するために何をすべきかを学びました。しかし、クライアントや経営陣にパフォーマンスに優先順位をつけて投資するように説得するにはどうすればよいのでしょうか?このセクションでは、意思決定者に投資をするように説得するための明確なビジネスケースの作成について説明します。

+ + + + + + + + + + + + +
前提条件:コンピュータリテラシーの基礎、クライアントサイドのウェブ技術の基礎知識、ウェブパフォーマンス最適化の基礎知識。
目標:クライアントや経営者に ウェブパフォーマンスを優先してもらい、自信を持って仕事ができるようになること。
+ +

パフォーマンスを経営の最優先事項にする

+ +

これまで、パフォーマンスに優先順位をつけることで、ユーザー体験を向上させ、その結果として収益を上げる方法について説明してきました。ウェブパフォーマンスを優先させないと、ビジネスの収益を失う可能性があることを知っています。この記事では、特定のビジネス指標がユーザーのウェブパフォーマンス体験にどのように直接関係しているか、ウェブパフォーマンスのユーザー体験を向上させるためにサービス設計を適用する方法について説明しています。また、累積的な経験がコンバージョン率やリテンション率にどのように影響するかを理解することの重要性を強調しています。

+ +
+
+ +

パフォーマンス予算

+ +

ウェブパフォーマンス予算を設定することで、チームがサイトを維持するための軌道に乗っているかどうかを確認し、回帰を防ぐのに役立ちます。パフォーマンスバジェットとは、維持しなければならない最大の http リクエスト数、すべてのアセットを合わせた最大の合計サイズ、特定のデバイスでの最小許容 FPS などの制限を指定するために設定される制限のセットです。予算は、単一のファイル、ファイルタイプ、ページに読み込まれたすべてのファイル、特定のメトリック、または一定期間のしきい値に適用することができます。

+ +

予算を定義して推進することで、マーケティング、セールス、さらにはビデオやサードパーティスクリプト、フレームワークを追加したいと考えている他の開発者など、競合する利害関係者に対抗して、優れたユーザーエクスペリエンスを提供するためのパフォーマンス推進者を支援することができます。パフォーマンス予算は、開発者チームがユーザーのために最適なパフォーマンスを保護し、ビジネスが新しい市場に参入してカスタム体験を提供できるようにするのに役立ちます。

+ +

key performance indicators

+ +

目標として主要業績評価指標(KPI)を設定することで、ビジネスの目標でもある業績目標を明確にすることができます。KPIは、ユーザーエクスペリエンスとパフォーマンスがビジネスのトップラインに与える影響を測定する上で重要なビジネスメトリクスのセットであると同時に、パフォーマンスに優先順位をつけることのメリットを示す方法でもあります。ここでは、検討すべき KPI をいくつか紹介します。

+ +
+
コンバージョン率 (CR)
+
購入の完了やニュースレターへの登録など、意図した行動をとったトラフィックの割合。ビジネスサイトの表示速度が遅いと、ユーザーが意図したタスクを完了できないことがあります。これは、コンバージョン率の低下につながる可能性があります。
+
Time on Site
+
集計したユーザーがサイトに費やす平均時間。サイトのパフォーマンスが低下すると、ユーザーはサイトを早期に放棄する可能性が高くなり、サイトのメトリクスにかかる時間が短くなる可能性があります。
+
ネットプロモーションスコア (NPS)
+
ネットプロモーションスコア (NPS) は、企業のブランド、製品、サービスに対する顧客の忠誠心を評価するための指標です。ユーザーのパフォーマンスが悪いと、ブランドの評判が悪くなります。
+
+ +

KPI としてコンバージョン率、サイト上の時間、および/またはネットプロモーションのスコアを設定すると、ウェブパフォーマンスの努力に財務および他のビジネス目標の価値を与え、努力の価値を証明するためのメトリクスを使用して、購入を後押しするのに役立ちます。

+ + + +
{{PreviousMenu("Learn/Performance/Mobile", "Learn/Performance")}}
+ +

このモジュール

+ + diff --git a/files/ja/learn/performance/index.html b/files/ja/learn/performance/index.html new file mode 100644 index 0000000000..070c09f1f1 --- /dev/null +++ b/files/ja/learn/performance/index.html @@ -0,0 +1,120 @@ +--- +title: Web パフォーマンス +slug: Learn/Performance +translation_of: Learn/Performance +--- +

{{LearnSidebar}}{{draft}}

+ +

Web サイトを構築するには、HTML、CSS、および JavaScript が必要です。人々が使用したい Web サイトやアプリケーションを構築し、ユーザを引き付けて維持するには、優れたユーザエクスペリエンスを作成する必要があります。良好なユーザエクスペリエンスの一部は、コンテンツの読み込みが迅速であり、ユーザの操作に反応することを保証することです。これは Web パフォーマンスと呼ばれ、このモジュールではパフォーマンスのよい Web サイトを構築するために必要なすべてを学習します。

+ +

Webパフォーマンスとは、客観的な測定値であり、ロード時間と実行時間に関するユーザーエクスペリエンスの評価です。 Webパフォーマンスとは、サイトがロードされて対話型で応答するまでにかかる時間、およびユーザーとの対話中のコンテンツの滑らかさです。スクロールはスムーズですか?ボタンはクリック可能ですか?ポップアップはすばやく開くことができますか?また、ポップアップはスムーズにアニメーション化されますか? Webパフォーマンスには、ロードにかかる時間、1秒あたりのフレーム数、インタラクティブにかかる時間などの客観的な測定値と、コンテンツのロードにかかったと感じる時間の主観的な経験値の両方が含まれます。
+
+ レイテンシ、アプリケーションサイズ、DOMノードの数、行われたリソースリクエストの数、JavaScriptのパフォーマンス、CPU負荷など、多くの機能がパフォーマンスに影響を与えます。ロードと応答時間を最小限に抑え、エクスペリエンスを可能な限り早くインタラクティブにできるようにすることで、レイテンシーを隠すための追加機能を追加し、エクスペリエンスの長いテール部分で非同期的にロードすることが重要です。
+
+ Webパフォーマンスの測定と改善に役立つツール、API、およびベストプラクティスがあります。これらもこのモジュールの過程で見ていきます。

+ +

学習経路

+ +

Webパフォーマンスの改善に関する多くの推奨事項を実装するにはHTML、CSS、およびJavaScriptを知っている必要がありますが、アプリケーションの構築方法を知っていることはWebパフォーマンスを理解および測定するための必須条件ではありません。
+
+ 以下の導入モジュールのいくつかはプログラミングの知識を必要としませんが、HTMLおよびパフォーマンスモジュールにはHTMLの理解が必要であり、CSSおよびパフォーマンスモジュールにはCSSの理解が必要です。導入モジュールを使用することをお勧めします。まず、最初に「Webパフォーマンスとは何か」から始めます。入門モジュールは、Webパフォーマンスの概要を提供します。最初の3つは、開発者であろうとプロジェクトマネージャーであろうと読む必要があると考えるべきです。技術トピックに焦点を当てたモジュールは、これらの技術を使用する開発者により適しています。
+
+ 高度なモジュールでは、入門モジュールで概要を説明したトピックをさらに深く掘り下げ、パフォーマンスAPI、テストおよび分析ツール、パフォーマンスのボトルネックの概要を提供します。
+
+ このトピックに進む前に、「Web入門」を完了することをお勧めします。ただし、そうすることは必ずしも必要ではありません。

+ +

Introductory modules

+ +

このトピックには、次のモジュールが含まれています。必ず最初のものから始めてください。

+ +
+
Webパフォーマンスとは何ですか?
+
この記事では、実際のパフォーマンスとは何かを詳しく説明することから始めます。これには、パフォーマンスを考える際に考慮する必要があるツール、メトリック、API、ネットワーク、人々のグループ、およびパフォーマンスをWeb開発ワークフローの一部にする方法が含まれます。
+
ユーザーはパフォーマンスをどのように知覚しますか?
+
ミリ秒単位のWebサイトの速度よりも重要なのは、ユーザーがサイトを認識する速度です。これらの認識は、実際のページの読み込み時間、アイドリング、ユーザーインタラクションへの応答性、スクロールやその他のアニメーションの滑らかさの影響を受けます。この記事では、実際のタイミングではなくても、ユーザーの認識を改善するためのベストプラクティスとともに、さまざまな読み込みメトリック、アニメーション、応答性メトリックについて説明します。
+
Webパフォーマンスの基本
+
+

HTML、CSS、JavaScript、およびメディアファイルのフロントエンドコンポーネントに加えて、アプリケーションを遅くできる機能と、アプリケーションを主観的および客観的に高速化できる機能があります。 Webパフォーマンスに関連する多くのAPI、開発者ツール、ベストプラクティス、および悪いプラクティスがあります。ここでは、これらの機能の多くを基本レベルで紹介し、各トピックのパフォーマンスを改善するためのより深いダイブへのリンクを提供します。

+
+
HTMLパフォーマンス機能
+
+

一部の属性とマークアップのソースの順序は、パフォーマンスまたはWebサイトに影響を与える可能性があります。 DOMノードの数を最小限に抑え、スタイル、スクリプト、メディア、サードパーティスクリプトなどのコンテンツを含めるために最適な順序と属性が使用されるようにすることで、ユーザーエクスペリエンスを大幅に改善できます。この記事では、パフォーマンスを最大限に高めるためにHTMLを使用する方法について詳しく説明します。

+
+
マルチメディア:画像とビデオ
+
+

多くの場合、Webパフォーマンスの最も低い成果はメディアの最適化です。各ユーザーエージェントの機能、サイズ、ピクセル密度に基づいて異なるメディアファイルを提供することが可能です。バックグラウンドビデオからオーディオトラックを削除するなどの追加のヒントは、パフォーマンスをさらに向上させることができます。この記事では、ビデオ、オーディオ、画像のコンテンツがパフォーマンスに与える影響と、その影響を最小限に抑える方法について説明します。

+
+
レスポンシブ画像
+
+

画像を最適化することは、高性能なメディアリッチユーザーエクスペリエンスに不可欠ですが、画像をダウンロードするデバイスに合わせて適切なサイズにすることは特に重要です。この記事では、効率的な画像配信における<picture>要素やsrcset属性などのネイティブブラウザー機能の役割と、それらを自信を持って使用する方法について説明します。

+
+
組み込みのプロファイラーを使用したプロファイリング
+
Firefoxの組み込みプロファイラーでアプリのパフォーマンスをプロファイリングする方法を学びます。
+
代替メディア形式
+
画像やビデオに関しては、おそらくあなたが知っているよりも多くのフォーマットがあります。これらの形式の中には、ファイルサイズをさらに削減することにより、高度に最適化されたメディアリッチページをさらに活用できるものがあります。このガイドでは、いくつかの代替メディア形式、サポートされていないブラウザが寒さの中に置き去りにされないように責任を持って使用する方法、および既存のアセットをトランスコードするための高度なガイダンスについて説明します。
+
CSSパフォーマンス機能
+
CSSは、パフォーマンスを向上させるためにそれほど重要ではない最適化の焦点となる場合がありますが、他のCSSよりもパフォーマンスに影響を与えるCSS機能がいくつかあります。この記事では、パフォーマンスに影響を与えるいくつかのCSSプロパティを検討し、パフォーマンスが悪影響を受けないようにスタイルを処理する方法を提案しました。
+
JavaScriptパフォーマンスのベストプラクティス
+
+

JavaScriptを適切に使用すると、インタラクティブで没入型のWebエクスペリエンスを実現できます。または、ダウンロード時間、レンダリング時間、アプリ内パフォーマンス、バッテリー寿命、ユーザーエクスペリエンスに大きな悪影響を与える可能性があります。この記事では、複雑なコンテンツであっても可能な限りパフォーマンスを高めるために考慮すべきJavaScriptのベストプラクティスの概要を説明します。

+
+
Webフォントのパフォーマンス
+
+

パフォーマンスのランドスケープで見落とされることが多いのは、Webフォントです。 WebフォントはWebデザインにおいてこれまで以上に目立っていますが、多くの開発者は単にサードパーティのサービスからフォントを埋め込み、それについて何も考えていません。この記事では、効率的なファイル形式とサブ設定を使用して、フォントファイルをできるだけ小さくする方法について説明します。そこから、ブラウザのテキストのしくみ、CSSとJavaScriptの機能を使用してフォントをすばやくレンダリングし、ユーザーエクスペリエンスの中断を最小限に抑える方法について説明します。

+
+
モバイル性能
+
+

モバイルデバイスでのWebアクセスは非常に人気があり、すべてのモバイルプラットフォームは本格的なWebブラウザーを備えていますが、帯域幅、CPU、およびバッテリーの寿命が制限されている可能性があるため、これらのプラットフォームでのWebコンテンツのパフォーマンスを考慮することが重要です。この記事では、モバイル固有のパフォーマンスに関する考慮事項について説明します。

+
+
+ + + +

Advanced Modules

+ +
+
Populating the page
+
HTTPリクエストが行われ、可能なら、数秒後にサイトが表示されます。コンテンツを表示するには、JavaScriptを実行し、DOMを変更し、スタイルを計算し、レイアウトを計算し、最後にコンテンツをレンダリングします。これには、ペイントと合成が含まれ、GPUアクセラレーションが別のスレッドに含まれます。
+
パフォーマンスのボトルネック
+
+
レイテンシを理解する
+
+

レイテンシとは、ブラウザーがリソースを要求してから、ブラウザーが要求されたリソースの最初のバイトを受信するまでにかかる時間です。この記事では、レイテンシとは何か、それがパフォーマンスに与える影響、レイテンシを測定および改善する方法について説明します。

+
+
帯域幅について
+
+

帯域幅は、1秒間に送信できるデータの量(MbpsまたはKbpsで測定)です。この記事では、メディアリッチインターネットアプリケーションにおける帯域幅の役割、測定方法、利用可能な帯域幅を最大限に活用するためにアプリケーションを最適化する方法について説明します。

+
+
HTTP / 2とあなた
+
+

トランスポート層(つまりHTTP)はWebの機能に不可欠であり、HTTP / 2の形で大きな更新が行われたのは比較的最近になってからです。すぐに使用できるHTTP / 2は、以前のバージョンよりも多くのパフォーマンスの改善と利点を提供しますが、状況を変えます。この記事では、HTTP / 2が何をするのか、そしてアプリケーションをさらに微調整してさらに前進させる方法を学びます。

+
+
パフォーマンスにおけるTLSの役割
+
+

TLS(またはHTTPSと呼ばれる傾向がある)は、安全で安全なユーザーエクスペリエンスを作成するために重要です。ハードウェアはTLSがサーバーのパフォーマンスに与える悪影響を軽減しましたが、ブラウザーがサーバーに接続するのを待つ時間のかなりの部分を占めています。この記事では、TLSハンドシェイクプロセスについて説明し、OCSPステープリング、HSTSプリロードヘッダー、サードパーティのTLSレイテンシをマスクするリソースヒントの潜在的な役割など、この時間を短縮するためのヒントを提供します。

+
+
組み込みのプロファイラーを使用したプロファイリング
+
Firefoxの組み込みプロファイラーでアプリのパフォーマンスをプロファイリングする方法を学びます。
+
パフォーマンスチャートを読む
+
開発者ツールは、パフォーマンス、メモリ、およびネットワーク要求に関する情報を提供します。ブラウザ開発ツールのウォーターフォールチャート、コールツリー、トレース、フレームチャート、および割り当ての読み方を知っていると、他のパフォーマンスツールのウォーターフォールチャートとフレームチャートを理解するのに役立ちます。
+
CSSおよびJavaScriptアニメーションのパフォーマンス
+
アニメーションは、楽しいユーザーエクスペリエンスにとって重要です。この記事では、CSSとJavaScriptベースのアニメーションのパフォーマンスの違いについて説明します。
+
JavaScriptバンドルの分析
+
間違いなく、JavaScriptは現代のWeb開発の大きな部分を占めています。アプリケーションで使用するJavaScriptの量を減らすよう常に努力する必要がありますが、どこから始めればよいかを知ることは困難です。このガイドでは、アプリケーションのスクリプトバンドルを分析し、使用しているものを把握する方法と、アプリのバンドル間でスクリプトが重複しているかどうかを検出する方法を示します。
+
動的インポートを使用したJavaScriptのLazy-load
+
開発者は「lazy loading」という用語を聞くと、ビューポートにスクロールするときに読み込まれるスクロールせずに見える画像をすぐに思い浮かべます。しかし、JavaScriptもlazy loadできることを知っていましたか?このガイドでは、動的import()ステートメントについて説明します。これは、JavaScriptモジュールをオンデマンドでロードする最新のブラウザーの機能です。もちろん、この機能はどこでも利用できるわけではないため、この機能を広く互換性のある方法で使用するようにツールを構成する方法も示します。
+
+ +
+
リソースヒントを使用したリソース配信の制御
+
ブラウザは、リソースの優先順位付けと配信に関して、私たちよりもよく知っていますが、千里眼からはほど遠いです。ネイティブブラウザー機能により、ブラウザーが別のサーバーに接続するタイミングを示唆したり、ブラウザーが必要とする前にリソースをプリロードしたりできます。賢明に使用すると、これにより高速なエクスペリエンスがさらに速く見えるようになります。この記事では、rel = preconnect、rel = dns-prefetch、rel = prefetch、rel = preloadなどのネイティブブラウザー機能と、それらを活用する方法について説明します。
+
+ +

See Also

+ + + +

{{LandingPageListSubpages}}

diff --git a/files/ja/learn/performance/measuring_performance/index.html b/files/ja/learn/performance/measuring_performance/index.html new file mode 100644 index 0000000000..f70a9cfa20 --- /dev/null +++ b/files/ja/learn/performance/measuring_performance/index.html @@ -0,0 +1,105 @@ +--- +title: パフォーマンスの測定 +slug: Learn/Performance/Measuring_performance +tags: + - API + - Beginner + - Guide + - Tools + - Web +translation_of: Learn/Performance/Measuring_performance +--- +
{{LearnSidebar}} {{PreviousMenuNext("Learn/Performance/Perceived_performance", "Learn/Performance/Multimedia", "Learn/Performance")}}
+ +
+ +
パフォーマンスの測定は、あなたがあなたのアプリケーション、サイト、ウェブサービスを評価することを助ける重要な指標を提供します。たとえば、パフォーマンスの指標を使うことで、競合と比較してアプリケーションをどのように動作させるか決めたり、リリースごとのパフォーマンスを比較したりできます。測定対象として選択する指標はユーザー、サイト、そしてビジネスのゴールに関連するものであるべきです。それらは一貫した手法で収集、測定され、非技術系の関係者にも理解でき、利用可能なフォーマットで分析される必要があります。この記事ではサイトのパフォーマンス測定と最適化に利用できるウェブパフォーマンスの指標を紹介します。
+ +
+ + + + + + + + + + + + +
前提:基本的なコンピューターリテラシー、基本的なソフトウェアのインストールクライアントサイドのウェブ技術の基本的な知識
目的: +

様々なウェブパフォーマンス API を通じて収集できる ウェブパフォーマンスの指標とデータの視覚化に利用できるツールの情報を提供すること

+
+ +

パフォーマンス API

+ +

ウェブのコードを書くとき、自分自身でパフォーマンス測定ツールを作るために利用できるたくさんのウェブ API があります。

+ +

クライアントサイドのウェブパフォーマンスを測定するために Navigation Timing API を利用できます。前のページをアンロードするために必要な時間、ドメインのルックアップにかかる時間、ウィンドウのロードハンドラー実行にかかる時間の合計などが含まれます。この API は、下図に示すナビゲーションイベント全てに関する指標として利用できます。

+ +

The various handlers that the navigation tiiming API can handle including Navigation timing API metrics Prompt for unload redirect unload App cache DNS TCP Request Response Processing onLoad navigationStart redirectStart redirectEnd fetchStart domainLookupEnd domainLookupStart connectStart (secureConnettionStart) connectEnd requestStart responseStart responseEnd unloadStart unloadEnd domLoading domInteractive domContentLoaded domComplete loadEventStart loadEventEnd

+ +

現在のページのパフォーマンスに関連する情報へのアクセスを提供する Performance API は、Performance Timeline APINavigation Timing APIUser Timing API、そして Resource Timing API を含みます。これらのインターフェースにより、JavaScript のタスクが完了するまでにかかる時間の正確な測定が可能になります。

+ +

PerformanceEntry オブジェクトは、パフォーマンスタイムラインの一部です。パフォーマンスエントリーは アプリケーション内の明示的なポイントでパフォーマンスの{{domxref("PerformanceMark","mark")}} または {{domxref("PerformanceMeasure","measure")}}  を作ること(たとえば {{domxref("Performance.mark","mark()")}} メソッドを呼び出すこと)で直接的に作成されます。パフォーマンスエントリーは、画像などリソースの読み込みのようなタイミングで間接的に作成されることもあります。

+ +

PerformanceObserver API はパフォーマンス測定のイベントを観察するために利用できます。さらにブラウザーのパフォーマンスタイムラインに新しいパフォーマンスエントリーが記録されるたびに通知することができます。

+ +

この記事ではこれらの API に深入りしませんが、これらの存在を知っていると便利です。パフォーマンスウェブ API を使う例についてより深く知りたい場合は Navigation and timings の記事を参照してください。

+ +

ツールと指標

+ +

パフォーマンスの改善を助けるために利用できるいくつかの異なるツールがあります。これらは一般的にふたつのカテゴリーに分類できます。

+ + + +

このコースでは両方のカテゴリーを取り上げます。そしてパフォーマンスの指標だけではなく、サイトのパフォーマンスが改善しているかどうかを測定するための指標についても議論します。

+ +

一般的なパフォーマンスレポートツール

+ +

PageSpeed Insights のようなツールではウェブサイトのパフォーマンスを測定できます。URL を入力すると数秒でパフォーマンスのレポートを入手できます。レポートはモバイルとデスクトップの両方でウェブサイトがどの程度の性能を示すかを表すスコアを含みます。これは、すでにできていることと改善が必要な部分についてのアイデアを得る良いスタート地点になります。

+ +

本記事の執筆時点で、MDN のパフォーマンスレポートのサマリーは以下のようになっています。

+ +

A screenshot of PageSpeed Insights report for the Mozilla homepage.

+ +

パフォーマンスレポートは、ページに何かが表示されまでにユーザーがどのくらい待たなければならないか、ページを表示するまでに何バイトのデータがダウンロードされる必要があるかなどの情報を含みます。さらに測定された値が良好と考えられるか、あるいは不良であるかも示します。

+ +

webpagetest.org は、サイトを自動的にテストして有益な指標を返すツールのもう一つの実例です。ぜひ webpagetest.org と PageSpeed Insights の両方であなたの好きなウェブサイトを実行してみてください。そしてスコアを見てみましょう。

+ +

ネットワークツール

+ +

多くのブラウザーが、読み込み対象のページに対してそれらがどのように動作しているか確認するために使えるツールを用意しています。たとえば、FIrefox の Network Monitor はネットワークからダウンロードされるすべてのアセットの詳細な情報を、それぞれダウンロードのどのくらいの時間がかかるかを示すグラフと合わせて表示します。

+ +

+ +

異なるアクションを実行したときのウェブアプリケーションやサイトのユーザーインターフェースのパフォーマンスを測定するために Performance Monitor を利用できます。これは ウェブアプリケーションやサイトを遅くしているかもしれない要素を指し示します。

+ +

+ +

結論

+ +

この記事ではウェブアプリケーションやサイトで利用可能なウェブパフォーマンスの指標の簡単な概要を紹介しました。次は、知覚されるパフォーマンスと、避けられないパフォーマンスへの影響をユーザーに深刻に見せない、あるいは完全に気づかれないようにするいくつかのテクニックを見ていきます。

+ +

{{PreviousMenuNext("Learn/Performance/Perceived_performance", "Learn/Performance/Multimedia", "Learn/Performance")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/performance/perceived_performance/index.html b/files/ja/learn/performance/perceived_performance/index.html new file mode 100644 index 0000000000..8af223ce2e --- /dev/null +++ b/files/ja/learn/performance/perceived_performance/index.html @@ -0,0 +1,111 @@ +--- +title: 知覚されるパフォーマンス +slug: Learn/Performance/perceived_performance +tags: + - Perceived Performance + - Web Performance +translation_of: Learn/Performance/perceived_performance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Performance/what_is_web_performance", "Learn/Performance/Measuring_performance", "Learn/Performance")}}
+ +

知覚されるパフォーマンスは、ユーザーから見てウェブサイトがどれくらい速く感じられるかを表します。ユーザーがパフォーマンスをどのように知覚するかは、具体的な統計値と同じくらい、あるいはどんな具体的な統計値よりも重要ですが、それは主観的で簡単に計測できるものではありません。知覚されるパフォーマンスはユーザーの視点であり、計測される値ではありません。

+ +

この記事は、ユーザーの知覚と、主観的な要素を計測するために使える具体的なツールに目を通し、知覚されるパフォーマンスの簡潔な紹介を提供します。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー、基本的なソフトウェアのインストールクライアントサイドのウェブ技術の基本的な知識
目的: +

ウェブパフォーマンスに対するユーザーの知覚について基本的な理解を獲得すること

+
+ +

パフォーマンスはユーザーの知覚に関連します。ウェブサイトの読み込みや描画がどれくらい速く感じられるかは、そのサイトが実際にどのくらい速く読み込まれ描画されるか以上にユーザーの体験に大きなインパクトを与えます。ある操作に(遅延やメインスレッドの無効状態によって)長い時間がかかる場合であっても、待っている間にローディングスピナーや一連の便利なヒント・ティップス(あるいはジョーク、その他適切なものであれば何でも)を表示することでユーザーのエンゲージを維持することが可能です。そのようなアプローチはただ何も表示しないよりずっと良いことです。何も表示しないことはより長い時間を感じさせ、ユーザーはそれが壊れていると思って待つのを諦めるかもしれません。

+ +

知覚されるパフォーマンス

+ +

サイトがどのくらい速く読み込まれるか、ユーザーのインタラクションにどのくらい良く反応すかの知覚はきわめて重要です。それは定量化することが難しい一方、実際のダウンロード時間以上に重要です。サイトにはそれ以上高速化することができない領域があるかもしれません。しかし、他のセクションで議論した統計値がそれ以上改善できない場合でも、サイトをより速く感じさせることは可能です。

+ +

ユーザーがどう感じるかを計測するたった一つの統計値 (unicorn metric) はありませんが、統計値は改善(または悪化)を判断するために有用です。関連する計測値には、First Meaningful Paint  (FMP)、Largetst contentful paint (LCP)、Time to interactive (TTI)、render start、DOM interactive、Speed Index があります。

+ +

First paint はブラウザーから報告され、ページの変更が始まる時間をミリ秒単位で提供します。しかし、この変更はシンプルな背景色の更新や、より気付きづらい小さなものである可能性があります。それは変更の完了を意味しておらず、目に見えるものが何も描画されていない時間を報告することもあります。First Contentful Paint (FCP) はブラウザーが最初に意味のある何か、テキスト、フォアグラウンド・バックグラウンドの画像、またはキャンバスや SVG を描画した時間を報告します。読み込みの経験のまさに始まりを補足します。しかし、それはただ単なるコンテンツであるため、意味のあるコンテンツ、あるいはユーザーが消費できるコンテンツであることを意味していません。First Meaningful Paint (FMP) は実際に意味のあるコンテンツがスクリーンに映し出された時間です。それは、ユーザーが知覚する読み込みの経験としてより適切な統計値ですが、まだ理想的とは言えません。Largest contentful paint (LCP) は、ビューポートの中で最も大きい目に見えるコンテンツの要素が描画される時間を報告する、Largest Contentful Paint API の中で定義された統計値です。

+ +

Speed index も知覚されるパフォーマンスの概算として使用されます。それは目に見えるスクリーン上にピクセルが描画される平均時間を計測します。それはジッターも、どのコンテンツがユーザーによってより重要であるかも考慮しません。そのため完全な統計値ではありません。

+ +

これらの統計値は最初の読み込みと描画に関わります。ユーザーがサイトとインタラクションを始めた後もサイトが速いと感じさせることは重要です。このために、time to interactive は良い統計値です。それは読み込みプロセスにおける最後の long task が終わり、ユーザーに UI が利用可能になる時間を表します。

+ +

UI の欠落や質の悪い反応はどちらも知覚されるパフォーマンスに悪い影響を与えます。タスクに長い時間がかかる場合であっても、それをより速く見せる方法はあります。知覚されるパフォーマンスを改善するいくつかのティップスがあります。

+ +

知覚されるパフォーマンスを改善する

+ +

ネットワークを理解すること、ブラウザがどのように動作するか、ユーザーが知覚する時間など、こういったものはユーザーのインタラクションを改善する方法を理解するために役立ちます。しかし、速さの知覚を改善するために、人間の心がどのように働くかと言った全てを理解する必要はありません。

+ +

それがどのくらい速い、または遅いと感じられるかは、ユーザーが能動的に待つか、受動的に待つかに大きく影響されます。待つことには能動と受動のフェーズがあります。ユーザが活動しているとき、マウスを動かしたり、考えたり、楽しんだりしているとき、ユーザーは能動的なフェーズにいます。受動的なフェーズは、ユーザーがモノクロのスクリーンを見つめるように受動的に待つ時に起こります。受動と能動の時間が客観的に同じとき、ユーザーは受動的に待つ時間が長かったと感じるでしょう。読み込み、描画、または反応の時間が客観的にそれ以上小さくできない場合、待つことを受動から能動的に待つ時間に変えることでより速く感じさせることができます。

+ +

いくつか従うべきヒントとコツがあります。より深く知りたい場合、これらのヒントのいくつかには別途完全な記事があります。

+ +

コンテンツ、または少なくともページの一部をコンテンツが読み込み中であることと併せてできるだけ速く表示することは、知覚されるパフォーマンスを改善するためにきわめて重要です。たとえば、ページの描画は CSS と Java Script の読み込みとパース処理にブロックされるため、最初の読み込みに必要とされる CSS と JS の量を最小化することは知覚されるパフォーマンスに大きな影響を持つでしょう。バイトとしてのサイズが同じだったとしても、ページの描画をブロックしないことは読み込みをより速く感じさせます。

+ +

知覚されるパフォーマンスを改善するヒントとコツを以下に示します。

+ +

最初の読み込みを最小化する

+ +

知覚されるパフォーマンスを改善するために、最初のページ読み込みを最小化しましょう。すなわち、最初に、実際に表示するものすべて、ただし本当に使うものだけをダウンロードしましょう。それから残りをダウンロードしましょう。すべてのアセットを最後までダウンロードしたときにはアセットの総量は改善されていません。実際にはコードを追加する必要があるかもしれません。しかし、直ちに必要ではないアセットをユーザーに気づかれない形で後からダウンロードすることによって、ユーザーはダウンロードが速くなったように感じます。

+ +

アセットを最小化するには最初の読み込みとコンテンツのインタラクティブな機能を分割する必要があります。その結果、目に見えるテキスト、スタイル、画像などの必要なコンテンツが最初に読み込まれます。

+ +

最初のページ読み込みで使用されない、あるいは目に見えない画像やスクリプトは読み込みしないようにしましょう。それらは読み込みを遅らせて、ページが使用可能になってから読み込むか、必要になった時に読み込みましょう。最初のページ読み込みの後で、追加のアセットやリソースを読み込むことは知覚されるパフォーマンスを改善します。最初のリクエストで必要なデータを読み込み、必要に応じて徐々に必要な部分やデータを読み込むことは帯域が限られている場合やスペックの低いハードウェアの問題を緩和することにも役立ちます。

+ +

さらに、読み込むアセットを最適化する必要があります。画像と動画は最適なフォーマットで、圧縮され、適切なサイズで提供されるべきです。

+ +

コンテンツのジャンプとリフローを防ぐ

+ +

画像やサードバーティーの広告のような、コンテンツを押し下げたり他の場所にジャンプさせたりするアセットは、ページがまだ読み込み中であるように感じさせ、知覚されるパフォーマンスを悪化させます。ユーザーのインタラクションに起因することなくリフローするコンテンツは特に悪いと言えます。他と比べて読み込みが遅く、かつ他のコンテンツがスクリーンに描画された後に要素が読み込まれるアセットは、レイアウト上にそれらのためのスペースを残すよう事前に計画しましょう。そうすることでコンテンツは、とくにサイトがインタラクション可能になった後で、ジャンプやリサイズしなくなります。

+ +

フォントファイルの遅延を避ける

+ +

フォントの使用はユーザーの体験を良くすることも悪くすることもあります。適切なフォントを選ぶことは芸術的であり、ユーザーの体験を劇的に良くすることもできます。フォントは、特に使用するフォントをインポートしなければいけないという点でユーザーの体験を悪化させることがあります。インポートするフォントが最適化されていない場合や馬鹿げた Comic Sans が使用されている場合はそうです。スタイリングされていないテキストのチラつきや該当するテキストが見つからないことはどちらもパフォーマンスを悪化させます。

+ +

同じサイズとウェイトのフォールバックフォントを用意しておきましょう。そうすることでフォントの読み込みによるページの変化に気付かれにくくなります。

+ +

インタラクティブな要素はインタラクティブに

+ +

目に見えるインタラクティブな要素は常にインタラクティブで反応できるようにしましょう。入力の要素が目に見える場合、ユーザーは遅延なしにそれらとインタラクションできるべきです。ユーザーは反応に 50 ミリ秒より長い時間がかかる場合、それが遅れていると感じます。コンテンツの再描画が 16.67 ミリ秒(または 60 frames per second)より遅いか、不規則な間隔で再描画されるとページが壊れているように感じます。

+ +

CSS で入力用のモーダルを表示したり、可能な場合は JS で先行入力・自動補完を追加するなど、先行入力や漸進的な拡張を使いましょう。

+ +

タスクの開始をよりインタラクティブにする

+ +

キーの押し上げを待たずにキーの押し下げでコンテンツをリクエストすることにより、知覚されるコンテンツの読み込みを 200 ミリ秒減らすことができます。キーの押し上げに合わせて興味深く、ただし目立ちすぎない 200 ミリ秒のアニメーションを追加することで知覚される読み込みをさらに 200 ミリ秒減らすことができます。実際に 400 ミリ秒の時間を削減したわけではありませんが、ユーザーは、自分がコンテンツを待っていると感じるまでは待っているとは感じないものです。

+ +

結論

+ +

ダウンロード、描画、待ち時間を能動的なフェーズに変え、受動的に待つ時間を減らすことにより、客観的な測定値が同じであったとしても、ユーザーはコンテンツのダウンロード、描画、反応がより速くなったように感じます。これで速度向上のために何をするべきかわかりました。次はいくつかの統計値を確認し、これらのイベントをどのように測定できるか学びましょう。

+ +

{{PreviousMenuNext("Learn/Performance/what_is_web_performance", "Learn/Performance/Measuring_performance", "Learn/Performance")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/performance/web_performance_basics/index.html b/files/ja/learn/performance/web_performance_basics/index.html new file mode 100644 index 0000000000..276e2f2e04 --- /dev/null +++ b/files/ja/learn/performance/web_performance_basics/index.html @@ -0,0 +1,89 @@ +--- +title: ウェブパフォーマンスの基礎 +slug: Learn/Performance/Web_Performance_Basics +tags: + - Best practices + - Website performance +translation_of: Learn/Performance/Web_Performance_Basics +--- +

{{draft}}あなたのウェブサイトが可能な限りのパフォーマンスを発揮すべき理由はたくさんあります。
+ 以下に、各トピックの詳細情報を提供するためのリンク付きのベストプラクティス、ツール、API の簡単なレビューを示します。

+ +

Best practices

+ + + +

Quick Wins

+ +

CSS

+ +

Web performance is all about user experience and perceived performance. As we learned in the critical rendering path document, linking CSS with a tradional link tag with rel="stylesheet" is synchronous and blocks rendering. Optimize the rendering of your page by removing blocking CSS.

+ +

To load CSS asynchronously one can simpy set the media type to print and then change to all once loaded. The following snippet includes an onload attribute, requiring Javascript, so it is important to include a noscript tag with a traditional fallback.

+ +
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">
+<noscript><link rel="stylesheet" href="/path/to/my.css"></noscript>
+
+ +

The downside with this approach is the flash of unstyled text (FOUT.) The simplist way to address this is by inlining CSS that is required for any content that is rendered above the fold, or what you see in the browser viewport before scrolling. These styles will improve perceived performance as the CSS does not require a file request.

+ +
<style type="text/css">
+// Insert your CSS here
+</style>
+
+ +

Javascript

+ +

Avoid Javascript blocking by using the async or defer attributes, or link javascript assets after the page's DOM elements. Javascript only block rendering for elements that appear after the script tag in the DOM tree.

+ +

Web Fonts

+ +

EOT and TTF formats are not compressed by default. Apply compression such as GZIP or Brotli for these file types. Use WOFF and WOFF2. These formats have compression built in.

+ +

Within @font-face use font-display: swap. By using font display swap the browser will not block rendering and will use the backup system fonts that are defined. Optimiize font weight to match the web font as closely as possible.

+ +

Icon web fonts

+ +

If possible avoid icon web fonts and use compressed SVGs. To further optimize inline your SVG data within HTML markup to avoid HTTP requests.

+ +

Tools

+ + + +

APIs

+ + + +

Things not to do (bad practices)

+ + + +

See also:

+ + diff --git a/files/ja/learn/performance/what_is_web_performance/index.html b/files/ja/learn/performance/what_is_web_performance/index.html new file mode 100644 index 0000000000..f969943627 --- /dev/null +++ b/files/ja/learn/performance/what_is_web_performance/index.html @@ -0,0 +1,90 @@ +--- +title: ウェブパフォーマンスとは何ですか? +slug: Learn/Performance/What_is_web_performance +tags: + - Beginner + - Introduction + - Learn + - Performance + - Reference + - Tutorial + - Web Performance +translation_of: Learn/Performance/What_is_web_performance +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Performance/why_web_performance", "Learn/Performance/Perceived_performance", "Learn/Performance")}}
+ +

ウェブパフォーマンスは、実際には遅い処理を速いように見せることを含め、ウェブサイトを速くすることに関わるすべての事柄を表します。サイトを速く読み込む、ユーザーが早くインタラクションを始められるようにする、あるいは、読み込みに時間がかかる場合は、たとえばローディングスピナーを表示するなど、ユーザーが安心できるフィードバックを提供する、これらができていますか?スクロールとアニメーションは滑らかですか?この記事では、客観的で測定可能なウェブパフォーマンス*についての簡潔なイントロダクションを提示し、どのような技術、テクニック、そして最適化に関わるツールが利用できるかを探っていきます。

+ + + + + + + + + + + + +
前提条件: +

基本的なコンピューターリテラシー、基本的なソフトウェアのインストールクライアントサイドのウェブ技術の基礎知識

+
目的: +

Web パフォーマンスに関わる事項について基本的な理解を得ること

+
+ +

* 次の記事でカバーする主観的な知覚されるパフォーマンスの逆

+ +

ウェブパフォーマンスとは何ですか?

+ +

ウェブパフォーマンスはウェブサイトまたはウェブアプリケーションの客観的な測定結果とユーザーによって知覚される体験です。これには以下の主要な領域が含まれます。

+ + + +

まとめると、たくさんの要素がパフォーマンスに影響を与えます。レイテンシー、アプリケーションのサイズ、DOM ノードの数、リクエストされるリソースの数、JavaScript の性能、CPU 負荷、その他いろいろです。それらの読み込みとレスポンスの時間を小さくすることが重要です。それから、ユーザーの体験上後で必要になる部分を同期で読み込むなどして、サイトが利用可能になる時間をできる限り早くすることでレイテンシーを感じさせないようにするといった追加の要素も重要です。

+ +
+

:ウェブのパフォーマンスには、Time to load、Frames per second、Time to interactive のような客観的や測定結果とコンテンツの読み込みがどれくらい長く感じられるかといった主観的な経験の両方が含まれます。

+
+ +

コンテンツはどのように描画されるか

+ +

効率的にウェブパフォーマンス、その背後にある問題やここまでに挙げた主要なトピックを理解するためにはブラウザーがどのように動作するかについていくつかの詳細を理解することが必要です。これには以下のトピックが含まれます。

+ + + +

結論

+ +

以上です。ウェブパフォーマンスのトピックに関するこの簡潔な要約が、あなたが全体のアイデアを理解するための助けとなり、さらに学ぶ意欲をかき立てることができたなら幸いです。この後は知覚されたパフォーマンスを取り上げ、避けられないパフォーマンスへの影響を、ユーザーにとって深刻に見えないようにする、あるいは完全に気づかれないようにする賢い方法について見ていきます。

+ +

{{PreviousMenuNext("Learn/Performance/why_web_performance", "Learn/Performance/Perceived_performance", "Learn/Performance")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/performance/why_web_performance/index.html b/files/ja/learn/performance/why_web_performance/index.html new file mode 100644 index 0000000000..fdc99200d6 --- /dev/null +++ b/files/ja/learn/performance/why_web_performance/index.html @@ -0,0 +1,101 @@ +--- +title: ウェブパフォーマンスの "なぜ" +slug: Learn/Performance/why_web_performance +tags: + - Beginner + - Introduction + - Learn + - Performance + - Reference + - Tutorial + - Web パフォーマンス +translation_of: Learn/Performance/why_web_performance +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Performance/What_is_web_performance", "Learn/Performance")}}
+ +

ウェブパフォーマンスは、遅いプロセスを速く見せることも含めて、ウェブサイトを速くすることがすべてです。この記事では、なぜウェブパフォーマンスがサイト訪問者にとって、またビジネスの目標にとって重要なのかを紹介しています。

+ + + + + + + + + + + + +
前提条件: +

基本的なコンピュータリテラシー、基本的なソフトウェアのインストールクライアントサイドのウェブ技術の基本的な知識。

+
目標:良いユーザー体験のために、なぜウェブパフォーマンスが重要なのか、その基礎知識を身につけること。
+ +

ウェブパフォーマンスとは、サイトのコンテンツの読み込みレンダリングの速さ、ユーザーとのやりとりへの反応の速さを指します。パフォーマンスの悪いサイトは、表示に時間がかかり、入力への反応が遅くなります。パフォーマンスの悪いサイトは、サイトの離脱率を高めます。パフォーマンスが悪いと、最悪の場合、コンテンツに完全にアクセスできなくなります。Web パフォーマンスの良い目標は、ユーザーがパフォーマンスに気づかないことです。サイトパフォーマンスのパフォーマンスに対する個人の認識は主観的なものですが、読み込みとレンダリングは測定できます。パフォーマンスが良いことは、ほとんどのサイト訪問者には明らかではないかもしれませんが、ほとんどの人は停滞しているサイトをすぐに認識するでしょう。それが私たちが気にする理由です。

+ +

なぜパフォーマンスを気にするのか?

+ +

ウェブパフォーマンスとそれに付随するベストプラクティスは、ウェブサイトの訪問者が良い体験をするために不可欠です。ある意味では、ウェブパフォーマンスはウェブアクセシビリティのサブセットと考えることができます。アクセシビリティと同様にパフォーマンスでは、サイト訪問者がサイトにアクセスするために使用しているデバイスとデバイスの接続速度を考慮します。

+ +

例として、この記事を書いている時点で、ファイルサイズが 22.6 MB を超える 400 以上の HTTP リクエストがあった CNN.com の読み込み体験を考えてみましょう。

+ + + +

22.6 MB のサイトは、3G ネットワーク上での読み込みに最大 83 秒かかり、DOMContentLoaded (サイトのベースとなる HTML 構造の意味) は 31.86 秒でした。

+ +

ダウンロードにかかる時間だけが大きな問題ではありません。多くの国では、いまだにメガバイト単位で請求されるインターネット接続があります。私たちの例では、22.6 MB の CNN.com をダウンロードするのに平均的なインド人の日給の約 11 % の費用がかかることになります。アフリカ北西部のモバイル・デバイスからだと、平均的な給料の2日分の費用がかかるかもしれません。 もしこのサイトが米国のキャリアの国際ローミングプランで読み込まれたとしたら?その費用に誰もが泣くことでしょう。("how much your site costs to download" を参照)

+ +

コンバージョン率を改善する

+ +

サイトのダウンロードとレンダリング時間を短縮することで、コンバージョン率とユーザー維持率が向上します。

+ +

コンバージョン率とは、サイト訪問者が測定された、または希望するアクションを実行する率のことです。例えば、購入する、記事を読む、ニュースレターを購読するなどです。コンバージョン率として測定されるアクションは、ウェブサイトのビジネス目標によって異なります。

+ +

パフォーマンスはコンバージョンに影響を与えます。サイト訪問者は、サイトが2秒以内に読み込まれることを期待していますが、モバイル (一般的にはもっと時間がかかる) ではそれ以下になることもあります。同じサイト訪問者でも、遅いサイトを3秒で放棄し始めます。

+ +

サイトの読み込み速度は1つの要因です。サイトがユーザーとのやり取りに反応するのが遅かったり、不愉快に見えたりすると、サイト訪問者は興味を失い、信頼を失います。

+ +

ここでは、パフォーマンス向上の実例をいくつか紹介します。

+ + + +

サイト訪問者を惹きつけ、維持するためには、アクセスしやすいサイトを作成し、優れたユーザー体験を提供する必要があります。ウェブサイトを構築するには、HTML、CSS、JavaScript が必要であり、通常は画像や動画などのバイナリファイルタイプも含まれます。サイトを構築する際の決定やツールの選択は、完成した作品のパフォーマンスに大きく影響します。

+ +

良いパフォーマンスは資産です。パフォーマンスが悪ければ負債となります。サイトの速度は、バウンス率、コンバージョン、収益、ユーザー満足度、検索エンジンランキングに直接影響します。パフォーマンスの高いサイトは、訪問者の維持率とユーザーの満足度を高めることが示されています。遅いコンテンツはサイトの放棄につながることが示されており、訪問者の中には二度と戻ってこない人もいます。クライアントとサーバーの間を通過するデータ量を減らすことで、すべての関係者のコストを削減します。HTML/CSS/JavaScript とメディアファイルのサイズを減らすことで、ロード時間とサイトの消費電力の両方を削減できます (パフォーマンス予算を参照)。

+ +

パフォーマンスのトラッキングは重要です。ネットワーク速度やデバイスの機能など、複数の要因がパフォーマンスに影響を与えます。また、ビジネスの目的が違えば、サイトやサポートしている組織の目標に応じて、異なるメトリクスの方がより関連性が高いことを意味する場合もあります。サイトのパフォーマンスがどのように認識されるかは、ユーザー体験です。

+ +

まとめ

+ +

ウェブパフォーマンスは、アクセシビリティだけでなく、組織やビジネスの目標を達成するための他のWeb サイトの測定基準にとっても重要です。ウェブサイトのパフォーマンスの良し悪しは、ほとんどのサイトの全体的な有効性と同様に、ユーザーエクスペリエンスと強力に相関しています。これが、ウェブパフォーマンスに注意を払うべき理由です。

+ +

{{NextMenu("Learn/Performance/What_is_web_performance", "Learn/Performance")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/release_notes/index.html b/files/ja/learn/release_notes/index.html new file mode 100644 index 0000000000..983ad71fef --- /dev/null +++ b/files/ja/learn/release_notes/index.html @@ -0,0 +1,69 @@ +--- +title: 学習エリアのリリースノート +slug: Learn/Release_notes +tags: + - Learn + - Release Notes +translation_of: Learn/Release_notes +--- +
{{learnsidebar}}
+ +

This page details significant changes made to the learning area. Check back here if you want to know what new content is available, and what existing content has been improved.

+ +

If you want to give feedback on any of these new additions, please leave comments in our Discourse forum.

+ +

June 2020

+ +

Our Front-end web developer learning pathway is officially launched! Check it out for an opinionated pathway to follow for learning front-end development! Also see our hacks post — Introducing the MDN Web Docs Front-end developer learning pathway — for more information about the rationale behind it.

+ +

May 2020

+ +

Our Understanding client-side JavaScript frameworks module is now available. Learn why frameworks exist, when you should use one (and when you shouldn't), what kinds of features are common to all frameworks, and how they relate to the vanilla JavaScript you may already know. Once you have a general understanding of frameworks, move on to tutorial series covering popular frameworks like React, Ember, and Vue.

+ +

Our Web Forms learning module now has "Test your skills" assessments accompanying the articles.

+ +

April 2020

+ +

Our new Understanding client-side web development tools module has been released! Learn the essentials of web development tooling, including what kind of tools exist, the command line, package managers, and how to assemble your own functioning tool chain.

+ +

March 2020

+ +

You'll now find "Test your skills" assessments accompanying the articles in the following modules:

+ + + +

January 2020

+ +

The HTML forms module has been significantly updated:

+ + + +

More "Test your skills" sections have been added. You can see these on:

+ + + +

December 2019

+ +

We are adding a new type of assessment article to the learning area — "Test your skills" — which will offer several short questions aimed at rapidly testing whether you understood what is going on. This is in addition to the longer Assessment articles that you'll find in some of the learning modules already. You will find these new articles linked in "Test your skills" sections at the bottom of relevant articles. You can see these on:

+ + diff --git a/files/ja/learn/server-side/django/development_environment/index.html b/files/ja/learn/server-side/django/development_environment/index.html new file mode 100644 index 0000000000..ac824323ea --- /dev/null +++ b/files/ja/learn/server-side/django/development_environment/index.html @@ -0,0 +1,433 @@ +--- +title: Django 開発環境の設定 +slug: Learn/Server-side/Django/development_environment +tags: + - Python + - Webフレームワーク + - django + - サーバーサイドプログラミング +translation_of: Learn/Server-side/Django/development_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}
+ +

Djangoがどういうものか知ったので、Windows、Linux(Ubuntu)、およびmacOSでDjango開発環境をセットアップしてテストする方法を説明します。一般的なオペレーティングシステムを使っていれば、Djangoアプリケーションの開発を始められます。

+ + + + + + + + + + + + +
前提条件:ターミナル/コマンドラインを開く方法を知っていること。開発用コンピュータのオペレーティングシステムにソフトウェアパッケージをインストールする方法を知っていること。
目的:あなたのコンピュータでDjango(2.0)の開発環境を動かします。
+ +

Django開発環境の概要

+ +

Djangoは自分のコンピュータをセットアップするのはとても簡単で、Webアプリケーションの開発を開始できます。このセクションでは、開発環境の内容を説明し、セットアップおよび構成オプションの一部の概要を示します。また、Ubuntu、macOS X、WindowsにDjango開発環境をインストールする際の推奨される方法と、そのテスト方法について説明します。

+ +

Django開発環境とは何ですか?

+ +

開発環境はDjangoをローカルコンピュータにインストールしたものです。Djangoアプリを開発し、運用環境にデプロイする前にテストできます。

+ +

Django自体が提供する主なツールは、Djangoプロジェクトを作成して作業するためのPythonスクリプトと、ローカルの(つまり、外部のWebサーバーではなく)Django Webアプリケーションをあなたのコンピュータ上のウェブブラウザでテストするための簡単な開発用Webサーバーです。

+ +

開発環境の一部を構成する他の周辺ツールがありますが、ここではカバーしません。これには、コードを編集するためのテキストエディタやIDE、コードの異なるバージョンを安全に管理するためのGitのようなソース管理ツールなどがあります。すでにテキストエディタがインストールされていると仮定しています。

+ +

Djangoの構成オプションとは?

+ +

Djangoは、インストール場所と設定の方法に関して非常に柔軟性があります。Djangoは次のようなことが可能です:

+ + + +

これらのオプションは、それぞれわずかに異なる構成とセットアップを必要とします。以下のサブセクションでは、いくつかの選択肢について説明します。この記事の残りの部分では、いくつかオペレーティングシステムにDjangoをセットアップする方法を説明します。このモジュールの残りの部分は、セットアップが済んでいる想定です。

+ +
+

ノート: その他のインストールオプションについては、Djangoの公式ドキュメントでカバーされています。下記で適切なドキュメントにリンクしています。

+
+ +

どのオペレーティングシステムがサポートされていますか?

+ +

DjangoのWebアプリケーションは、Python 3プログラミング言語を実行できるほとんどすべてのマシン(Windows、MacOS X、Linux / Unix、Solarisなど)で実行できます。ほとんどのコンピュータで開発中にDjangoを実行できるパフォーマンスが必要です。

+ +

この記事では、Windows、macOS X、およびLinux/Unixについて説明します。

+ +

どのバージョンのPythonを使うべきですか?

+ +

最新のバージョンを使用することをお勧めします - 執筆時点ではPython 3.6です。

+ +

必要であればPython 3.4以上を使用できます(Python 3.4のサポートは将来のリリースでは廃止される予定です)。

+ +
+

ノート: Python 2.7はDjango 2.0では使用できません(Django 1.11.x系はPython 2.7をサポートする最後のバージョンです)。

+
+ +

どこでDjangoをダウンロードできますか?

+ +

Djangoをダウンロードする場所は3つあります:

+ + + +

この記事ではPyPiからDjangoをインストールし、最新の安定版を入手する方法を説明します。

+ +

どのデータベースですか?

+ +

Djangoは4つの主要なデータベース(PostgreSQL、MySQL、Oracle、SQLite)をサポートしています。また、他の一般的なSQLデータベースやNOSQLデータベースにさまざまなレベルのサポートを提供するコミュニティライブラリもあります。 DjangoはObject-Relational Mapper(ORM)を使用して多くのデータベースの違いを抽象化していますが、回避する方が良い潜在的な問題がまだあります。

+ +

この記事(とこのモジュールのほとんど)では、データをファイルに保存するSQLiteデータベースを使用します。 SQLiteは軽量データベースとしての使用を目的としており、高度な並行性はサポートできません。 ただし、主に読み取り専用のアプリケーションには最適です。

+ +
+

ノート: Djangoは、標準ツール(django-admin)を使用してWebサイトプロジェクトを開始するときに、デフォルトでSQLiteを使用するように設定されています。 これは、追加の設定やセットアップが不要なため、入門には最適な選択です。

+
+ +

システム全体またはPythonの仮想環境にインストールするには?

+ +

Python3をインストールすると、すべてのPython3コードで共有される単一のグローバル環境が得られます。 環境に好きなPythonパッケージをインストールすることはできますが、一度に1つのパッケージしかインストールできません。

+ +
+

ノート: グローバル環境にインストールされたPythonアプリケーションは、お互いに衝突する可能性があります(例えば、同じパッケージの異なるバージョンに依存する場合)。 

+
+ +

Djangoをデフォルト/グローバル環境にインストールすると、コンピュータ上でDjangoの1つのバージョンのみを対象にできます。 古いバージョンに依存しているWebサイトを維持しながら、新しいWebサイト(Djangoの最新バージョンを使用)を作成したい場合、これは問題になる可能性があります。

+ +

その結果、経験豊富なPython/Django開発者は通常、独立したPython仮想環境内でPythonアプリケーションを実行します。これにより、1台のコンピュータ上で複数の異なるDjango環境を使用することができます。Djangoの開発チームは、Pythonの仮想環境を使用することをお勧めしています。

+ +

このモジュールは以下に示す方法で、仮想環境にDjangoをインストールすることを前提としています。

+ +

Python 3のインストール

+ +

Djangoを使用するには、オペレーティングシステムにPythonをインストールする必要があります。Python 3を使用している場合は、Djangoとその他のPythonアプリケーションで使用されるPythonパッケージ/ライブラリの管理(インストール、更新、削除)に使用する Python Package Indexツール『pip3』も必要です。

+ +

このセクションでは、Ubuntu Linux 16.04、macOS X、およびWindows 10のPythonのバージョンを確認し、必要に応じて新しいバージョンをインストールする方法を簡単に説明します。

+ +
+

ノート: 使用しているプラットフォームによっては、オペレーティングシステム独自のパッケージマネージャやその他のメカニズムを使ってPython/pipをインストールできます。ほとんどのプラットフォームでは、 https://www.python.org/downloads/ から必要なインストールファイルをダウンロードし、適切なプラットフォーム固有の方法を使用してインストールできます。

+
+ +

Ubuntu 16.04

+ +

Ubuntu Linux 16.04 LTSにはデフォルトでPython 3.5.2が含まれています。 これを確認するには、bash端末で次のコマンドを実行します:

+ +
python3 -V
+ Python 3.5.2
+ +

しかし、Python 3(Djangoを含む)用のパッケージをインストールするために必要なPython Package Indexツールは、デフォルトでは利用できません。 次のコマンドを使用してbash端末にpip3をインストールできます:

+ +
sudo apt-get install python3-pip
+
+ +

macOS X

+ +

macOS X "El Capitan"やその他の最近のバージョンにはPython 3は含まれていません。これはbash端末で次のコマンドを実行することで確認できます:

+ +
python3 -V
+ -bash: python3: command not found
+ +

python.orgのPython 3(pip3ツールと一緒に)を簡単にインストールできます:

+ +
    +
  1. 必要なインストーラをダウンロードします: +
      +
    1. https://www.python.org/downloads/ を開きます
    2. +
    3. Download Python 3.6.4 ボタンを選択します(正確なマイナーバージョン番号は異なる場合があります)。
    4. +
    +
  2. +
  3. Finderを使用してファイルを探し、パッケージファイルをダブルクリックします。インストールの後、プロンプトが表示されます。
  4. +
+ +

以下に示すように、Python 3を確認することで、正常にインストールされたことを確認できます:

+ +
python3 -V
+ Python 3.6.4
+
+ +

同様にpip3がインストールされていることを確認するには、利用可能なパッケージを一覧表示します:

+ +
pip3 list
+ +

Windows 10

+ +

WindowsにはデフォルトでPythonは含まれていませんが、python.orgからpip3ツールと一緒に簡単にインストールできます:

+ +
    +
  1. 必要なインストーラをダウンロードします: +
      +
    1. https://www.python.org/downloads/ を開きます
    2. +
    3. Download Python 3.6.4 ボタンを選択します(正確なマイナーバージョン番号は異なる場合があります)。
    4. +
    +
  2. +
  3. ダウンロードしたファイルをダブルクリックし、インストールのプロンプトに従ってPythonをインストールします。
  4. +
+ +

Python 3がインストールされたことを確認するには、コマンドプロンプトに次のテキストを入力します:

+ +
py -3 -V
+ Python 3.6.4
+
+ +

Windowsインストーラには、デフォルトでpip3(Pythonパッケージマネージャ)が組み込まれています。次に示すようにインストールされたパッケージを一覧表示できます:

+ +
pip3 list
+
+ +
+

ノート: インストーラは、上記のコマンドが動作するために必要なものすべてをセットアップする必要があります。Pythonが見つからないというメッセージが表示された場合は、システムパスに追加する必要があります。

+
+ +

Python仮想環境内でのDjangoの使用

+ +

仮想環境を作成するために使用するライブラリは、 virtualenvwrapper (LinuxとmacOS X)とvirtualenvwrapper-win(Windows)です。これらはどちらもvirtualenvツールを使用します。ラッパーツールは、すべてのプラットフォーム上のインターフェイスを管理するための一貫したインターフェイスを作成します。

+ +

仮想環境ソフトウェアのインストール

+ +

Ubuntu仮想環境のセットアップ

+ +

Pythonとpipをインストールした後、virtualenvwrapper(virtualenvを含む)をインストールできます。公式インストールガイドはこちら、または下記の手順に従ってください。

+ +

pip3を使用してツールをインストールします:

+ +
sudo pip3 install virtualenvwrapper
+ +

次に、シェルのスタートアップファイルの最後に次の行を追加します(これはホームディレクトリ内の .bashrc という名前の隠しファイルです)。これらは、仮想環境の存在場所、開発プロジェクトディレクトリの場所、およびこのパッケージと共にインストールされるスクリプトの場所を設定します:

+ +
export WORKON_HOME=$HOME/.virtualenvs
+export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
+export VIRTUALENVWRAPPER_VIRTUALENV_ARGS=' -p /usr/bin/python3 '
+export PROJECT_HOME=$HOME/Devel
+source /usr/local/bin/virtualenvwrapper.sh
+ +
+

ノート: VIRTUALENVWRAPPER_PYTHONおよびVIRTUALENVWRAPPER_VIRTUALENV_ARGS変数は、Python3の通常のインストール場所を指し、source /usr/local/bin/virtualenvwrapper.shvirtualenvwrapper.sh スクリプトの通常の場所を指します。テスト時にvirtualenvが動作しない場合は、Pythonとスクリプトが予想される場所にあることを確認してから、起動ファイルを適切に変更してください。
+
+ あなたのシステムでの正しい場所は、which virtualenvwrapper.shwhich python3というコマンドを使って見つけることができます。

+
+ +

次に、ターミナルで次のコマンドを実行してスタートアップファイルをリロードします:

+ +
source ~/.bashrc
+ +

この時点で、以下に示すように一連のスクリプトが実行されているはずです:

+ +
virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/premkproject
+virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postmkproject
+...
+virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/preactivate
+virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postactivate
+virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/get_env_details
+
+ +

これで、mkvirtualenvコマンドを使用して新しい仮想環境を作成できます。

+ +

macOS X仮想環境のセットアップ

+ +

macOS Xでのvirtualenvwrapperのセットアップは、Ubuntuの場合とほぼ同じです(オフィシャルインストールガイドまたはそれ以下の指示に従います)。

+ +

次に示すようにpipを使用してvirtualenvwrapper(およびvirtualenvをバンドル)をインストールします。

+ +
sudo pip3 install virtualenvwrapper
+ +

次に、シェルスタートアップファイルの最後に次の行を追加します。

+ +
export WORKON_HOME=$HOME/.virtualenvs
+export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
+export PROJECT_HOME=$HOME/Devel
+source /usr/local/bin/virtualenvwrapper.sh
+
+ +
+

ノートVIRTUALENVWRAPPER_PYTHON変数はPython3の通常のインストール場所を指し、source /usr/local/bin/virtualenvwrapper.shvirtualenvwrapper.shスクリプトの通常の場所を指しています。テスト時にvirtualenvが動作しない場合は、Pythonとスクリプトが予想される場所にあることを確認してから、起動ファイルを適切に変更してください。

+ +

 

+ +

たとえば、macOSでの1つのインストールテストでは、スタートアップファイルに次の行が必要になりました:

+ +
export WORKON_HOME=$HOME/.virtualenvs
+export VIRTUALENVWRAPPER_PYTHON=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
+export PROJECT_HOME=$HOME/Devel
+source /Library/Frameworks/Python.framework/Versions/3.7/bin/virtualenvwrapper.sh
+ +

 

+ +

あなたのシステムでの正しい場所は、which virtualenvwrapper.shwhich python3というコマンドを使って見つけることができます。

+
+ +


+ これらはUbuntuの場合と同じ行ですが、スタートアップファイルはホームディレクトリ内で .bash_profile という別の名前の隠しファイルです。

+ +
+

ノート: 編集する.bash-profileがFinderで見つからない場合は、ターミナルでnanoを使用して開くこともできます。

+ +

コマンドは次のようになります:

+ +
cd ~  # Navigate to my home directory
+ls -la #List the content of the directory. YOu should see .bash_profile
+nano .bash_profile # Open the file in the nano text editor, within the terminal
+# Scroll to the end of the file, and copy in the lines above
+# Use Ctrl+X to exit nano, Choose Y to save the file.
+
+ +

 

+
+ +

ターミナルで次の呼び出しを行うことによって、スタートアップファイルをリロードします:

+ +
source ~/.bash_profile
+ +

この時点で、たくさんのスクリプトが実行されているのを見ることができます(Ubuntuのインストールと同じスクリプト)。mkvirtualenvコマンドを使用して新しい仮想環境を作成できるようになりました。

+ +

Windows 10仮想環境のセットアップ

+ +

virtualenvwrapper-winのインストールは、仮想環境情報を保存する場所(デフォルト値があります)を設定する必要がないため、virtualenvwrapperを設定するより簡単です。コマンドプロンプトで次のコマンドを実行するだけです:

+ +
pip3 install virtualenvwrapper-win
+ +

これで、mkvirtualenvコマンドで新しい仮想環境を作成できます。

+ +

仮想環境の作成

+ +

virtualenvwrapperまたはvirtualenvwrapper-winをインストールすると、仮想環境での作業はすべてのプラットフォームでほとんど同様になります。

+ +

mkvirtualenv コマンドを使用して新しい仮想環境を作成できます。このコマンドが実行されると、セットアップされる環境が表示されます(表示されるのはプラットフォーム固有のものです)。コマンドが完了すると、新しい仮想環境がアクティブになります。これは、プロンプトの開始が環境の名前(下に示すように)になるので、確認できます。

+ +
$ mkvirtualenv my_django_environment
+
+Running virtualenv with interpreter /usr/bin/python3
+...
+virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/t_env7/bin/get_env_details
+(my_django_environment) ubuntu@ubuntu:~$
+
+ +

これで、Djangoをインストールして開発を開始できる仮想環境の中に入りました。

+ +
+

ノート: これ以降、この記事(と実際にはモジュール)では、上でセットアップしたようなPython仮想環境内でコマンドが実行されると仮定してください。

+
+ +

仮想環境の使用

+ +

他にも知っておくべき便利なコマンドがいくつかあります(ツールのドキュメントには多くのものがありますが、これらはいつも使用するコマンドです):

+ + + +

Djangoのインストール

+ +

仮想環境を作成し、workonでその環境に入ってから、pip3を使用してDjangoをインストールできます。

+ +
pip3 install django
+
+ +

Djangoがインストールされていることをテストするには、次のコマンドを実行します(PythonがDjangoモジュールを見つけることができます):

+ +
# Linux/macOS X
+python3 -m django --version
+ 2.0
+
+# Windows
+py -3 -m django --version
+ 2.0
+
+ +
+

ノート: Windowsではpy -3コマンドをプレフィックスにしてPython 3スクリプトを起動し、Linux/macOS Xでは python3を実行します。

+
+ +
+

重要: このモジュールの残りの部分は、 Python 3 (python3) を呼び出すためにLinuxコマンドを使用します。Windowsで作業している場合は、単にこの接頭辞をpy -3に置き換えてください。

+
+ +

インストールのテスト

+ +

上記のテストはうまくいきますが、それほど楽しいことではありません。より面白いテストは、スケルトンプロジェクトを作成し、それが動作することを確認することです。これを行うには、コマンドプロンプト/ターミナルでDjangoアプリケーションを保存する場所に移動します。テストサイト用のフォルダを作成し、そのサイトに移動します。

+ +
mkdir django_test
+cd django_test
+
+ +

次に示すように、django-adminツールを使用して、 "mytestsite"という新しいスケルトンサイトを作成します。サイトを作成したら、manage.pyというプロジェクト管理用のメインスクリプトがあるフォルダに移動します。

+ +
django-admin startproject mytestsite
+cd mytestsite
+ +

次に示すようにmanage.pyrunserverコマンドを使用して、このフォルダ内から開発用Webサーバーを実行できます。

+ +
$ python3 manage.py runserver
+Performing system checks...
+
+System check identified no issues (0 silenced).
+
+You have 14 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
+Run 'python manage.py migrate' to apply them.
+
+December 29, 2017 - 03:03:47
+Django version 2.0, using settings 'mytestsite.settings'
+Starting development server at http://127.0.0.1:8000/
+Quit the server with CONTROL-C.
+
+ +
+

ノート: 上記のコマンドは、Linux/macOS Xコマンドを示しています。この時点では、 "14 unapplied migration(s)" という警告は無視できます!

+
+ +

サーバーが稼働したら、ローカルWebブラウザで http://127.0.0.1:8000/ というURLに移動して、サイトを表示できます。次のようなサイトが表示されます:

+ +

Django Skeleton App Homepage

+ + + +

要約

+ +

Django開発環境をあなたのコンピュータ上で稼働できるようになりました。

+ +

テストのセクションでは、django-admin startprojectを使用して新しいDjango Webサイトを作成する方法と、開発用Webサーバー(python3 manage.py runserver)を使用してブラウザで実行する方法についても簡単に説明しました。次の記事では、このプロセスを拡張して、シンプルで完全なWebアプリケーションを構築します。

+ +

参考文献

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}

+ +

このモジュール内

+ + + +

 

diff --git a/files/ja/learn/server-side/django/index.html b/files/ja/learn/server-side/django/index.html new file mode 100644 index 0000000000..cdb4304f5d --- /dev/null +++ b/files/ja/learn/server-side/django/index.html @@ -0,0 +1,69 @@ +--- +title: Djangoウェブフレームワーク (Python) +slug: Learn/Server-side/Django +tags: + - Python + - django + - ウェブアプリケーションフレームワーク + - サーバーサイドプログラミング + - プログラミング + - 初心者 + - 学習 + - 概要 +translation_of: Learn/Server-side/Django +--- +
{{LearnSidebar}}
+ +

Django は、Python で書かれた高機能なサーバーサイドウェブフレームワークで、とても普及しています。このモジュールは、Django が最も人気のあるウェブサーバーフレームワークの 1 つである理由、開発環境の設定方法、独自のウェブアプリケーションを作成する方法を説明します。

+ +

前提条件

+ +

このモジュールを進める前に、Django を知る必要はありません。理想は、サーバー・サイドのウェブサイトプログラミング第一歩 を読んで、サーバーサイドのウェブプログラミングとウェブフレームワークについて理解しておくことです。

+ +

プログラミングの概念と Python に関する一般的な知識はあるとよいですが、コアの概念を理解することは必須ではありません。

+ +
+

: Python は、初心者が読んで理解しやすい最も簡単なプログラミング言語の 1 つです。つまり、あなたがこのモジュールをより理解したいのであれば、インターネット上の多数の無料の書籍やチュートリアルがあなたを助けてくれます。(新しいプログラマーは python.org wiki の Python for Non Programmers ページをチェックすると良いでしょう。)

+
+ +

ガイド

+ +
+
Django の紹介
+
最初の Django の記事では、 "Django とは何ですか?" という疑問に答え、このウェブフレームワークの特徴と概要を説明します。主な機能の概要と、このモジュールで詳しく説明しない高度な機能などを紹介します。また、Django アプリケーションの主要な構成部品のいくつかを示して、使いはじめる前にどのように使うのか、何ができるのかを知っておきます。
+
Django 開発環境の設定
+
Django がどのようなものか知ったので、次は Windows、Linux (Ubuntu)、Mac OS X でDjango 開発環境をセットアップしてテストする方法を説明します。一般的なオペレーティングシステムを使っていれば、この記事で Django アプリケーションの開発を始められるでしょう。
+
Django チュートリアル: 地域図書館ウェブサイト
+
最初の記事は、実践的なチュートリアルで学習する内容を説明し、「地域図書館ウェブサイト」の概要を示します。このウェブサイトの例は、後の記事で作り進めていきます。
+
Django チュートリアル Part 2: ウェブサイトの骨組み作成
+
この記事は、基本的なウェブサイトプロジェクトの「骨組み」をどのように作っていくのかを示します。サイト固有の設定、URL、モデル、ビュー、テンプレートを作成する方法について説明します。
+
Django チュートリアル Part 3: モデルの使用
+
この記事は、地域図書館ウェブサイト用のモデルを定義する方法を示します ― モデルはアプリケーションのデータを格納するデータ構造を表し、Django はデータベースにデータを格納できます。モデルとは何か、どのように定義されるのか、および主要なフィールドタイプのいくつかを説明します。また、モデルデータにアクセスする主な方法のいくつかを簡単に示します。
+
Django チュートリアル Part 4: Django 管理サイト
+
地域図書館ウェブサイトのモデルを作成したので、Django 管理サイトを使用して実際の書籍データを追加します。最初に、管理サイトにモデルを登録する方法を示します。その後、ログインしてデータを作成する方法を示します。最後に、管理サイトの表示を改善する方法をいくつか示します。
+
Django チュートリアル Part 5: ホームページの作成
+
最初のページ全体を表示するコードを追加する準備が整いました。ここでは地域図書館ウェブサイトのホームページで各モデルタイプのレコード数を表示し、他のページへのサイドバーナビゲーションリンクを提供します。基本的な URL マップやビューを作成したり、データベースからレコードを取得したり、テンプレートを使用して実践的な経験を積むことができます。
+
Django チュートリアル Part 6: 汎用の一覧表示と詳細表示
+
このチュートリアルでは、地域図書館ウェブサイトを拡張し、書籍や著者の一覧と詳細ページを追加します。ここでは、汎用のクラスベースのビューについて学び、共通のユースケースのために書くコードの量をどのように減らせるかを示します。またURLのパターンマッチングがどのように行われるのか詳しく説明します。
+
Django チュートリアル Part 7: セッションフレームワーク
+
このチュートリアルでは、地域図書館ウェブサイトを拡張し、ホームページにセッションベースのアクセスカウンターを追加します。これは比較的簡単な例ですが、セッションフレームワークを使用して、自分のサイトの匿名ユーザーに永続的な動作を提供する方法を示しています。
+
Django チュートリアル Part 8: ユーザー認証と権限
+
このチュートリアルでは、ユーザーが自分のアカウントで自分のサイトにログインできるようにする方法と、ログインできるかどうかを制御する方法、ログインしているかどうか、アクセス許可によって表示する方法について説明します。このデモンストレーションの一環として、地域図書館ウェブサイトを拡張し、ログインページとログアウトページを追加し、貸し出された本を表示するためのユーザーとスタッフのページを追加します。
+
Django チュートリアル Part 9: フォームの操作
+
このチュートリアルでは、Django で HTML フォームを扱う方法、特にモデルインスタンスを作成、更新、削除するためのフォームを書く最も簡単な方法を紹介します。このデモンストレーションの一環として、図書館員が書籍を更新したり、管理アプリケーションを使用するのではなく独自のフォームを使用して著者の作成、更新、削除を行えるように、地域図書館ウェブサイトを拡張します。
+
Django チュートリアル Part 10: Django ウェブアプリケーションのテスト
+
ウェブサイトが成長するにつれて、手動でテストするのが困難になります。コンポーネント間のやりとりが複雑になるにつれて、ある領域の小さな変更が、他の領域へ影響がないか検証するためのテストの追加が多く必要になります。これらの問題を軽減する1つの方法は、変更を行うたびに簡単かつ確実に実行できる自動テストを作成することです。このチュートリアルでは、Django のテストフレームワークを使用して、あなたのウェブサイトの単体テストを自動化する方法を示します。
+
Django チュートリアル Part 11: Django を本番環境にデプロイする
+
これで、地域図書館の素晴らしいウェブサイトを作成 (およびテスト) できました。公開ウェブサーバーにインストールして、図書館のスタッフやメンバーがインターネット経由でアクセスできるようにしたいですね。この記事では、ウェブサイトを展開するホストを見つける方法と、サイトを実稼働のために必要な準備作業の概要について説明します。
+
Django ウェブアプリケーションセキュリティ
+
ユーザーデータの保護は、ウェブサイトの設計において不可欠な要素です。以前、ウェブセキュリティの記事でより一般的なセキュリティ上の脅威のいくつかについて説明しました。この記事では、Django の組み込み保護がそのような脅威をどのように処理するかを実践的に実演します。
+
+ +

課題

+ +

次の課題では、上記のガイドに記載されているように、Django を使用してウェブサイトを作成する方法を理解しているかテストします。

+ +
+
DIY Django ミニブログ
+
この課題では、このモジュールから学んだ知識の一部を使用して自分のブログを作成します。
+
diff --git a/files/ja/learn/server-side/django/introduction/index.html b/files/ja/learn/server-side/django/introduction/index.html new file mode 100644 index 0000000000..882c54bb56 --- /dev/null +++ b/files/ja/learn/server-side/django/introduction/index.html @@ -0,0 +1,281 @@ +--- +title: Djangoの紹介 +slug: Learn/Server-side/Django/Introduction +tags: + - Python + - Webフレームワーク + - django + - サーバーサイドプログラミング +translation_of: Learn/Server-side/Django/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
+ +

最初のDjangoの記事では、 "Djangoとは何ですか?" という疑問に答え、このWebフレームワークの特徴と概要を説明します。主な機能の概要と、このモジュールで詳しく説明しない高度な機能などを紹介します。 また、Djangoアプリケーションの主要な構成部品のいくつかを示します。 (この時点ではまだテストできる開発環境を持っていません).

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシーを持っていること。サーバーサイドウェブプログラミング の一般的な理解、特にウェブサイトにおけるクライントとサーバーのやりとりの仕組みを理解していること。
目的:Djangoが何であるか、Djangoの持つ機能、そしてDjangoアプリケーションの主要な構成部品に精通します。
+ +

Djangoとは何ですか?

+ +

Djangoは、安全でメンテナンス可能なWebサイトの迅速な開発を可能にする、高度なPython Webフレームワークです。経験豊富な開発者によって開発されたDjangoは、Web開発の多くの面倒事を引き受けてくれます。そのため車輪の再発明が不要で、アプリケーションを書くことに集中できます。無料でオープンソースであり、活発なコミュニティ、偉大なドキュメントがあります。また、無料と有料のサポートの多くのオプションもあります。 

+ +

Djangoの以下の特徴はソフトウェアを書くのに役立ちます:

+ +
+
完全
+
Djangoは "Batteries included" の哲学に従い、開発者が "すぐに" やりたいことのほとんどを提供します。必要なものはすべて1つの「製品」に含まれているため、すべてがシームレスに連携し、一貫した設計原則に従います。そして、豊富な最新のドキュメントが用意されています。
+
多彩
+
Djangoは、コンテンツ管理システムやWikiからソーシャルネットワーク、ニュースサイトなど、ほとんどのタイプのWebサイトを構築できます。任意のクライアントサイドのフレームワークで動作し、HTML、RSSフィード、JSON、XMLなどのほとんどの形式のコンテンツを配信できます。現在読んでいるサイトもDjangoベースですよ!
+
+ 内部的には、必要となるほとんどの機能(人気のあるデータベースやテンプレートエンジンなど)の選択肢を提供していますが、他のコンポーネントを使用するように拡張もできます。
+
安全
+
Djangoは、Webサイトを自動的に保護するために "正しいことをする" ように設計されたフレームワークです。多くの一般的なセキュリティミスを開発者が避けられるようにできています。例えば、セッション情報を脆弱な場所に置いたり、パスワードを直接保存するといった一般的なミスをDjangoでは避けるようになっています。セッション情報は、クッキーにセッションキーだけを格納し、実際のセッションデータはデータベースに保存されます。パスワードはパスワードハッシュをデータベースに格納します。このようにユーザーアカウントとパスワードを安全に管理する方法を提供しています。
+
+ パスワードハッシュは、送信されたパスワードから 暗号化ハッシュ関数を介して生成された固定長の値です。 Djangoは入力されたパスワードが正しいかどうかを、ハッシュ関数を介した値と保存されたハッシュ値を比較することでチェックできます。これは "一方向性" の機能であり、もし保存されているハッシュ値が侵害されても、攻撃者が元のパスワードを解読するのは困難です。
+
+ Djangoは、SQLインジェクション、クロスサイトスクリプティング(XSS)、クロスサイトリクエストフォージェリ(CSRF)、クリックジャッキングなどの多くの脆弱性に対する保護が有効です(これらの攻撃についての詳細は、 ウェブサイトのセキュリティ を参照してください)。
+
スケーラブル
+
Djangoはコンポーネントベースの “シェアードナッシング” アーキテクチャを採用しています(アーキテクチャの各部分は他と独立しており、必要に応じて置き換え、変更できます)。異なる部分を明確に分離しているため、キャッシュサーバー、データベースサーバー、アプリケーションサーバーの各ハードウェアをそれぞれ追加することによって、トラフィックの増加に合わせてスケールできるようになっています。いくつかの最も忙しいサイトは、ニーズを満たすためにDjangoを適切にスケールさせています(InstagramやDisqusなど)
+
メンテナンス可能
+
Djangoのコードは、保守可能で再利用可能になるような設計原則、デザインパターンを使って書かれています。特に、Do not Repeat Yourself(DRY)原則によって不要な複製がなく、コード量を削減します。Djangoは、関連する機能を再利用可能な "アプリケーション" にグループ化し、低いレベルでは関連するコードをモジュールにグループ化します(モデルビューコントローラ(MVC)パターンに沿っています)。
+
ポータブル
+
Djangoのコードは多くのプラットフォームで動作するPythonで書かれています。これはあなたがプラットフォームに縛られていないことを意味します。アプリケーションは多くの種類のLinux、Windows、Mac OS Xで実行できます。さらに、Djangoは多くのホスティングプロバイダによってよくサポートされています。Djangoサイトを特定のインフラストラクチャでホスティングするために、ドキュメントを提供していることが多いです。
+
+ +

どこから来たの?

+ +

Djangoは当初、2003年から2005年の間に、新聞のウェブサイトの作成とメンテナンスを担当するWebチームによって開発されました。いくつかのサイトを作成した後、チームは多くの共通コードとデザインパターンを除外、再利用するようになりました。この共通コードは、"Django" プロジェクトとして2005年7月にオープンソース化され、汎用のWeb開発フレームワークに発展しました。 

+ +

Djangoは、2008年9月の最初のマイルストーンリリース(1.0)から、最新のリリースバージョンである2.0(2017)まで、成長を続けています。 各リリースでは、新しいタイプのデータベース、テンプレートエンジン、キャッシュのサポートから、"汎用"ビュー機能とクラスの追加(プログラミングタスクで開発者が記述しなければならないコード量を削減します)などの新機能追加やバグフィックスがありました。 

+ +
+

ノート: DjangoのWebサイトの リリースノート をチェックして、最近のバージョンで何が変わったのか、どのような作業がDjangoを改善しているのか確認してください。

+
+ +

Djangoは現在、活発なオープンソースプロジェクトであり、何千人ものユーザーとコントリビュータがいます。元々の起源に関連するいくつかの機能はまだありますが、DjangoはあらゆるタイプのWebサイトを開発できる汎用フレームワークに進化しました。 

+ +

Djangoはどれくらい普及していますか?

+ +

サーバーサイドのフレームワークの普及率を決定的に測定する、すぐに利用できるものはありません (Hot Frameworks のようなサイトでは、GitHubプロジェクトの数や、各プラットフォームのStackOverflowの質問数をカウントするなどのメカニズムを使用して人気を評価しています) より良い質問は、「人気のないプラットフォームで問題を避けるために、Djangoは "人気がある" かどうか」、「それは進化し続けていますか?」「必要なときに助けを得ることができますか?」「Djangoを学べば、仕事を得る機会がありますか?」などです。

+ +

Djangoを使用している有名なサイトの数、コードベースにコントリビュートする人数、無料と有料の両方でサポートを提供する人数に基づいて、Djangoは普及しているフレームワークと言えるでしょう。

+ +

Djangoを使用している有名なサイト: Disqus、Instagram、Knight Foundation、MacArthur Foundation、Mozilla、National Geographic、Open Knowledge Foundation、Pinterest、Open Stack (ソース: Djangoホームページ)

+ +

Djangoはこだわりが強いですか?

+ +

Webフレームワークは、自身を "こだわりが強い" か "こだわりが強くない" と呼ぶことがあります。

+ +

こだわりが強いフレームワークは、特定のタスクを処理するための "正しい方法" についてこだわりを持っています。特定のドメイン(特定の種類の問題の解決)は、どのように扱うと正しいか、広く知られており、文書化もされているため、迅速な開発をサポートします。 しかし、主ドメイン以外の問題解決において柔軟性を欠き、使用できるコンポーネントのやアプローチの選択肢が少なくなる傾向があります。

+ +

対照的に、こだわりの強くないフレームワークは、目的を達成するための最善の結合されたコンポーネントの提供や、使用するコンポーネントを制限することが非常に少ないです。開発者は、特定のタスクを完了するために最も適したツールを簡単に使用できます。ただし、それらのコンポーネントを自分で見つける必要があります。
+
+ Djangoは "多少こだわりがある" ので、 "両方の世界のベスト" を提供します。 ほとんどのWeb開発タスクを処理するための一連のコンポーネントと、それを使う1つ(または2つ)の正しい方法を提供します。Djangoの分離アーキテクチャでは、通常、さまざまなオプションから選択しますが、必要に応じて新しいオプションを追加できます。

+ +

Djangoコードはどのように見えますか?

+ +

昔ながらのデータ駆動型Webサイトでは、WebアプリケーションはWebブラウザ(または他のクライアント)からのHTTPリクエストを待ちます。リクエストを受信すると、アプリケーションは、URLおよび、GET や POST データの情報に基づいて必要な処理を行います。 必要に応じてデータベースの情報を読み書きしたり、要求を満たすために必要なタスクを実行できます。 アプリケーションはWebブラウザに応答を返す際、検索したデータをHTMLテンプレートのプレースホルダに挿入し、動的にHTMLページを生成することがよくあります。

+ +

Django Webアプリケーションは、通常、これらの各ステップを処理するコードを別々のファイルにグループ化します:

+ +

+ + + +
+

ノート: Djangoはこの構成を "モデルビューテンプレート(Model View Template, MVT)" アーキテクチャと呼んでいます。これは Model View Controller アーキテクチャとよく似ています。 

+
+ + + +

以下のセクションでは、Djangoアプリケーションの主要部分の外観について説明します(開発環境を設定後、詳しく説明します)。

+ +

リクエストを正しいビューに送信する(urls.py)

+ +

URLマッパーは通常、urls.pyという名前のファイルに格納されます。以下の例では、マッパー(urlpatterns)はルート(特定のURLパターン) と対応するビュー関数のマッピングのリストを定義します。指定されたパターンと一致するURLを持つHTTPリクエストが受信されると、関連するビュー関数が呼び出され、リクエストを渡します。

+ +
urlpatterns = [
+    path('admin/', admin.site.urls),
+    path('book/<int:id>/', views.book-detail, name='book_detail'),
+    path('catalog/', include('catalog.urls')),
+    re_path(r'^([0-9]+)/$', views.best),
+]
+
+ +

 

+ +

urlpatternsオブジェクトはpath()re_path()関数のリストです(Pythonのリストは角括弧を使って定義され、アイテムはカンマ区切りです。末尾のカンマは任意です。例:  [item1, item2, item3,]

+ +

両方の関数の最初の引数は、一致させたいルート(パターン)です。path() 関数では、かぎ括弧を使って、ビュー関数に名前付き引数として渡されるURLの部分を定義します。 re_path() 関数では、柔軟なパターンマッチング方法として知られている正規表現を使います。 これらについては後の記事で説明します。

+ +

2つ目の引数は、パターンに一致したときに呼び出される別の関数です。views.book_detailという表記は、呼び出されたviewsモジュール内(views.pyという名前のファイル内部)で見つかるbook_detail()関数が呼び出されることを示します。

+ +

 

+ +

リクエストの処理(views.py)

+ +

ビューは、Webアプリケーションの中心であり、WebクライアントからHTTPリクエストを受け取り、HTTPレスポンスを返します。その中では、データベースにアクセスしたり、テンプレートをレンダリングしたりして、フレームワークの他のリソースを変換します。

+ +

以下の例は、前のセクションのURLマッパーによって呼び出される最小限の index() ビュー関数を示しています。すべてのビュー関数と同様に、HttpRequestオブジェクトをパラメータ(request)として受け取り、HttpResponseオブジェクトを返却します。この場合、リクエストには何もしません。レスポンスはハードコードされた文字列を返します。後のセクションで、もっと興味深いことをするリクエストを示します。

+ +
## filename: views.py (Django view functions)
+
+from django.http import HttpResponse
+
+def index(request):
+    # Get an HttpRequest - the request parameter
+    # perform operations using information from the request.
+    # Return HttpResponse
+    return HttpResponse('Hello from Django!')
+
+ +
+

ノート: Pythonについて少し:

+ + +
+ + + +

ビューは通常 views.py ファイルに格納します。

+ +

データモデルの定義(models.py)

+ +

Django Webアプリケーションは、モデルと呼ばれるPythonオブジェクトを通じてデータを管理し、クエリを実行します。モデルは、フィールドのタイプや、最大サイズ、デフォルト値、選択リストのオプション、ドキュメントのヘルプテキスト、フォームのラベルテキストなど、格納されるデータの構造を定義します。モデルの定義は、下層のデータベース(プロジェクト設定でいくつかから選択できます)からは独立しています。使用したいデータベースを選択したあとは、直接そのデータベースとやりとりする必要はありません。モデル構造と他のコードを書くだけで、Djangoはデータベースとのやりとりのすべての面倒な作業を処理します。

+ +

以下のコードスニペットは、Teamオブジェクトの非常に単純なDjangoモデルを示しています。Teamクラスは、Djangoのmodels.Modelクラスを継承しています。これは、チーム名とチームレベルを文字列フィールドとして定義し、各レコードに格納する最大文字数を指定します。team_levelはいくつかの値の一つになる可能性があります。したがって、この値を選択フィールドとして定義し、表示する選択項目と保存するデータの間のマッピングをデフォルト値とともに提供します。

+ +
# filename: models.py
+
+from django.db import models
+
+class Team(models.Model):
+    team_name = models.CharField(max_length=40)
+
+    TEAM_LEVELS = (
+        ('U09', 'Under 09s'),
+        ('U10', 'Under 10s'),
+        ('U11', 'Under 11s'),
+        ...  #list other team levels
+    )
+    team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
+
+ +
+

ノート: Pythonについて少し:

+ + +
+ +

データの問い合わせ(views.py)

+ +

Djangoモデルは、データベースを検索するための簡単なクエリAPIを提供します。これは、さまざまな照合基準(例:完全一致、大文字小文字を区別しない、大なりなど)を使用して一度にいくつかのフィールドと照合でき、複雑なステートメントをサポートできます(たとえば、「U11チームのうち、"Fr"で始まるか"al"で終わる名前」)。

+ +

コードスニペットには、U09チームのすべてを表示するためのビュー機能(リソースハンドラ)が示されています。太字の線は、モデルクエリAPIを使用して、team_level フィールドに完全一致でテキスト 'U09' があるすべてのレコードをフィルタリングする方法を示しています。 (filter() 関数には、照合基準としてフィールド名とマッチタイプをダブルアンダースコアで区切った引数で渡していることに注意してください: team_level__exact)

+ +
## filename: views.py
+
+from django.shortcuts import render
+from .models import Team
+
+def index(request):
+    list_teams = Team.objects.filter(team_level__exact="U09")
+    context = {'youngest_teams': list_teams}
+    return render(request, '/best/index.html', context)
+
+ +
+
+ +

この関数は、ブラウザに返信されるHttpResponseを生成するために render() 関数を使います。この関数はショートカットです。指定されたHTMLテンプレートとテンプレートに挿入するいくつかのデータ("context"という名前の変数で提供される)を組み合わせてHTMLファイルを作成します。次のセクションでは、HTMLを作成するためにテンプレートにデータがどのように挿入されているかを示します。

+ +

データのレンダリング(HTMLテンプレート)

+ +

テンプレートシステムでは、出力ドキュメントの構造を指定できます。ページの生成時に埋められるデータはプレースホルダを使用します。テンプレートはHTMLを作成するためによく使われますが、他のタイプドキュメントも作成できます。Djangoはネイティブのテンプレートシステムと、Jinja2と呼ばれる一般的なPythonライブラリの両方をサポートしています。(必要に応じて他のシステムもサポートできます)

+ +

コードスニペットは、前のセクションの render()関数で呼び出されるHTMLテンプレートの外観を示しています。 このテンプレートは、レンダリング時にyoungest_teams というリスト変数(上記のrender()関数によってコンテキスト変数に含まれます)にアクセスできる前提で作成されています。HTMLスケルトンでは、youngest_teams変数が存在するかどうかを最初にチェックし、それを forループで繰り返す式があります。各繰り返しにおいて、テンプレートは各チームのteam_name値を{{htmlelement("li")}}要素に表示します。

+ +
## filename: best/templates/best/index.html
+
+<!DOCTYPE html>
+<html lang="en">
+<body>
+
+ {% if youngest_teams %}
+    <ul>
+    {% for team in youngest_teams %}
+        <li>\{\{ team.team_name \}\}</li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>No teams are available.</p>
+{% endif %}
+
+</body>
+</html>
+ +

他に何ができますか?

+ +

前のセクションでは、ほとんどのWebアプリケーションで使用する主な機能(URLマッピング、ビュー、モデルおよびテンプレート)を示しました。Djangoが提供する他の機能のいくつかを紹介します:

+ + + +

要約

+ +

おめでとう、あなたはDjangoの旅の最初のステップを完了しました!Djangoの主なメリット、歴史について少し分かって、Djangoアプリケーションの主要部分のそれぞれがどのように見えるかを理解する必要があります。リスト、関数、クラスの構文も含めて、Pythonプログラミング言語についていくつか学んだことがあります。

+ +

上記では実際のDjangoコードをいくつか見ましたが、クライアントサイドのコードとは異なり、実行するための開発環境をセットアップする必要があります。それが次のステップです。

+ +
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
+ +

このモジュール内

+ + diff --git a/files/ja/learn/server-side/django/models/index.html b/files/ja/learn/server-side/django/models/index.html new file mode 100644 index 0000000000..fb3952f6b9 --- /dev/null +++ b/files/ja/learn/server-side/django/models/index.html @@ -0,0 +1,461 @@ +--- +title: 'Django チュートリアル Part 3: モデルの使用' +slug: Learn/Server-side/Django/Models +translation_of: Learn/Server-side/Django/Models +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}
+ +

この記事では、LocalLibrary Web サイトのモデルを定義する方法を説明します。モデルとは何か、その宣言方法、および主要なフィールドタイプについて説明します。また、モデルデータにアクセスするための主な方法のいくつかについても簡単に説明します。

+ + + + + + + + + + + + +
前提条件:Django チュートリアル Part 2: Web サイトの骨組み作成.
目標:適切なフィールドを選択しながら、独自のモデルを設計および作成できるようになる。
+ +

概要

+ +

Django web applications access and manage data through Python objects referred to as models. Models define the structure of stored data, including the field types and possibly also their maximum size, default values, selection list options, help text for documentation, label text for forms, etc. The definition of the model is independent of the underlying database — you can choose one of several as part of your project settings. Once you've chosen what database you want to use, you don't need to talk to it directly at all — you just write your model structure and other code, and Django handles all the dirty work of communicating with the database for you.

+ +

This tutorial shows how to define and access the models for the LocalLibrary website example.

+ +

Designing the LocalLibrary models

+ +

Before you jump in and start coding the models, it's worth taking a few minutes to think about what data we need to store and the relationships between the different objects.

+ +

We know that we need to store information about books (title, summary, author, written language, category, ISBN) and that we might have multiple copies available (with globally unique id, availability status, etc.). We might need to store more information about the author than just their name, and there might be multiple authors with the same or similar names. We want to be able to sort information based on book title, author, written language, and category.

+ +

When designing your models it makes sense to have separate models for every "object" (a group of related information). In this case, the obvious objects are books, book instances, and authors.

+ +

You might also want to use models to represent selection-list options (e.g. like a drop down list of choices), rather than hard coding the choices into the website itself — this is recommended when all the options aren't known up front or may change. Obvious candidates for models, in this case, include the book genre (e.g. Science Fiction, French Poetry, etc.) and language (English, French, Japanese).

+ +

Once we've decided on our models and field, we need to think about the relationships. Django allows you to define relationships that are one to one (OneToOneField), one to many (ForeignKey) and many to many (ManyToManyField).

+ +

With that in mind, the UML association diagram below shows the models we'll define in this case (as boxes).

+ +

LocalLibrary Model UML

+ +

We've created models for the book (the generic details of the book), book instance (status of specific physical copies of the book available in the system), and author. We have also decided to have a model for the genre so that values can be created/selected through the admin interface. We've decided not to have a model for the BookInstance:status — we've hardcoded the values (LOAN_STATUS) because we don't expect these to change. Within each of the boxes, you can see the model name, the field names, and types, and also the methods and their return types.

+ +

The diagram also shows the relationships between the models, including their multiplicities. The multiplicities are the numbers on the diagram showing the numbers (maximum and minimum) of each model that may be present in the relationship. For example, the connecting line between the boxes shows that Book and a Genre are related. The numbers close to the Genre model show that a book must have one or more Genres (as many as you like), while the numbers on the other end of the line next to the Book model show that a Genre can have zero or many associated books.

+ +
+

Note: The next section provides a basic primer explaining how models are defined and used. As you read it, consider how we will construct each of the models in the diagram above.

+
+ +

Model primer

+ +

This section provides a brief overview of how a model is defined and some of the more important fields and field arguments.

+ +

Model definition

+ +

Models are usually defined in an application's models.py file. They are implemented as subclasses of django.db.models.Model, and can include fields, methods and metadata. The code fragment below shows a "typical" model, named MyModelName:

+ +
from django.db import models
+
+class MyModelName(models.Model):
+    """A typical class defining a model, derived from the Model class."""
+
+    # Fields
+    my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')
+    ...
+
+    # Metadata
+    class Meta:
+        ordering = ['-my_field_name']
+
+    # Methods
+    def get_absolute_url(self):
+        """Returns the url to access a particular instance of MyModelName."""
+        return reverse('model-detail-view', args=[str(self.id)])
+
+    def __str__(self):
+        """String for representing the MyModelName object (in Admin site etc.)."""
+        return self.my_field_name
+ +

In the below sections we'll explore each of the features inside the model in detail:

+ +

Fields

+ +

A model can have an arbitrary number of fields, of any type — each one represents a column of data that we want to store in one of our database tables. Each database record (row) will consist of one of each field value. Let's look at the example seen below:

+ +
my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')
+ +

Our above example has a single field called my_field_name, of type models.CharField — which means that this field will contain strings of alphanumeric characters. The field types are assigned using specific classes, which determine the type of record that is used to store the data in the database, along with validation criteria to be used when values are received from an HTML form (i.e. what constitutes a valid value). The field types can also take arguments that further specify how the field is stored or can be used. In this case we are giving our field two arguments:

+ + + +

The field name is used to refer to it in queries and templates. Fields also have a label, which is either specified as an argument (verbose_name) or inferred by capitalising the first letter of the field's variable name and replacing any underscores with a space (for example my_field_name would have a default label of My field name).

+ +

The order that fields are declared will affect their default order if a model is rendered in a form (e.g. in the Admin site), though this may be overridden.

+ +
Common field arguments
+ +

The following common arguments can be used when declaring many/most of the different field types:

+ + + +

There are many other options — you can view the full list of field options here.

+ +
Common field types
+ +

The following list describes some of the more commonly used types of fields. 

+ + + +

There are many other types of fields, including fields for different types of numbers (big integers, small integers, floats), booleans, URLs, slugs, unique ids, and other "time-related" information (duration, time, etc.). You can view the full list here.

+ +

Metadata

+ +

You can declare model-level metadata for your Model by declaring class Meta, as shown.

+ +
class Meta:
+    ordering = ['-my_field_name']
+
+ +

One of the most useful features of this metadata is to control the default ordering of records returned when you query the model type. You do this by specifying the match order in a list of field names to the ordering attribute, as shown above. The ordering will depend on the type of field (character fields are sorted alphabetically, while date fields are sorted in chronological order). As shown above, you can prefix the field name with a minus symbol (-) to reverse the sorting order.

+ +

So as an example, if we chose to sort books like this by default:

+ +
ordering = ['title', '-pubdate']
+ +

the books would be sorted alphabetically by title, from A-Z, and then by publication date inside each title, from newest to oldest.

+ +

Another common attribute is verbose_name, a verbose name for the class in singular and plural form:

+ +
verbose_name = 'BetterName'
+ +

Other useful attributes allow you to create and apply new "access permissions" for the model (default permissions are applied automatically), allow ordering based on another field, or to declare that the class is "abstract" (a base class that you cannot create records for, and will instead be derived from to create other models).

+ +

Many of the other metadata options control what database must be used for the model and how the data is stored (these are really only useful if you need to map a model to an existing database).

+ +

The full list of metadata options are available here: Model metadata options (Django docs).

+ +

Methods

+ +

A model can also have methods.

+ +

Minimally, in every model you should define the standard Python class method __str__() to return a human-readable string for each object. This string is used to represent individual records in the administration site (and anywhere else you need to refer to a model instance). Often this will return a title or name field from the model.

+ +
def __str__(self):
+    return self.field_name
+ +

Another common method to include in Django models is get_absolute_url(), which returns a URL for displaying individual model records on the website (if you define this method then Django will automatically add a "View on Site" button to the model's record editing screens in the Admin site). A typical pattern for get_absolute_url() is shown below.

+ +
def get_absolute_url(self):
+    """Returns the url to access a particular instance of the model."""
+    return reverse('model-detail-view', args=[str(self.id)])
+
+ +
+

Note: Assuming you will use URLs like /myapplication/mymodelname/2 to display individual records for your model (where "2" is the id for a particular record), you will need to create a URL mapper to pass the response and id to a "model detail view" (which will do the work required to display the record). The reverse() function above is able to "reverse" your url mapper (in the above case named 'model-detail-view') in order to create a URL of the right format.

+ +

Of course to make this work you still have to write the URL mapping, view, and template!

+
+ +

You can also define any other methods you like, and call them from your code or templates (provided that they don't take any parameters).

+ +

Model management

+ +

Once you've defined your model classes you can use them to create, update, or delete records, and to run queries to get all records or particular subsets of records. We'll show you how to do that in the tutorial when we define our views, but here is a brief summary.

+ +

Creating and modifying records

+ +

To create a record you can define an instance of the model and then call save().

+ +
# Create a new record using the model's constructor.
+record = MyModelName(my_field_name="Instance #1")
+
+# Save the object into the database.
+record.save()
+
+ +
+

Note: If you haven't declared any field as a primary_key, the new record will be given one automatically, with the field name id. You could query this field after saving the above record, and it would have a value of 1.

+
+ +

You can access the fields in this new record using the dot syntax, and change the values. You have to call save() to store modified values to the database.

+ +
# Access model field values using Python attributes.
+print(record.id) # should return 1 for the first record.
+print(record.my_field_name) # should print 'Instance #1'
+
+# Change record by modifying the fields, then calling save().
+record.my_field_name = "New Instance Name"
+record.save()
+ +

Searching for records

+ +

You can search for records that match certain criteria using the model's objects attribute (provided by the base class).

+ +
+

Note: Explaining how to search for records using "abstract" model and field names can be a little confusing. In the discussion below we'll refer to a Book model with title and genre fields, where genre is also a model with a single field name.

+
+ +

We can get all records for a model as a QuerySet, using objects.all(). The QuerySet is an iterable object, meaning that it contains a number of objects that we can iterate/loop through.

+ +
all_books = Book.objects.all()
+
+ +

Django's filter() method allows us to filter the returned QuerySet to match a specified text or numeric field against particular criteria. For example, to filter for books that contain "wild" in the title and then count them, we could do the following.

+ +
wild_books = Book.objects.filter(title__contains='wild')
+number_wild_books = wild_books.count()
+
+ +

The fields to match and the type of match are defined in the filter parameter name, using the format: field_name__match_type (note the double underscore between title and contains above). Above we're filtering title with a case-sensitive match. There are many other types of matches you can do: icontains (case insensitive), iexact (case-insensitive exact match), exact (case-sensitive exact match) and in, gt (greater than), startswith, etc. The full list is here.

+ +

In some cases you'll need to filter on a field that defines a one-to-many relationship to another model (e.g. a ForeignKey). In this case you can "index" to fields within the related model with additional double underscores. So for example to filter for books with a specific genre pattern, you will have to index to the name through the genre field, as shown below:

+ +
# Will match on: Fiction, Science fiction, non-fiction etc.
+books_containing_genre = Book.objects.filter(genre__name__icontains='fiction')
+
+ +
+

Note: You can use underscores (__) to navigate as many levels of relationships (ForeignKey/ManyToManyField) as you like. For example, a Book that had different types, defined using a further "cover" relationship might have a parameter name: type__cover__name__exact='hard'.

+
+ +

There is a lot more you can do with queries, including backwards searches from related models, chaining filters, returning a smaller set of values etc. For more information see Making queries (Django Docs).

+ +

Defining the LocalLibrary Models

+ +

In this section we will start defining the models for the library. Open models.py (in /locallibrary/catalog/). The boilerplate at the top of the page imports the models module, which contains the model base class models.Model that our models will inherit from.

+ +
from django.db import models
+
+# Create your models here.
+ +

Genre model

+ +

Copy the Genre model code shown below and paste it into the bottom of your models.py file. This model is used to store information about the book category — for example whether it is fiction or non-fiction, romance or military history, etc. As mentioned above, we've created the Genre as a model rather than as free text or a selection list so that the possible values can be managed through the database rather than being hard coded.

+ +
class Genre(models.Model):
+    """Model representing a book genre."""
+    name = models.CharField(max_length=200, help_text='Enter a book genre (e.g. Science Fiction)')
+
+    def __str__(self):
+        """String for representing the Model object."""
+        return self.name
+ +

The model has a single CharField field (name), which is used to describe the genre (this is limited to 200 characters and has some help_text. At the end of the model we declare a __str__() method, which simply returns the name of the genre defined by a particular record. No verbose name has been defined, so the field will be called Name in forms.

+ +

Book model

+ +

Copy the Book model below and again paste it into the bottom of your file. The book model represents all information about an available book in a general sense, but not a particular physical "instance" or "copy" available for loan. The model uses a CharField to represent the book's title and isbn (note how the isbn specifies its label as "ISBN" using the first unnamed parameter because the default label would otherwise be "Isbn"). The model uses TextField for the summary, because this text may need to be quite long.

+ +
from django.urls import reverse # Used to generate URLs by reversing the URL patterns
+
+class Book(models.Model):
+    """Model representing a book (but not a specific copy of a book)."""
+    title = models.CharField(max_length=200)
+
+    # Foreign Key used because book can only have one author, but authors can have multiple books
+    # Author as a string rather than object because it hasn't been declared yet in the file
+    author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
+
+    summary = models.TextField(max_length=1000, help_text='Enter a brief description of the book')
+    isbn = models.CharField('ISBN', max_length=13, help_text='13 Character <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>')
+
+    # ManyToManyField used because genre can contain many books. Books can cover many genres.
+    # Genre class has already been defined so we can specify the object above.
+    genre = models.ManyToManyField(Genre, help_text='Select a genre for this book')
+
+    def __str__(self):
+        """String for representing the Model object."""
+        return self.title
+
+    def get_absolute_url(self):
+        """Returns the url to access a detail record for this book."""
+        return reverse('book-detail', args=[str(self.id)])
+
+ +

The genre is a ManyToManyField, so that a book can have multiple genres and a genre can have many books. The author is declared as ForeignKey, so each book will only have one author, but an author may have many books (in practice a book might have multiple authors, but not in this implementation!)

+ +

In both field types the related model class is declared as the first unnamed parameter using either the model class or a string containing the name of the related model. You must use the name of the model as a string if the associated class has not yet been defined in this file before it is referenced! The other parameters of interest in the author field are null=True, which allows the database to store a Null value if no author is selected, and on_delete=models.SET_NULL, which will set the value of the author to Null if the associated author record is deleted.

+ +

The model also defines __str__() , using the book's title field to represent a Book record. The final method, get_absolute_url() returns a URL that can be used to access a detail record for this model (for this to work we will have to define a URL mapping that has the name book-detail, and define an associated view and template).

+ +

BookInstance model

+ +

Next, copy the BookInstance model (shown below) under the other models. The BookInstance represents a specific copy of a book that someone might borrow, and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details, and a unique id for the book in the library.

+ +

Some of the fields and methods will now be familiar. The model uses

+ + + +
import uuid # Required for unique book instances
+
+class BookInstance(models.Model):
+    """Model representing a specific copy of a book (i.e. that can be borrowed from the library)."""
+    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular book across whole library')
+    book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True)
+    imprint = models.CharField(max_length=200)
+    due_back = models.DateField(null=True, blank=True)
+
+    LOAN_STATUS = (
+        ('m', 'Maintenance'),
+        ('o', 'On loan'),
+        ('a', 'Available'),
+        ('r', 'Reserved'),
+    )
+
+    status = models.CharField(
+        max_length=1,
+        choices=LOAN_STATUS,
+        blank=True,
+        default='m',
+        help_text='Book availability',
+    )
+
+    class Meta:
+        ordering = ['due_back']
+
+    def __str__(self):
+        """String for representing the Model object."""
+        return f'{self.id} ({self.book.title})'
+ +

We additionally declare a few new types of field:

+ + + +

The model __str__() represents the BookInstance object using a combination of its unique id and the associated Book's title.

+ +
+

Note: A little Python:

+ + +
+ +

Author model

+ +

Copy the Author model (shown below) underneath the existing code in models.py.

+ +
class Author(models.Model):
+    """Model representing an author."""
+    first_name = models.CharField(max_length=100)
+    last_name = models.CharField(max_length=100)
+    date_of_birth = models.DateField(null=True, blank=True)
+    date_of_death = models.DateField('Died', null=True, blank=True)
+
+    class Meta:
+        ordering = ['last_name', 'first_name']
+
+    def get_absolute_url(self):
+        """Returns the url to access a particular author instance."""
+        return reverse('author-detail', args=[str(self.id)])
+
+    def __str__(self):
+        """String for representing the Model object."""
+        return f'{self.last_name}, {self.first_name}'
+
+ +

All of the fields/methods should now be familiar. The model defines an author as having a first name, last name, and dates of birth and death (both optional). It specifies that by default the __str__() returns the name in last name, firstname order. The get_absolute_url() method reverses the author-detail URL mapping to get the URL for displaying an individual author.

+ +

Re-run the database migrations

+ +

All your models have now been created. Now re-run your database migrations to add them to your database.

+ +
python3 manage.py makemigrations
+python3 manage.py migrate
+ +

Language model — challenge

+ +

Imagine a local benefactor donates a number of new books written in another language (say, Farsi). The challenge is to work out how these would be best represented in our library website, and then to add them to the models.

+ +

Some things to consider:

+ + + +

After you've decided, add the field. You can see what we decided on Github here.

+ +

Don't forget that after a change to your model, you should again re-run your database migrations to add the changes.

+ +
python3 manage.py makemigrations
+python3 manage.py migrate
+ + + + + +

Summary

+ +

In this article we've learned how models are defined, and then used this information to design and implement appropriate models for the LocalLibrary website.

+ +

At this point we'll divert briefly from creating the site, and check out the Django Administration site. This site will allow us to add some data to the library, which we can then display using our (yet to be created) views and templates.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}

+ + + +

In this module

+ + diff --git a/files/ja/learn/server-side/django/skeleton_website/index.html b/files/ja/learn/server-side/django/skeleton_website/index.html new file mode 100644 index 0000000000..0d76ae46eb --- /dev/null +++ b/files/ja/learn/server-side/django/skeleton_website/index.html @@ -0,0 +1,398 @@ +--- +title: 'Django チュートリアル Part 2: スケルトンウェブサイトの作成' +slug: Learn/Server-side/Django/skeleton_website +tags: + - django + - イントロダクション + - ガイド + - チュートリアル + - 初心者 + - 学習 + - 記事 +translation_of: Learn/Server-side/Django/skeleton_website +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}
+ +

Djangoチュートリアル の2つ目の記事では、基本的なウェブサイトプロジェクトの「スケルトン」をどのように作っていくのかを説明します。サイト固有の設定、URL、モデル、ビュー、テンプレートを作成する方法について説明します。

+ + + + + + + + + + + + +
前提条件:Django 開発環境の設定Djangoチュートリアルを確認してください。
目的:Djangoのツールを使って自分の新しいウェブサイトプロジェクトを開始できるようにする。
+ +

概要

+ +

この記事は、"スケルトン"ウェブサイトを作る方法を示します。そこにはサイト固有の設定、パス、モデル、ビューやテンプレートを組み込むことができるます。(これらについては後で述べます)

+ +

そのプロセスは単純です:

+ +
    +
  1. django-admin ツールを使ってプロジェクトフォルダ、基本的なテンプレートファイル、プロジェクト管理スクリプト(manage.py)を作ります .
  2. +
  3. manage.py は1つ以上のアプリケーションを作ります。 +
    +

    メモ: ウェブサイトは1つ以上のセクションから成ります。例えば、メインサイト、ブログ、ウィキ、ダウンロードエリアなど。Djangoは、これらのコンポーネントを別々のアプリケーションとして作成することを助けてくれます。それらは、必要なら異なるプロジェクトで再利用できます。

    +
    +
  4. +
  5. プロジェクトにアプリケーションを含めるために登録します。
  6. +
  7. url/path マッパーはそれらのアプリケーションを結びつけます。
  8. +
+ +

Local Library website のために、ウェブサイトフォルダとプロジェクトフォルダはlocallibrary という名前をつけます。また、1つのアプリケーションはcatalogという名前をつけます。 したがって、最上位のフォルダ構成は以下のようになります。:

+ +
locallibrary/         # Website foldermanage.py         # Script to run Django tools for this project (created using django-admin)
+    locallibrary/     # Website/project folder (created using django-admin)
+    catalog/          # Application folder (created using manage.py)
+
+ +

以下のセクションでは、その過程をもっと詳細に述べ、あなたが変更を試す方法を示しましょう。この記事の最後に、我々はいくつかの他のウェブサイトの設定について述べてみます。それはあなたがこのステージで行っていることかもしませんが。

+ +

プロジェクトの作成

+ +

始めにコマンドプロンプトまたはターミナルを開いて、(先に自分が仮想環境(virtual environment)にいることを確認して下さい)、Djangoアプリを格納したい場所へ移動します(ドキュメントフォルダの中など探しやすい場所にしましょう)。そして、新しいウェブサイトのフォルダ(この場合は locallibraryを作りましょう。そして、cdコマンドでそのフォルダへ移動しましょう。

+ +
mkdir locallibrary
+cd locallibrary
+ +

以下のように、django-admin startprojectコマンドで新しいプロジェクトを作り、そのフォルダの中に移動します。

+ +
django-admin startproject locallibrary
+cd locallibrary
+ +

django-adminツールは以下のようなフォルダ/ファイル構成を作ります。

+ +
locallibrary/manage.pylocallibrary/
+        settings.py
+        urls.py
+        wsgi.py
+ +

我々の現在の作業ディレクトリはこのようなものになっているでしょう。

+ +
../django_projects/locallibrary/
+ +

locallibraryプロジェクトのサブフォルダはこのウェブサイトに入口点となります: 

+ + + +

manage.py スクリプトはアプリケーションを作成したり、データベースを操作したり、webサーバを起動したりするのに使われます。

+ +

catalogアプリケーションの作成

+ +

次に、以下のコマンドを実行し、localibrary プロジェクトの中にアプリケーションを作りましょう。(このコマンドはプロジェクト内のmanage.pyと同じフォルダで実行する必要があります)

+ +
python3 manage.py startapp catalog
+ +
+

メモ: 上記コマンドは LinuxやmacOS X用です。Windows のコマンドは: py -3 manage.py startapp catalog

+ +

もしWindowsを使っているなら、このモジュール(manage.py)を使う際はpython3py -3 に変更して下さい。

+ +

もしPython 3.7.0以降を使用しているなら、py manage.py startapp catalogで使用できます。

+
+ +

このツールは新しいフォルダを作成し、アプリケーションの様々なパーツとなるファイルをそのフォルダに追加します(以下の太字で表示)。 ほとんどのファイルは目的に応じて便利な名前が付けられており(例えば ビューはviews.pyに、モジュールは models.pyに、テストはtests.pyに、管理サイトの設定は admin.pyに、アプリケーションの登録はapps.pyに保存する必要がある)、 さらに、関連するオブジェクトを操作するための最低限の定型的なコードを用意している。

+ +

アップデートされた後のプロジェクトディレクトリはこのようになる:

+ +
locallibrary/
+    manage.py
+    locallibrary/
+    catalog/
+        admin.py
+        apps.py
+        models.py
+        tests.py
+        views.py
+        __init__.py
+        migrations/
+
+ +

加えて今持っているものは:

+ + + +
+

メモ: 上記ファイルリストに何か欠けているものがあることに気づきましたか? ビューやモデルがある一方で、URLマッピング、テンプレート、静的ファイルの配置場所はありません。それらの作り方も以後説明します。(それらは全てのサイトで必須ではないですが、この例では必要になります。).

+
+ +

catalogアプリケーションの登録

+ +

アプリケーションが作成されたので、ツールを実行するために(例えばデータベースにモデルを追加する)プロジェクトに登録する必要がある。 アプリケーションの登録はプロジェクトの設定でINSTALLED_APPS リストに加えることで行えます。

+ +

プロジェクトの設定ファイル locallibrary/locallibrary/settings.py を開いて、INSTALLED_APPS リストの定義を見つけましょう。そして、以下のようにリストの最後に新しい行を追加しましょう。

+ +
INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'catalog.apps.CatalogConfig', 
+]
+ +

追加した新しい行はアプリケーションの構成オブジェクト(CatalogConfig) を指定しており、それはアプリケーション作成時に/locallibrary/catalog/apps.py によって生成されています。

+ +
+

メモ: すでにたくさんの他のINSTALLED_APPS (MIDDLEWAREも同様。設定ファイルのさらに下の方にあります)が存在していることに気づいたでしょう。これらは、Django administration site をサポートすること可能にし、その結果、Djangoが使用するたくさんの機能(セッション、認証など)をサポートします。

+
+ +

データベースの指定

+ +

これは、プロジェクトで使用するデータベースを特定する場所を指しています。— 開発と本番で動作のわずかな違いを避けるために、可能な限り同じデータベースを使用するのがよいでしょう。様々なDatabases オプションを確認することができます(Django docs)。

+ +

この例では、SQLite データベースを使いましょう。なぜなら、デモンストレーションデータベースでは多くの同時アクセスを必要とせず、セットアップ作業に追加の作業が不要だからです。このデータベースがどのように設定されているかは settings.py で確認できます。 (詳細は以下にも記載しています):

+ +
DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    }
+}
+
+ +

SQLiteを使っているので、ここではこれ以上のセットアップは不要です。次へ移りましょう!

+ +

その他のプロジェクト設定

+ +

settings.py ファイルは、ほかのいくつかの設定の構成にも使用されますが、この時点では TIME_ZONE を変更するだけでよいでしょう。これは、tzデータベースタイムゾーンの標準リストの文字列を同じにする必要があります。(テーブルのTZ列に必要な値が含まれています) TIME_ZONE の値を、あなたのタイムゾーンに適した文字列に変更しましょう。
+ 例を示します:

+ +
TIME_ZONE = 'Europe/London'
+ +

今は変更しないが、次の2つの設定があることに注意してください。

+ + + +

URLマッパーの接続

+ +

Webサイトは、プロジェクトフォルダー内のURLマッパーファイル(urls.py)で作成されます。このファイルを使用してすべてのURLマッピングを管理できますが、関連付けられたアプリケーションへマッピングを延ばすのがより一般的です。

+ +

 locallibrary/locallibrary/urls.py を開いて、URLマッパーを使うためのいくつかの方法を記した説明文に注意してください。

+ +
"""locallibrary URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/2.0/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path
+
+urlpatterns = [
+    path('admin/', admin.site.urls),
+]
+
+ +

The URL mappings are managed through the urlpatterns variable, which is a Python list of path() functions. Each path() function either associates a URL pattern to a specific view, which will be displayed when the pattern is matched, or with another list of URL pattern testing code (in this second case, the pattern becomes the "base URL" for patterns defined in the target module). The urlpatterns list initially defines a single function that maps all URLs with the pattern admin/ to the module admin.site.urls , which contains the Administration application's own URL mapping definitions.

+ +
+

Note: The route in path() is a string defining a URL pattern to match. This string might include a named variable (in angle brackets), e.g. 'catalog/<id>/'. This pattern will match a URL like /catalog/any_chars/ and pass any_chars to the view as a string with parameter name id). We discuss path methods and route patterns further in later topics.

+
+ +

Add the lines below to the bottom of the file in order to add a new list item to the urlpatterns list. This new item includes a path() that forwards requests with the pattern catalog/ to the module catalog.urls (the file with the relative URL /catalog/urls.py).

+ +
# Use include() to add paths from the catalog application
+from django.conf.urls import include
+from django.urls import path
+
+urlpatterns += [
+    path('catalog/', include('catalog.urls')),
+]
+
+ +

Now let's redirect the root URL of our site (i.e. 127.0.0.1:8000) to the URL 127.0.0.1:8000/catalog/; this is the only app we'll be using in this project, so we might as well. To do this, we'll use a special view function (RedirectView), which takes as its first argument the new relative URL to redirect to (/catalog/) when the URL pattern specified in the path() function is matched (the root URL, in this case).

+ +

Add the following lines, again to the bottom of the file:

+ +
#Add URL maps to redirect the base URL to our application
+from django.views.generic import RedirectView
+urlpatterns += [
+    path('', RedirectView.as_view(url='/catalog/')),
+]
+ +

Leave the first parameter of the path function empty to imply '/'. If you write the first parameter as '/' Django will give you the following warning when you start the development server:

+ +
System check identified some issues:
+
+WARNINGS:
+?: (urls.W002) Your URL pattern '/' has a route beginning with a '/'.
+Remove this slash as it is unnecessary.
+If this pattern is targeted in an include(), ensure the include() pattern has a trailing '/'.
+
+ +

Django does not serve static files like CSS, JavaScript, and images by default, but it can be useful for the development web server to do so while you're creating your site. As a final addition to this URL mapper, you can enable the serving of static files during development by appending the following lines. 

+ +

Add the following final block to the bottom of the file now:

+ +
# Use static() to add url mapping to serve static files during development (only)
+from django.conf import settings
+from django.conf.urls.static import static
+
+urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+
+ +
+

Note: There are a number of ways to extend the urlpatterns list (above we just appended a new list item using the += operator to clearly separate the old and new code). We could have instead just included this new pattern-map in the original list definition:

+ +
urlpatterns = [
+    path('admin/', admin.site.urls),
+    path('catalog/', include('catalog.urls')),
+    path('', RedirectView.as_view(url='/catalog/', permanent=True)),
+] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+
+ +

In addition, we included the import line (from django.urls import include) with the code that uses it (so it is easy to see what we've added), but it is common to include all your import lines at the top of a Python file.

+
+ +

As a final step, create a file inside your catalog folder called urls.py, and add the following text to define the (empty) imported urlpatterns. This is where we'll add our patterns as we build the application. 

+ +
from django.urls import path
+from . import views
+
+
+urlpatterns = [
+
+]
+
+ +

ウェブサイトフレームワークのテスト

+ +

At this point we have a complete skeleton project. The website doesn't actually do anything yet, but its worth running it to make sure that none of our changes have broken anything. 

+ +

Before we do that, we should first run a database migration. This updates our database to include any models in our installed applications (and removes some build warnings).

+ +

Running database migrations

+ +

Django uses an Object-Relational-Mapper (ORM) to map Model definitions in the Django code to the data structure used by the underlying database. As we change our model definitions, Django tracks the changes and can create database migration scripts (in /locallibrary/catalog/migrations/) to automatically migrate the underlying data structure in the database to match the model.

+ +

When we created the website Django automatically added a number of models for use by the admin section of the site (which we'll look at later). Run the following commands to define tables for those models in the database (make sure you are in the directory that contains manage.py):

+ +
python3 manage.py makemigrations
+python3 manage.py migrate
+
+ +
+

Important: You'll need to run the above commands every time your models change in a way that will affect the structure of the data that needs to be stored (including both addition and removal of whole models and individual fields).

+
+ +

The makemigrations command creates (but does not apply) the migrations for all applications installed in your project (you can specify the application name as well to just run a migration for a single project). This gives you a chance to checkout the code for these migrations before they are applied — when you're a Django expert you may choose to tweak them slightly!

+ +

The migrate command actually applies the migrations to your database (Django tracks which ones have been added to the current database).

+ +
+

Note: See Migrations (Django docs) for additional information about the lesser-used migration commands.

+
+ +

Running the website

+ +

During development you can test the website by first serving it using the development web server, and then viewing it on your local web browser. 

+ +
+

Note: The development web server is not robust or performant enough for production use, but it is a very easy way to get your Django website up and running during development to give it a convenient quick test. By default it will serve the site to your local computer (http://127.0.0.1:8000/), but you can also specify other computers on your network to serve to. For more information see django-admin and manage.py: runserver (Django docs).

+
+ +

Run the development web server by calling the runserver command (in the same directory as manage.py):

+ +
python3 manage.py runserver
+
+ Performing system checks...
+
+ System check identified no issues (0 silenced).
+ September 22, 2016 - 16:11:26
+ Django version 1.10, using settings 'locallibrary.settings'
+ Starting development server at http://127.0.0.1:8000/
+ Quit the server with CTRL-BREAK.
+
+ +

Once the server is running you can view the site by navigating to http://127.0.0.1:8000/ in your local web browser. You should see a site error page that looks like this:

+ +

Django Debug page for Django 2.0

+ +

Don't worry! This error page is expected because we don't have any pages/urls defined in the catalogs.urls module (which we're redirected to when we get an URL to the root of the site). 

+ +
+

Note: The above page demonstrates a great Django feature — automated debug logging. An error screen will be displayed with useful information whenever a page cannot be found, or any error is raised by the code. In this case we can see that the URL we've supplied doesn't match any of our URL patterns (as listed). The logging will be turned off during production (when we put the site live on the Web), in which case a less informative but more user-friendly page will be served.

+
+ +

At this point we know that Django is working! 

+ +
+

Note: You should re-run migrations and re-test the site whenever you make significant changes. It doesn't take very long!

+
+ +

自分でやってみよう

+ +

The catalog/ directory contains files for the views, models, and other parts of the application. Open these files and inspect the boilerplate. 

+ +

As you saw above, a URL-mapping for the Admin site has already been added in the project's urls.py. Navigate to the admin area in your browser and see what happens (you can infer the correct URL from the mapping above).

+ + + +

要約

+ +

You have now created a complete skeleton website project, which you can go on to populate with urls, models, views, and templates.

+ +

Now the skeleton for the Local Library website is complete and running, it's time to start writing the code that makes this website do what it is supposed to do. 

+ +

参考文献

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/server-side/django/tutorial_local_library_website/index.html b/files/ja/learn/server-side/django/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..d0d0f670f2 --- /dev/null +++ b/files/ja/learn/server-side/django/tutorial_local_library_website/index.html @@ -0,0 +1,99 @@ +--- +title: 'Django チュートリアル: 地域図書館ウェブサイト' +slug: Learn/Server-side/Django/Tutorial_local_library_website +tags: + - Python + - django + - チュートリアル + - 初心者 +translation_of: Learn/Server-side/Django/Tutorial_local_library_website +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}
+ +

実践的なチュートリアルシリーズの最初の記事は、学習する内容を説明し、後の記事で進めていく「地域図書館」のサンプルウェブサイトの概要を示しています。

+ + + + + + + + + + + + +
前提条件:Djangoの紹介を読んでください。以下の記事では、Django開発環境をセットアップする必要があります。
目的:このチュートリアルで使用されているサンプルアプリケーションを紹介し、読者が何をするかを理解できるようにします。
+ +

概要

+ +

MDN "地域図書館" Djangoチュートリアルへようこそ。ここでは、地域図書館のカタログを管理するためのWebサイトを開発します。

+ +

この一連のチュートリアルの記事でやることは次の通りです:

+ + + +

これらの話題のいくつかについて学び、他の話題にも簡単に触れました。チュートリアルシリーズの最後は、あなた自身で簡単なDjangoアプリケーションを開発するのに十分な知識が必要です。

+ +

地域図書館ウェブサイト

+ +

地域図書館(LocalLibrary)は、この一連のチュートリアルの過程で作成および展開するWebサイトの名前です。ご存じのように、ウェブサイトの目的は、利用可能な書籍を閲覧してアカウントを管理できる小さな地域図書館のオンラインカタログを提供することです。

+ +

この例は慎重に選択されています。なぜなら、必要に応じて細かく表示することができ、ほぼすべてのDjango機能を表示するために使用できます。 さらに重要なことは、Django Webフレームワークの最も重要な機能をガイドする方法を提供できることです:

+ + + +

これは非常に拡張可能な例ですが、地域図書館と呼んでいます。理由は、Djangoをすぐに起動して実行するのに役立つ最小限の情報を表示したいと考えているからです。つまり、書籍、本のコピー、作者関する情報、およびその他の重要な情報は保存します。しかし、図書館が保管する可能性のある他のアイテムに関する情報を保管したり、複数の図書館サイトやその他の「大きな図書館」機能をサポートするために必要なインフラストラクチャーを提供することはありません。

+ +

詰まってます、どこでソースを入手できますか?

+ +

チュートリアルを進めるうちに、各ポイントでコピー&ペーストするための適切なコードスニペットが提供されます。また、この他に自分で拡張してほしいコードもあります(いくつかのガイダンスがあります)。

+ +

詰まった場合は、ウェブサイトの完全に開発されたバージョンをGithub上で見ることができます。

+ +

要約

+ +

地域図書館ウェブサイトについてと、何を学ぶのかをもう少し知りました。今度は例を含むスケルトンプロジェクトを作成しましょう。

+ +

{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}

+ +

 

+ +

このモジュール内

+ + + +

 

diff --git a/files/ja/learn/server-side/django/web_application_security/index.html b/files/ja/learn/server-side/django/web_application_security/index.html new file mode 100644 index 0000000000..496fac0fbd --- /dev/null +++ b/files/ja/learn/server-side/django/web_application_security/index.html @@ -0,0 +1,180 @@ +--- +title: Django Web アプリケーションのセキュリティ +slug: Learn/Server-side/Django/web_application_security +translation_of: Learn/Server-side/Django/web_application_security +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}
+ +
ユーザーのデータを守ることはWebデザインにおいて重要です。 以前、より一般的なセキュリティの脅威の一部を Webセキュリティ の記事で説明しました— 本記事ではDjangoにビルトインされている保護機能がそのような脅威にどう対応しているか、より実践的な動きを見ながら説明していきます。
+ + + + + + + + + + + + +
前提条件:Read the サーバーサイドプログラミングの "Webサイトセキュリティ" の記事を読んでいること。Djangoチュートリアルを少なくとも Django Tutorial Part 9: Working with forms まで完了していること。
目標:Django Webアプリケーションをセキュアにするためにやるべきこと、やってはいけないことを理解する。
+ +

概要

+ +

The Website security topic provides an overview of what website security means for server-side design, and some of the more common threats that you may need to protect against. One of the key messages in that article is that almost all attacks are successful when the web application trusts data from the browser.

+ +
+

Important: The single most important lesson you can learn about website security is to never trust data from the browser. This includes GET request data in URL parameters, POST data, HTTP headers and cookies, user-uploaded files, etc. Always check and sanitize all incoming data. Always assume the worst.

+
+ +

The good news for Django users is that many of the more common threats are handled by the framework! The Security in Django (Django docs) article explains Django's security features and how to secure a Django-powered website.

+ +

Common threats/protections

+ +

Rather than duplicate the Django documentation here, in this article we'll demonstrate just a few of the security features in the context of our Django LocalLibrary tutorial.

+ +

Cross site scripting (XSS)

+ +

XSS is a term used to describe a class of attacks that allow an attacker to inject client-side scripts through the website into the browsers of other users. This is usually achieved by storing malicious scripts in the database where they can be retrieved and displayed to other users, or by getting users to click a link that will cause the attacker’s JavaScript to be executed by the user’s browser.

+ +

Django's template system protects you against the majority of XSS attacks by escaping specific characters that are "dangerous" in HTML. We can demonstrate this by attempting to inject some JavaScript into our LocalLibrary website using the Create-author form we set up in Django Tutorial Part 9: Working with forms.

+ +
    +
  1. Start the website using the development server (python3 manage.py runserver).
  2. +
  3. Open the site in your local browser and login to your superuser account.
  4. +
  5. Navigate to the author-creation page (which should be at URL: http://127.0.0.1:8000/catalog/author/create/).
  6. +
  7. Enter names and date details for a new user, and then append the following text to the Last Name field:
    + <script>alert('Test alert');</script>.
    + Author Form XSS test +
    +

    Note: This is a harmless script that, if executed, will display an alert box in your browser. If the alert is displayed when you submit the record then the site is vulnerable to XSS threats.

    +
    +
  8. +
  9. Press Submit to save the record.
  10. +
  11. When you save the author it will be displayed as shown below. Because of the XSS protections the alert() should not be run. Instead the script is displayed as plain text.Author detail view XSS test
  12. +
+ +

If you view the page HTML source code, you can see that the dangerous characters for the script tags have been turned into their harmless escape code equivalents (e.g. > is now &gt;)

+ +
<h1>Author: Boon&lt;script&gt;alert(&#39;Test alert&#39;);&lt;/script&gt;, David (Boonie) </h1>
+
+ +

Using Django templates protects you against the majority of XSS attacks. However it is possible to turn off this protection, and the protection isn't automatically applied to all tags that wouldn't normally be populated by user input (for example, the help_text in a form field is usually not user-supplied, so Django doesn't escape those values).

+ +

It is also possible for XSS attacks to originate from other untrusted source of data, such as cookies, Web services or uploaded files (whenever the data is not sufficiently sanitized before including in a page). If you're displaying data from these sources, then you may need to add your own sanitisation code.

+ +

Cross site request forgery (CSRF) protection

+ +

CSRF attacks allow a malicious user to execute actions using the credentials of another user without that user’s knowledge or consent. For example consider the case where we have a hacker who wants to create additional authors for our LocalLibrary.

+ +
+

Note: Obviously our hacker isn't in this for the money! A more ambitious hacker could use the same approach on other sites to perform much more harmful tasks (e.g. transfer money to their own accounts, etc.)

+
+ +

In order to do this, they might create an HTML file like the one below, which contains an author-creation form (like the one we used in the previous section) that is submitted as soon as the file is loaded. They would then send the file to all the Librarians and suggest that they open the file (it contains some harmless information, honest!). If the file is opened by any logged in librarian, then the form would be submitted with their credentials and a new author would be created.

+ +
<html>
+<body onload='document.EvilForm.submit()'>
+
+<form action="http://127.0.0.1:8000/catalog/author/create/" method="post" name='EvilForm'>
+  <table>
+    <tr><th><label for="id_first_name">First name:</label></th><td><input id="id_first_name" maxlength="100" name="first_name" type="text" value="Mad" required /></td></tr>
+    <tr><th><label for="id_last_name">Last name:</label></th><td><input id="id_last_name" maxlength="100" name="last_name" type="text" value="Man" required /></td></tr>
+    <tr><th><label for="id_date_of_birth">Date of birth:</label></th><td><input id="id_date_of_birth" name="date_of_birth" type="text" /></td></tr>
+    <tr><th><label for="id_date_of_death">Died:</label></th><td><input id="id_date_of_death" name="date_of_death" type="text" value="12/10/2016" /></td></tr>
+  </table>
+  <input type="submit" value="Submit" />
+</form>
+
+</body>
+</html>
+
+ +

Run the development web server, and log in with your superuser account. Copy the text above into a file and then open it in the browser. You should get a CSRF error, because Django has protection against this kind of thing!

+ +

The way the protection is enabled is that you include the {% csrf_token %} template tag in your form definition. This token is then rendered in your HTML as shown below, with a value that is specific to the user on the current browser.

+ +
<input type='hidden' name='csrfmiddlewaretoken' value='0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW' />
+
+ +

Django generates a user/browser specific key and will reject forms that do not contain the field, or that contain an incorrect field value for the user/browser.

+ +

To use this type of attack the hacker now has to discover and include the CSRF key for the specific target user. They also can't use the "scattergun" approach of sending a malicious file to all librarians and hoping that one of them will open it, since the CSRF key is browser specific.

+ +

Django's CSRF protection is turned on by default. You should always use the {% csrf_token %} template tag in your forms and use POST for requests that might change or add data to the database.

+ +

Other protections

+ +

Django also provides other forms of protection (most of which would be hard or not particularly useful to demonstrate):

+ +
+
SQL injection protection
+
SQL injection vulnerabilities enable malicious users to execute arbitrary SQL code on a database, allowing data to be accessed, modified, or deleted irrespective of the user's permissions. In almost every case you'll be accessing the database using Django’s querysets/models, so the resulting SQL will be properly escaped by the underlying database driver. If you do need to write raw queries or custom SQL then you'll need to explicitly think about preventing SQL injection.
+
Clickjacking protection
+
In this attack a malicious user hijacks clicks meant for a visible top level site and routes them to a hidden page beneath. This technique might be used, for example, to display a legitimate bank site but capture the login credentials in an invisible <iframe> controlled by the attacker. Django contains clickjacking protection in the form of the X-Frame-Options middleware which, in a supporting browser, can prevent a site from being rendered inside a frame.
+
Enforcing SSL/HTTPS
+
SSL/HTTPS can be enabled on the web server in order to encrypt all traffic between the site and browser, including authentication credentials that would otherwise be sent in plain text (enabling HTTPS is highly recommended). If HTTPS is enabled then Django provides a number of other protections you can use:
+
+ + + +
+
Host header validation
+
Use ALLOWED_HOSTS to only accept requests from trusted hosts.
+
+ +

There are many other protections, and caveats to the usage of the above mechanisms. While we hope that this has given you an overview of what Django offers, you should still read the Django security documentation.

+ + + +

Summary

+ +

Django has effective protections against a number of common threats, including XSS and CSRF attacks. In this article we've demonstrated how those particular threats are handled by Django in our LocalLibrary website. We've also provided a brief overview of some of the other protections.

+ +

This has been a very brief foray into web security. We strongly recommend that you read Security in Django to gain a deeper understanding.

+ +

The next and final step in this module about Django is to complete the assessment task.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/ja/learn/server-side/express_nodejs/deployment/index.html b/files/ja/learn/server-side/express_nodejs/deployment/index.html new file mode 100644 index 0000000000..6f8b60f094 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/deployment/index.html @@ -0,0 +1,525 @@ +--- +title: 'Express チュートリアル Part 7: プロダクションへのデプロイ' +slug: Learn/Server-side/Express_Nodejs/deployment +tags: + - CodingScripting + - Express + - Node + - heroku + - サーバサイド + - デプロイ + - 初心者 + - 学習 +translation_of: Learn/Server-side/Express_Nodejs/deployment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}
+ +

これで素晴らしい地域図書館 Web サイトを作成 (およびテスト) したので、公共の Web サーバーにインストールして、図書館のスタッフとメンバーがインターネット経由でアクセスできるようにします。この記事では Web サイトをデプロイするためのホストを見つける方法、およびサイトを運用に向けて準備するために必要な作業の概要について説明します。

+ + + + + + + + + + + + +
前提条件:Express チュートリアル Part 6: フォームの操作を含む、これまでのチュートリアルのトピックをすべて完了してください。
目標:Express アプリケーションをプロダクションにデプロイする場所と方法を学ぶ。
+ +

Overview

+ +

Once your site is finished (or finished "enough" to start public testing) you're going to need to host it somewhere more public and accessible than your personal development computer.

+ +

Up to now, you've been working in a development environment, using Express/Node as a web server to share your site to the local browser/network, and running your website with (insecure) development settings that expose debugging and other private information. Before you can host a website externally you're first going to have to:

+ + + +

This tutorial provides some guidance on your options for choosing a hosting site, a brief overview of what you need to do in order to get your Express app ready for production, and a worked example of how to install the LocalLibrary website onto the Heroku cloud hosting service.

+ +

Bear in mind that you don't have to use Heroku — there are other hosting services available. We've also provided a separate tutorial to show how to Install LocalLibrary on PWS/Cloud Foundry.

+ +

What is a production environment?

+ +

The production environment is the environment provided by the server computer where you will run your website for external consumption. The environment includes:

+ + + +

The server computer could be located on your premises and connected to the Internet by a fast link, but it is far more common to use a computer that is hosted "in the cloud". What this actually means is that your code is run on some remote computer (or possibly a "virtual" computer) in your hosting company's data center(s). The remote server will usually offer some guaranteed level of computing resources (e.g. CPU, RAM, storage memory, etc.) and Internet connectivity for a certain price.

+ +

This sort of remotely accessible computing/networking hardware is referred to as Infrastructure as a Service (IaaS). Many IaaS vendors provide options to preinstall a particular operating system, onto which you must install the other components of your production environment. Other vendors allow you to select more fully-featured environments, perhaps including a complete Node setup.

+ +
+

Note: Pre-built environments can make setting up your website very easy because they reduce the configuration, but the available options may limit you to an unfamiliar server (or other components) and may be based on an older version of the OS. Often it is better to install components yourself so that you get the ones that you want, and when you need to upgrade parts of the system, you have some idea of where to start!

+
+ +

Other hosting providers support Express as part of a Platform as a Service (PaaS) offering. When using this sort of hosting you don't need to worry about most of your production environment (servers, load balancers, etc.) as the host platform takes care of those for you. That makes deployment quite easy because you just need to concentrate on your web application and not any other server infrastructure.

+ +

Some developers will choose the increased flexibility provided by IaaS over PaaS, while others will appreciate the reduced maintenance overhead and easier scaling of PaaS. When you're getting started, setting up your website on a PaaS system is much easier, so that is what we'll do in this tutorial.

+ +
+

Tip: If you choose a Node/Express-friendly hosting provider they should provide instructions on how to set up an Express website using different configurations of web server, application server, reverse proxy, etc. For example, there are many step-by-step guides for various configurations in the Digital Ocean Node community docs.

+
+ +

Choosing a hosting provider

+ +

There are numerous hosting providers that are known to either actively support or work well with Node (and Express). These vendors provide different types of environments (IaaS, PaaS), and different levels of computing and network resources at different prices.

+ +
+

Tip: There are a lot of hosting solutions, and their services and pricing can change over time. While we introduce a few options below, it is worth performing your own Internet search before selecting a hosting provider.

+
+ +

Some of the things to consider when choosing a host:

+ + + +

The good news when you're starting out is that there are quite a few sites that provide computing environments for "free", albeit with some conditions. For example, Heroku provides a free but resource-limited PaaS environment "forever", while Amazon Web Services, Microsoft Azure, and the open source option PWS/Cloud Foundry provide free credit when you first join.

+ +

Many providers also have a "basic" tier that provides more useful levels of computing power and fewer limitations. Digital Ocean is an example of a popular hosting provider that offers a relatively inexpensive basic computing tier (in the $5 per month lower range at time of writing).

+ +
+

Note: Remember that price is not the only selection criterion. If your website is successful, it may turn out that scalability is the most important consideration.

+
+ +

Getting your website ready to publish

+ +

The main things to think about when publishing your website are web security and performance. At the bare minimum, you will want to remove the stack traces that are included on error pages during development, tidy up your logging, and set the appropriate headers to avoid many common security threats.

+ +

In the following subsections, we outline the most important changes that you should make to your app.

+ +
+

Tip: There are other useful tips in the Express docs — see Production best practices: performance and reliability and Production Best Practices: Security.

+
+ +

Set NODE_ENV to 'production'

+ +

We can remove stack traces in error pages by setting the NODE_ENV environment variable to production (it is set to 'development' by default). In addition to generating less-verbose error messages, setting the variable to production caches view templates and CSS files generated from CSS extensions. Tests indicate that setting NODE_ENV to production can improve app performance by a factor of three!

+ +

This change can be made either by using export or an environment file or using the OS initialization system.  

+ +
+

Note: This is actually a change you make in your environment setup rather than your app, but important enough to note here! We'll show how this is set for our hosting example below. 

+
+ +

Log appropriately

+ +

Logging calls can have an impact on a high-traffic website. In a production environment, you may need to log website activity (e.g. tracking traffic or logging API calls) but you should attempt to minimize the amount of logging added for debugging purposes.

+ +

One way to minimize "debug" logging in production is to use a module like debug that allows you to control what logging is performed by setting an environment variable. For example, the code fragment below shows how you might set up "author" logging. The debug variable is declared with the name 'author', and the prefix "author" will be automatically displayed for all logs from this object.

+ +
var debug = require('debug')('author');
+
+// Display Author update form on GET
+exports.author_update_get = function(req, res, next) {
+
+    req.sanitize('id').escape().trim();
+    Author.findById(req.params.id, function(err, author) {
+        if (err) {
+            debug('update error:' + err);
+            return next(err);
+        }
+        //On success
+        res.render('author_form', { title: 'Update Author', author: author });
+    });
+
+};
+ +

You can then enable a particular set of logs by specifying them as a comma-separated list in the DEBUG environment variable. You can set the variables for displaying author and book logs as shown (wildcards are also supported).

+ +
#Windows
+set DEBUG=author,book
+
+#Linux
+export DEBUG="author,book"
+
+ +
+

Challenge: Calls to debug can replace logging you might previously have done using console.log() or console.error(). Replace any console.log() calls in your code with logging via the debug module. Turn the logging on and off in your development environment by setting the DEBUG variable and observe the impact this has on logging.

+
+ +

If you need to log website activity you can use a logging library like Winston or Bunyan. For more information on this topic see: Production best practices: performance and reliability.

+ +

Use gzip/deflate compression for responses

+ +

Web servers can often compress the HTTP response sent back to a client, significantly reducing the time taken to for the client to get and load the page. The compression method used will depend on what decompression methods the client says that it supports in the request (if no compression methods are supported the response will be sent uncompressed).

+ +

You can add this to your site using compression middleware. Install this to your project by running the following command at the root of the project.

+ +
npm install compression
+ +

Open ./app.js and require the compression library as shown. Add the compression library to the middleware chain with the use() method (this should appear before any routes that you want compressed — in this case, all of them!)

+ +
var catalogRouter = require('./routes/catalog'); //Import routes for "catalog" area of site
+var compression = require('compression');
+
+// Create the Express application object
+var app = express();
+
+...
+
+app.use(compression()); //Compress all routes
+
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.use('/', indexRouter);
+app.use('/users', usersRouter);
+app.use('/catalog', catalogRouter);  // Add catalog routes to middleware chain.
+
+...
+
+ +
+

Note: For a high-traffic website in production you wouldn't use this middleware. Instead, you would use a reverse proxy like Nginx.

+
+ +

Use Helmet to protect against well known vulnerabilities

+ +

Helmet is a middleware package that can help protect your app from some well-known web vulnerabilities by setting appropriate HTTP headers (see the docs for more information on what headers it sets/vulnerabilities it protects against). 

+ +

Install this to your project by running the following command at the root of the project.

+ +
npm install helmet
+
+ +

Open ./app.js and require the helmet library as shown. Then add the module to the middleware chain with the use() method.

+ +
var compression = require('compression');
+var helmet = require('helmet');
+
+// Create the Express application object
+var app = express();
+
+app.use(helmet());
+...
+ +
+

Note: The command above adds the subset of available headers that makes sense for most sites. You can add/disable specific headers as needed by following the instructions on npm.

+
+ +

Example: Installing LocalLibrary on Heroku

+ +

This section provides a practical demonstration of how to install LocalLibrary on the Heroku PaaS cloud.

+ +

Why Heroku?

+ +

Heroku is one of the longest-running and popular cloud-based PaaS services. It originally supported only Ruby apps, but now can be used to host apps from many programming environments, including Node (and hence Express)!

+ +

We are choosing to use Heroku for several reasons:

+ + + +

While Heroku is perfect for hosting this demonstration it may not be perfect for your real website. Heroku makes things easy to set up and scale, at the cost of being less flexible, and potentially a lot more expensive once you get out of the free tier.

+ +

How does Heroku work?

+ +

Heroku runs websites within one or more "Dynos", which are isolated, virtualized Unix containers that provide the environment required to run an application. The dynos are completely isolated and have an ephemeral file system (a short-lived file system that is cleaned/emptied every time the dyno restarts). The only thing that dynos share by default are application configuration variables. Heroku internally uses a load balancer to distribute web traffic to all "web" dynos. Since nothing is shared between them, Heroku can scale an app horizontally by adding more dynos (though of course, you may also need to scale your database to accept additional connections).

+ +

Because the file system is ephemeral you can't install the services required by your application directly (e.g. databases, queues, caching systems, storage, email services, etc). Instead, Heroku web applications use backing services provided as independent "add-ons" by Heroku or 3rd parties. Once attached to your web application, the add-on services are accessed in your web application via environment variables.

+ +

In order to execute your application Heroku needs to be able to set up the appropriate environment and dependencies, and also understand how it is launched. For Node apps, all the information it needs is obtained from your package.json file.

+ +

Developers interact with Heroku using a special client app/terminal, which is much like a Unix bash script. This allows you to upload code that is stored in a git repository, inspect the running processes, see logs, set configuration variables, and much more!

+ +

In order to get our application to work on Heroku, we'll need to put our Express web application into a git repository and make some minor changes to the package.json. Once we've done that we can set up a Heroku account, get the Heroku client, and use it to install our website.

+ +

That's all the overview you need in order to get started (see Getting Started on Heroku with Node.js for a more comprehensive guide).

+ +

Creating an application repository in Github

+ +

Heroku is closely integrated with the git source code version control system, using it to upload/synchronize any changes you make to the live system. It does this by adding a new Heroku "remote" repository named heroku pointing to a repository for your source on the Heroku cloud. During development, you use git to store changes on your "master" repository. When you want to deploy your site, you sync your changes to the Heroku repository.

+ +
+

Note: If you're used to following good software development practices you are probably already using git or some other SCM system. If you already have a git repository, then you can skip this step.

+
+ +

There are a lot of ways of to work with git, but one of the easiest is to first set up an account on GitHub, create the repository there, and then sync to it locally:

+ +
    +
  1. Visit https://github.com/ and create an account.
  2. +
  3. Once you are logged in, click the + link in the top toolbar and select New repository.
  4. +
  5. Fill in all the fields on this form. While these are not compulsory, they are strongly recommended. +
      +
    • Enter a new repository name (e.g. express-locallibrary-tutorial), and description (e.g. "Local Library website written in Express (Node)".
    • +
    • Choose Node in the Add .gitignore selection list.
    • +
    • Choose your preferred license in the Add license selection list.
    • +
    • Check Initialize this repository with a README.
    • +
    +
  6. +
  7. Press Create repository.
  8. +
  9. Click the green "Clone or download" button on your new repo page.
  10. +
  11. Copy the URL value from the text field inside the dialog box that appears (it should be something like: https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git).
  12. +
+ +

Now the repository ("repo") is created we are going to want to clone it on our local computer:

+ +
    +
  1. Install git for your local computer (you can find versions for different platforms here).
  2. +
  3. Open a command prompt/terminal and clone your repository using the URL you copied above: +
    git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git
    +
    + This will create the repository below the current point.
  4. +
  5. Navigate into the new repo. +
    cd express-locallibrary-tutorial
    +
  6. +
+ +

The final step is to copy in your application and then add the files to your repo using git:

+ +
    +
  1. Copy your Express application into this folder (excluding /node_modules, which contains dependency files that you should fetch from NPM as needed).
  2. +
  3. Open a command prompt/terminal and use the add command to add all files to git.
  4. +
  5. +
    git add -A
    +
    +
  6. +
  7. Use the status command to check all files that you are about to add are correct (you want to include source files, not binaries, temporary files etc.). It should look a bit like the listing below. +
    > git status
    +On branch master
    +Your branch is up-to-date with 'origin/master'.
    +Changes to be committed:
    +  (use "git reset HEAD <file>..." to unstage)
    +
    +        new file:   ...
    +
  8. +
  9. When you're satisfied commit the files to your local repository: +
    git commit -m "First version of application moved into github"
    +
  10. +
  11. Then synchronize your local repository to the Github website, using the following: +
    git push origin master
    +
  12. +
+ +

When this operation completes, you should be able to go back to the page on Github where you created your repo, refresh the page, and see that your whole application has now been uploaded. You can continue to update your repository as files change using this add/commit/push cycle.

+ +
+

Tip: This is a good point to make a backup of your "vanilla" project — while some of the changes we're going to be making in the following sections might be useful for deployment on any platform (or development) others might not.

+ +

The best way to do this is to use git to manage your revisions. With git you can not only go back to a particularly old version, but you can maintain this in a separate "branch" from your production changes and cherry-pick any changes to move between production and development branches. Learning Git is well worth the effort, but is beyond the scope of this topic.

+ +

The easiest way to do this is to just copy your files into another location. Use whichever approach best matches your knowledge of git!

+
+ +

Update the app for Heroku

+ +

This section explains the changes you'll need to make to our LocalLibrary application to get it to work on Heroku.

+ +

Set node version 

+ +

The package.json contains everything needed to work out your application dependencies and what file should be launched to start your site. Heroku detects the presence of this file, and will use it to provision your app environment.

+ +

The only useful information missing in our current package.json is the version of node. We can find the version of node we're using for development by entering the command:

+ +
>node --version
+v8.9.1
+ +

Open package.json, and add this information as an engines > node section as shown (using the version number for your system).

+ +
{
+  "name": "express-locallibrary-tutorial",
+  "version": "0.0.0",
+  "engines": {
+    "node": "8.9.1"
+  },
+  "private": true,
+  ...
+
+ +

Database configuration

+ +

So far in this tutorial, we've used a single database that is hard-coded into app.js. Normally we'd like to be able to have a different database for production and development, so next we'll modify the LocalLibrary website to get the database URI from the OS environment (if it has been defined), and otherwise use our development database.

+ +

Open app.js and find the line that sets the MongoDB connection variable. It will look something like this:

+ +
var mongoDB = 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
+ +

Replace the line with the following code that uses process.env.MONGODB_URI to get the connection string from an environment variable named MONGODB_URI if has been set (use your own database URL instead of the placeholder below.)

+ +
var mongoDB = process.env.MONGODB_URI || 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
+
+ +

Get dependencies and re-test

+ +

Before we proceed, let's test the site again and make sure it wasn't affected by any of our changes. 

+ +

First, we will need to fetch our dependencies (you will recall we didn't copy the node_modules folder into our git tree). You can do this by running the following command in your terminal at the root of the project:

+ +
npm install
+
+ +

Now run the site (see Testing the routes for the relevant commands) and check that the site still behaves as you expect.

+ +

Save changes to Github

+ +

Next, let's save all our changes to Github. In the terminal (whilst inside our repository), enter the following commands:

+ +
git add -A
+git commit -m "Added files and changes required for deployment to heroku"
+git push origin master
+ +

We should now be ready to start deploying LocalLibrary on Heroku.

+ +

Get a Heroku account

+ +

To start using Heroku you will first need to create an account (skip ahead to Create and upload the website if you've already got an account and installed the Heroku client):

+ + + +

Install the client

+ +

Download and install the Heroku client by following the instructions on Heroku here.

+ +

After the client is installed you will be able to run commands. For example to get help on the client:

+ +
heroku help
+
+ +

Create and upload the website

+ +

To create the app we run the "create" command in the root directory of our repository. This creates a git remote ("pointer to a remote repository") named heroku in our local git environment.

+ +
heroku create
+ +
+

Note: You can name the remote if you like by specifying a value after "create". If you don't then you'll get a random name. The name is used in the default URL.

+
+ +

We can then push our app to the Heroku repository as shown below. This will upload the app, get all its dependencies, package it in a dyno, and start the site.

+ +
git push heroku master
+ +

If we're lucky, the app is now "running" on the site. To open your browser and run the new website, use the command:

+ +
heroku open
+ +
+

Note: The site will be running using our development database. Create some books and other objects, and check out whether the site is behaving as you expect. In the next section, we'll set it to use our new database.

+
+ +

Setting configuration variables

+ +

You will recall from a preceding section that we need to set NODE_ENV to 'production' in order to improve our performance and generate less-verbose error messages. We do this by entering the following command:

+ +
>heroku config:set NODE_ENV='production'
+Setting NODE_ENV and restarting limitless-tor-18923... done, v13
+NODE_ENV: production
+
+ +

We should also use a separate database for production, setting its URI in the MONGODB_URI  environment variable. You can set up a new database and database-user exactly as we did originally, and get its URI. You can set the URI as shown (obviously, using your own URI!)

+ +
>heroku config:set MONGODB_URI='mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production'
+Setting MONGODB_URI and restarting limitless-tor-18923... done, v13
+MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production
+
+ +

You can inspect your configuration variables at any time using the heroku config command — try this now:

+ +
>heroku config
+=== limitless-tor-18923 Config Vars
+MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production
+NODE_ENV:    production
+
+ +

Heroku will restart your app when it updates the variables. If you check the home page now it should show zero values for your object counts, as the changes above mean that we're now using a new (empty) database.

+ +

Managing addons

+ +

Heroku uses independent add-ons to provide backing services to apps — for example, email or database services. We don't use any addons in this website, but they are an important part of working with Heroku, so you may want to check out the topic Managing Add-ons (Heroku docs).

+ +

Debugging

+ +

The Heroku client provides a few tools for debugging:

+ +
heroku logs  # Show current logs
+heroku logs --tail # Show current logs and keep updating with any new results
+heroku ps   #Display dyno status
+
+ + + +

まとめ

+ +

これで、本番環境での Express アプリケーションの設定に関するこのチュートリアル、および Express を使用した作業に関する一連のチュートリアルは終了です。それらが役に立つことを願っています。完全に完成したバージョンの Github のソースコードをここでチェックすることができます。

+ +

あわせて参照

+ + + +

{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/development_environment/index.html b/files/ja/learn/server-side/express_nodejs/development_environment/index.html new file mode 100644 index 0000000000..7bfa26bb88 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/development_environment/index.html @@ -0,0 +1,410 @@ +--- +title: Node 開発環境の設定 +slug: Learn/Server-side/Express_Nodejs/development_environment +tags: + - CodingScripting + - Express + - Intro + - Learn + - Node + - nodejs + - npm + - server-side + - イントロダクション + - サーバサイド + - 初心者 + - 学習 + - 開発環境 +translation_of: Learn/Server-side/Express_Nodejs/development_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}
+ +

Express の目的が理解できたので、Windows、Linux (Ubuntu)、および macOS 上で Node/Express 開発環境をセットアップしてテストする方法を説明します。どのような一般的な OS を使用していても、この記事では Express アプリケーションの開発を開始するために必要なものを提供します。

+ + + + + + + + + + + + +
前提条件:端末/コマンドラインを開く方法を知っている。開発用コンピューターの OS にソフトウェアパッケージをインストールする方法を知っている。
目標:コンピューター上に Express (X.XX) 用の開発環境をセットアップします。
+ +

Express 開発環境概要

+ +

Node と Express のおかげでウェブアプリケーションの開発を始めるためにコンピューターをセットアップすることが非常に簡単になります。このセクションでは必要なツールの概要、Ubuntu、macOS、および Windows に Node (および Express) をインストールするための最も簡単な方法について説明し、インストールをテストする方法を示します。

+ +

Express 開発環境とは何か?

+ +

Express 開発環境には NodejsNPM パッケージマネージャー、および (オプションで) ローカルコンピューターに Express Application Generator がインストールされています。

+ +

Node と NPM パッケージマネージャーは、準備されたバイナリパッケージ、インストーラー、オペレーティングシステムのパッケージマネージャー、またはソースから一緒にインストールされます (次のセクションを参照)。 Express は、NPM によって、個々の Express ウェブアプリケーションの依存関係として (テンプレートエンジン、データベースドライバー、認証ミドルウェア、静的ファイルを提供するためのミドルウェアなどの他のライブラリと共に) インストールされます。

+ +

NPMMVC パターンに従ったスケルトンの Express ウェブアプリケーションを作成するための便利なツールである Express Application Generatorを (グローバルに) インストールするためにも使用できます。Express を使用するアプリを作成したり、同じアーキテクチャ上のレイアウトや依存関係を持つ Express アプリを構築したりするためにこのツールを使用する必要はないため、アプリケーションジェネレーターはオプションです。ただし、使い始めるのがはるかに簡単になり、モジュール式のアプリケーション構造が促進されるため、これを使用します。

+ +
+

メモ: 他のウェブフレームワークとは異なり、開発環境には独立した開発用の ウェブサーバーは含まれていません。Node/Express では、ウェブアプリケーションが独自のウェブサーバーを作成して実行します。

+
+ +

テキストエディタやコード編集用の IDE、コードの異なるバージョンを安全に管理するための Git などのソース管理マネジメントツールなど、一般的な開発環境の一部である他の周辺ツールもあります。これらの種類のツール (特にテキストエディタ) が既にインストールされていると仮定しています。

+ +

どのオペレーティングシステムがサポートされていますか?

+ +

Node は Windows、macOS、Linux の多くの「フレーバー」、Docker などで実行できます (nodejs のダウンロードページに完全なリストがあります)。ほとんどのパーソナルコンピューターは開発中に Node を実行するのに必要な性能を持っているはずです。ExpressNode 環境で実行されるため、Node を実行する任意のプラットフォームで実行できます。

+ +

この記事では Windows、macOS、および Ubuntu Linux のセットアップ手順を説明します。

+ +

どのバージョンの Node/Express を使用すべきですか?

+ +

たくさんの Node のリリースがあります - 新しいリリースにはバグ修正、ECMAScript (JavaScript) 標準のより最新のバージョンのサポート、そして Node API の改良が含まれています。

+ +

一般的には最新の LTS (長期サポート) リリースを使用するべきです。比較的最新の機能を持ちながら (そして現在も積極的にメンテナンスされています)、"最新の" リリースより安定しているからです。LTS バージョンに存在しない機能が必要な場合は、最新版リリースを使用してください。

+ +

Express は常に最新のバージョンを使うべきです。

+ +

データベースやその他の依存関係についてはどうですか?

+ +

データベースドライバー、テンプレートエンジン、認証エンジンなどのその他の依存関係はアプリケーションの一部であり、NPM パッケージマネージャーを使用してアプリケーション環境にインポートされます。それらについては、後のアプリ固有の記事で説明します。

+ +

Node のインストール

+ +

Express を使用するには、まず Nodejs Node Package Manager (NPM) をオペレーティングシステムにインストールする必要があります。以下のセクションでは Ubuntu Linux 18.04、macOS、および Windows 10 に Long Term Supported (LTS) バージョンの Nodejs をインストールする最も簡単な方法について説明します。

+ +
+

Tip: 以下のセクションは、ターゲット OS プラットフォームに Node NPM をインストールする最も簡単な方法を示しています。他の OS を使用している場合、または現在のプラットフォームで他の方法を使用したい場合は、パッケージマネージャーによる Node.js のインストール (nodejs.org) を参照してください。

+
+ +

macOS および Windows

+ +

Windows と macOS への Node NPM のインストールは、提供されているインストーラーを使用することができるため、簡単です。

+ +
    +
  1. 必要なインストーラーをダウンロードします +
      +
    1. https://nodejs.org/ja/ に進みます
    2. +
    3. "ほとんどのユーザーに推奨" である LTS ビルドをダウンロードするためのボタンを選択してください。
    4. +
    +
  2. +
  3. ダウンロードしたファイルをダブルクリックし、インストールの指示に従って Node をインストールします。
  4. +
+ +

Ubuntu 18.04

+ +

Node 10.x の最新の LTS バージョンをインストールする最も簡単な方法は、パッケージマネージャーを使ってそれを Ubuntu バイナリ配布リポジトリーから入手することです。これはあなたの端末で以下の2つのコマンドを実行することによって非常に簡単に行うことができます。

+ +
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
+sudo apt-get install -y nodejs
+
+ +
+

警告: それらは非常に古いバージョンの Node を含んでいるので、通常の Ubuntu リポジトリーから直接インストールしないでください。

+
+ +
    +
+ +

Nodejs および NPM インストールのテスト

+ +

Node がインストールされていることをテストする最も簡単な方法は、ターミナル/コマンドプロンプトで "version" コマンドを実行し、バージョン文字列が返されることを確認することです。

+ +
>node -v
+v10.16.0
+ +

Nodejs パッケージマネージャー NPM もインストールされているはずで、同じ方法でテストできます。

+ +
>npm -v
+6.9.0
+ +

もう少し刺激的なテストとして、ブラウザーで正しい URL にアクセスしたときにブラウザーに「Hello World」を単純に出力する、非常に基本的な "純粋な Node" サーバーを作成しましょう。

+ +
    +
  1. 次のテキストを hellonode.js というファイルにコピーします。これは純粋な Node 関数 (Express からは何もしていません) といくつかの ES6 構文を使用します。 + +
    //HTTP モジュールを読み込む
    +const http = require("http");
    +const hostname = '127.0.0.1';
    +const port = 3000;
    +
    +//HTTP サーバーを作成し、3000 番ポートでリクエストを待機します。
    +const server = http.createServer((req, res) => {
    +
    +  //HTTP ステータスとコンテンツタイプを持つ応答 HTTP ヘッダーを設定します。
    +  res.statusCode = 200;
    +  res.setHeader('Content-Type', 'text/plain');
    +  res.end('Hello World\n');
    +});
    +
    +//3000 番ポートでリクエストを待機し、受信したときにログ出力するコールバック関数
    +server.listen(port, hostname, () => {
    +  console.log(`Server running at http://${hostname}:${port}/`);
    +});
    +
    +
    + +

    このコードは "http" モジュールをインポートし、それを使用して 3000 番ポートで HTTP リクエストを待機するサーバーを作成 (createServer()) します。次に、スクリプトはサーバーをテストするために使用できるブラウザー URL についてのメッセージをコンソールに出力します。 createServer() 関数は、HTTP リクエストを受信したときに呼び出されるコールバック関数を引数として取ります。これは HTTP ステータスコード 200 ("OK") とプレーンテキスト "Hello World" のレスポンスを返します。

    + +
    +

    メモ:  このコードが何をしているのか正確に理解できなくても心配しないでください。Express を使い始めたら、コードについて詳しく説明します。

    +
    +
  2. +
  3. コマンドプロンプトで hellonode.js ファイルと同じディレクトリに移動し、次のようにスクリプト名とともに node を呼び出してサーバーを起動します。 +
    >node hellonode.js
    +Server running at http://127.0.0.1:3000/
    +
    +
  4. +
  5. http://127.0.0.1:3000 の URL に移動します。すべてがうまくいったら、ブラウザーは単に文字列 "Hello World" を表示するはずです。
  6. +
+ +

NPM の使用

+ +

Node 自体の次に、NPM は Node アプリケーションを操作するための最も重要なツールです。NPM は、アプリケーションが開発、テスト、および/または運用に必要なパッケージ(JavaScript ライブラリ) を取得するために使用されます。また、開発プロセスで使用されるテストやツールを実行するために使用されることもあります。

+ +
+

メモ: Node の観点からすると、Express は NPM を使用してインストールしてから独自のコードで必要とするもう1つのパッケージです。

+
+ +

手動で NPM を使用して、必要な各パッケージを別々に取り出すことができます。通常、代わりに package.json というプレーンテキストの定義ファイルを使用して依存関係を管理します。このファイルにはパッケージの名前、バージョン、説明、実行する初期ファイル、プロダクション依存関係、開発依存関係、それが動作可能な Node のバージョンなど、特定のJavaScript "package" に対するすべての依存関係が一覧表示されます。package.json ファイルには、NPM がアプリケーションを取得して実行するために必要なものがすべて含まれている必要があります (再利用可能なライブラリを作成している場合は、この定義を使用してパッケージを npm リポジトリーにアップロードし、他のユーザが利用できるようにします)。

+ +

依存関係の追加

+ +

次の手順では NPM を使用してパッケージをダウンロードし、それをプロジェクトの依存関係に保存してから、それを Node アプリケーションで要求する方法を示します。

+ +
+

メモ: ここでは Express パッケージを取得してインストールするための手順を示します。後で、このパッケージなどが Express Application Generator を使用してすでにどのように指定されているかを示します。このセクションは NPM がどのように機能するのか、および Application Generator によって何が作成されているのかを理解するのに役立ちます。

+
+ +
    +
  1. +

    まず、新しいアプリケーション用のディレクトリーを作成し、そこに移動します。

    + +
    mkdir myapp
    +cd myapp
    +
  2. +
  3. +

    アプリケーション用の package.json ファイルを作成するには、npm init コマンドを使用します。このコマンドはアプリケーションの名前とバージョン、初期エントリポイントファイルの名前 (デフォルトでは index.js) など、さまざまなことを要求します。今のところ、デフォルトをそのまま使用します。

    + +
    npm init
    + +

    package.json ファイル (cat package.json) を表示すると、受け入れたデフォルトが表示され、最後にライセンスが表示されます。

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC"
    +}
    +
    +
  4. +
  5. +

    myapp ディレクトリーに Express をインストールし、それをあなたの package.json ファイルの依存関係リストに保存してください。

    + +
      npm install express --save
    +
    +
  6. +
  7. +

    package.json の依存関係セクションが package.json ファイルの最後に表示され、Express が含まれます。

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC",
    +  "dependencies": {
    +    "express": "^4.16.3"
    +  }
    +}
    +
    +
  8. +
  9. このライブラリを使用するには、index.js ファイルで以下に示すように require() 関数を呼び出します。"myapp" アプリケーションディレクトリーのルートにファイルを作り、以下の内容を記述します。 +
    const express = require('express')
    +const app = express();
    +
    +app.get('/', (req, res) => {
    +  res.send('Hello World!')
    +});
    +
    +app.listen(8000, () => {
    +  console.log('Example app listening on port 8000!')
    +});
    +
    + +

    このコードは、最小限の「HelloWorld」Express ウェブアプリケーションを示しています。これは「express」モジュールをインポートし、それを使用して 8000 番ポートで HTTP リクエストを待機するサーバ ー(app) を作成し、サーバーをテストするために使用できるブラウザー URL を説明するメッセージをコンソールに出力します。 app.get() 関数は、指定された URLパス ('/') で HTTP GET リクエストにのみ応答します。この場合、関数を呼び出して Hello World! メッセージを送信します。

    +
  10. +
  11. コマンドプロンプトでスクリプトを使用して node を呼び出すことでサーバーを起動できます。 +
    >node index.js
    +Example app listening on port 8000
    +
    +
  12. +
  13. URL (http://127.0.0.1:8000/) に移動します。すべてがうまくいったら、ブラウザーは単に文字列 "Hello World!" を表示するはずです。
  14. +
+ +

開発の依存関係

+ +

依存関係が開発中にのみ使用される場合は、代わりに "開発依存関係" として保存する必要があります (パッケージユーザーが本番環境にインストールする必要がないようにするため)。たとえば、一般的な JavaScript Linting ツールの eslint を使用するには、次のように NPM を呼び出します。

+ +
npm install eslint --save-dev
+ +

次のエントリがアプリケーションの package.json に追加されます。

+ +
  "devDependencies": {
+    "eslint": "^4.12.1"
+  }
+
+ +
+

メモ: "Lint" は一連のコーディングのベストプラクティスに準拠しているかどうかを認識して報告するために、ソフトウェアで静的分析を実行するツールです。

+
+ +

タスクの実行

+ +

依存関係の定義と取得に加えて、package.json ファイルに名前付きスクリプトを定義し、NPM を呼び出してそれらを run-script コマンドで実行することもできます。このアプローチは、実行中のテストや開発の一部を自動化したり、ツールチェーン (たとえば JavaScript の縮小、画像の縮小、コードの LINT/分析などのツールの実行) を構築したりするためによく使用されます。

+ +
+

メモ: GulpGrunt のようなタスクランナーもテストや他の外部ツールを実行するために使うことができます。

+
+ +

たとえば、前のセクションで指定した eslint 開発依存関係を実行するためのスクリプトを定義するには、次のスクリプトブロックを package.json ファイルに追加します (アプリケーションソースが /src/js フォルダにあると仮定します)。

+ +
"scripts": {
+  ...
+  "lint": "eslint src/js"
+  ...
+}
+
+ +

もう少し詳しく説明すると、eslint src/js は、app ディレクトリー内の src/js ディレクトリーに含まれる JavaScript ファイルに対して eslint を実行するために terminal/command 行に入力できるコマンドです。アプリの package.json ファイル内に上記を含めると、このコマンドのショートカット - つまり lint が提供されます。

+ +

こうすれば、NPM を使って eslint を実行することができます。

+ +
npm run-script lint
+# OR (using the alias)
+npm run lint
+
+ +

この例は元のコマンドより短く見えないかもしれませんが、複数のコマンドのチェーンを含めて、npm スクリプト内にもっと大きなコマンドを含めることができます。一度にすべてのテストを実行する単一の npm スクリプトを指定できます。

+ +

Express Application Generator のインストール

+ +

Express Application Generator ツールは Express アプリケーションの「スケルトン」を生成します。次に示すように、NPM を使用してジェネレーターをインストールします (-g フラグを指定すると、ツールをグローバルにインストールして、どこからでも呼び出すことができます)。

+ +
npm install express-generator -g
+ +

デフォルト設定で "helloworld" という名前の Express アプリを作成するには、作成する場所に移動して、図のようにアプリを実行します。

+ +
express helloworld
+ +
+

注記: 利用するテンプレートライブラリ等の他の設定を指定することもできます。すべてのオプションを見るには、help コマンドを使用してください。

+ +
express --help
+
+
+ +

NPM は現在の場所のサブフォルダーに新しい Express アプリケーションを作成し、コンソールにビルドの進行状況を表示します。完了すると、Node の依存関係をインストールしてアプリを起動するために入力する必要があるコマンドがツールに表示されます。

+ +
+

新しいアプリには、そのルートディレクトリーに package.json ファイルがあります。これを開くと、Express やテンプレートライブラリ Jade など、インストールされている依存関係を確認できます。

+ +
{
+  "name": "helloworld",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www"
+  },
+  "dependencies": {
+    "body-parser": "~1.18.2",
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.15.5",
+    "jade": "~1.11.0",
+    "morgan": "~1.9.0",
+    "serve-favicon": "~2.4.5"
+  }
+}
+ + +
+ +

次に示すように、NPM を使用して helloworld アプリのすべての依存関係をインストールします。

+ +
cd helloworld
+npm install
+
+ +

次に、以下のようにアプリを実行します (コマンドは Windows と Linux/macOS で若干異なります)。

+ +
#  Windows のコマンドプロンプトで helloworld を実行
+SET DEBUG=helloworld:* & npm start
+
+# Windows の PowerShell で helloworld を実行
+SET DEBUG=helloworld:* | npm start
+
+# Linux/macOS で helloworld を実行
+DEBUG=helloworld:* npm start
+
+ +

DEBUG コマンドは有用なロギングを作成し、その結果、以下に示すような出力が得られます。

+ +
>SET DEBUG=helloworld:* & npm start
+
+> helloworld@0.0.0 start D:\Github\expresstests\helloworld
+> node ./bin/www
+
+  helloworld:server Listening on port 3000 +0ms
+ +

ブラウザーを開いて http://127.0.0.1:3000/ に移動し、デフォルトの Express ウェルカムページを表示します。

+ +

Express - Generated App Default Screen

+ +

スケルトンアプリケーションの生成に関する記事にアクセスしたら、生成されたアプリケーションについて詳しく説明します。

+ + + +

まとめ

+ +

これで、Express ウェブアプリケーションを作成するために使用できる Node 開発環境がコンピューター上で稼働しています。また、NPM を使用して Express をアプリケーションにインポートする方法、および Express Application Generator ツールを使用してアプリケーションを作成して実行する方法についても説明しました。

+ +

次の記事では、この環境と関連ツールを使って完全なウェブアプリケーションを構築するためのチュートリアルを始めます。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュールの中

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html new file mode 100644 index 0000000000..5c4acc7193 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/author_detail_page/index.html @@ -0,0 +1,89 @@ +--- +title: 著者詳細ページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Author_detail_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Author_detail_page +--- +

著者詳細ページには、指定された Author に関する情報を、その (自動的に生成された) _id フィールド値を使用して識別し、その Author に関連するすべての Book オブジェクトのリストを表示する必要があります。

+ +

Controller

+ +

Open /controllers/authorController.js.

+ +

Add the following lines to the top of the file to import the async and Book modules (these are needed for our author detail page).

+ +
var async = require('async');
+var Book = require('../models/book');
+ +

Find the exported author_detail() controller method and replace it with the following code.

+ +
// Display detail page for a specific Author.
+exports.author_detail = function(req, res, next) {
+
+    async.parallel({
+        author: function(callback) {
+            Author.findById(req.params.id)
+              .exec(callback)
+        },
+        authors_books: function(callback) {
+          Book.find({ 'author': req.params.id },'title summary')
+          .exec(callback)
+        },
+    }, function(err, results) {
+        if (err) { return next(err); } // Error in API usage.
+        if (results.author==null) { // No results.
+            var err = new Error('Author not found');
+            err.status = 404;
+            return next(err);
+        }
+        // Successful, so render.
+        res.render('author_detail', { title: 'Author Detail', author: results.author, author_books: results.authors_books } );
+    });
+
+};
+
+ +

The method uses async.parallel() to query the Author and their associated Book instances in parallel, with the callback rendering the page when (if) both requests complete successfully. The approach is exactly the same as described for the Genre detail page above.

+ +

View

+ +

Create /views/author_detail.pug and copy in the following text.

+ +
extends layout
+
+block content
+
+  h1 Author: #{author.name}
+  p #{author.date_of_birth} - #{author.date_of_death}
+
+  div(style='margin-left:20px;margin-top:20px')
+
+    h4 Books
+
+    dl
+      each book in author_books
+        dt
+          a(href=book.url) #{book.title}
+        dd #{book.summary}
+
+      else
+        p This author has no books.
+
+ +

Everything in this template has been demonstrated in previous sections.

+ +

What does it look like?

+ +

Run the application and open your browser to http://localhost:3000/. Select the All Authors link, then select one of the authors. If everything is set up correctly, your site should look something like the following screenshot.

+ +

Author Detail Page - Express Local Library site

+ +
+

Note: The appearance of the author lifespan dates is ugly! We'll address that in the final challenge in this article.

+
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html new file mode 100644 index 0000000000..f738902bfb --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/author_list_page/index.html @@ -0,0 +1,85 @@ +--- +title: 著者リストページとジャンルリストページのチャレンジ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Author_list_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Author_list_page +--- +

The author list page needs to display a list of all authors in the database, with each author name linked to its associated author detail page. The date of birth and date of death should be listed after the name on the same line.

+ +

Controller

+ +

The author list controller function needs to get a list of all Author instances, and then pass these to the template for rendering.

+ +

Open /controllers/authorController.js. Find the exported author_list() controller method near the top of the file and replace it with the following code (the changed code is shown in bold).

+ +
// Display list of all Authors.
+exports.author_list = function(req, res, next) {
+
+  Author.find()
+    .sort([['family_name', 'ascending']])
+    .exec(function (err, list_authors) {
+      if (err) { return next(err); }
+      //Successful, so render
+      res.render('author_list', { title: 'Author List', author_list: list_authors });
+    });
+
+};
+ +

The method uses the model's find(), sort() and exec() functions to return all Author objects sorted by family_name in alphabetic order. The callback passed to the exec() method is called with any errors (or null) as the first parameter, or a list of all authors on success. If there is an error it calls the next middleware function with the error value, and if not it renders the author_list(.pug) template, passing the page title and the list of authors (author_list).

+ +

View

+ +

Create /views/author_list.pug and replace its content with the text below.

+ +
extends layout
+
+block content
+  h1= title
+
+  ul
+    each author in author_list
+      li
+        a(href=author.url) #{author.name}
+        |  (#{author.date_of_birth} - #{author.date_of_death})
+
+    else
+      li There are no authors.
+ +

The view follows exactly the same pattern as our other templates.

+ +

What does it look like?

+ +

Run the application and open your browser to http://localhost:3000/. Then select the All authors link. If everything is set up correctly, the page should look something like the following screenshot.

+ +

Author List Page - Express Local Library site

+ +
+

Note: The appearance of the author lifespan dates is ugly! You can improve this using the same approach as we used for the BookInstance list (adding the virtual property for the lifespan to the Author model). This time, however, there are missing dates, and references to nonexistent properties are ignored unless strict mode is in effect. moment() returns the current time, and you don't want missing dates to be formatted as if they were today. One way to deal with this is to define the body of the function that returns a formatted date so it returns a blank string unless the date actually exists. For example:

+ +

return this.date_of_birth ? moment(this.date_of_birth).format('YYYY-MM-DD') : '';

+
+ +

Genre list page—challenge!Edit

+ +

In this section you should implement your own genre list page. The page should display a list of all genres in the database, with each genre linked to its associated detail page. A screenshot of the expected result is shown below.

+ +

Genre List - Express Local Library site

+ +

The genre list controller function needs to get a list of all Genre instances, and then pass these to the template for rendering.

+ +
    +
  1. You will need to edit genre_list() in /controllers/genreController.js
  2. +
  3. The implementation is almost exactly the same as the author_list() controller. +
      +
    • Sort the results by name, in ascending order.
    • +
    +
  4. +
  5. The template to be rendered should be named genre_list.pug.
  6. +
  7. The template to be rendered should be passed the variables title ('Genre List') and genre_list (the list of genres returned from your Genre.find() callback.
  8. +
  9. The view should match the screenshot/requirements above (this should have a very similar structure/format to the Author list view, except for the fact that genres do not have dates).
  10. +
+ +

Next steps

+ +

Return to Express Tutorial Part 5: Displaying library data.

+ +

Proceed to the next subarticle of part 5: Genre detail page.

diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html new file mode 100644 index 0000000000..f2080e6109 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/book_detail_page/index.html @@ -0,0 +1,112 @@ +--- +title: 本の詳細ページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Book_detail_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Book_detail_page +--- +

The Book detail page needs to display the information for a specific Book, identified using its (automatically generated) _id field value, along with information about each associated copy in the libary (BookInstance). Wherever we display an author, genre, or book instance, these should be linked to the associated detail page for that item.

+ +

Controller

+ +

Open /controllers/bookController.js. Find the exported book_detail() controller method and replace it with the following code.

+ +
// Display detail page for a specific book.
+exports.book_detail = function(req, res, next) {
+
+    async.parallel({
+        book: function(callback) {
+
+            Book.findById(req.params.id)
+              .populate('author')
+              .populate('genre')
+              .exec(callback);
+        },
+        book_instance: function(callback) {
+
+          BookInstance.find({ 'book': req.params.id })
+          .exec(callback);
+        },
+    }, function(err, results) {
+        if (err) { return next(err); }
+        if (results.book==null) { // No results.
+            var err = new Error('Book not found');
+            err.status = 404;
+            return next(err);
+        }
+        // Successful, so render.
+        res.render('book_detail', { title: 'Title', book: results.book, book_instances: results.book_instance } );
+    });
+
+};
+
+
+ +
+

Note: We don't need to require async and BookInstance, as we already imported those modules when we implemented the home page controller.

+
+ +

The method uses async.parallel() to find the Book and its associated copies (BookInstances) in parallel. The approach is exactly the same as described for the Genre detail page above.

+ +

View

+ +

Create /views/book_detail.pug and add the text below.

+ +
extends layout
+
+block content
+  h1 #{title}: #{book.title}
+
+  p #[strong Author:]
+    a(href=book.author.url) #{book.author.name}
+  p #[strong Summary:] #{book.summary}
+  p #[strong ISBN:] #{book.isbn}
+  p #[strong Genre:]&nbsp;
+    each val, index in book.genre
+      a(href=val.url) #{val.name}
+      if index < book.genre.length - 1
+        |,
+
+  div(style='margin-left:20px;margin-top:20px')
+    h4 Copies
+
+    each val in book_instances
+      hr
+      if val.status=='Available'
+        p.text-success #{val.status}
+      else if val.status=='Maintenance'
+        p.text-danger #{val.status}
+      else
+        p.text-warning #{val.status}
+      p #[strong Imprint:] #{val.imprint}
+      if val.status!='Available'
+        p #[strong Due back:] #{val.due_back}
+      p #[strong Id:]&nbsp;
+        a(href=val.url) #{val._id}
+
+    else
+      p There are no copies of this book in the library.
+
+ +

Almost everything in this template has been demonstrated in previous sections.

+ +
+

Note: The list of genres associated with the book is implemented in the template as below. This adds a comma after every genre associated with the book except for the last one.

+ +
  p #[strong Genre:]
+    each val, index in book.genre
+      a(href=val.url) #{val.name}
+      if index < book.genre.length - 1
+        |, 
+
+ +

What does it look like?

+ +

Run the application and open your browser to http://localhost:3000/. Select the All books link, then select one of the books. If everything is set up correctly, your page should look something like the following screenshot.

+ +

Book Detail Page - Express Local Library site

+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html new file mode 100644 index 0000000000..4dfc9c5a5e --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/book_list_page/index.html @@ -0,0 +1,68 @@ +--- +title: ブックリストページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Book_list_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Book_list_page +--- +

Next we'll implement our book list page. This page needs to display a list of all books in the database along with their author, with each book title being a hyperlink to its associated book detail page.

+ +

Controller

+ +

The book list controller function needs to get a list of all Book objects in the database, and then pass these to the template for rendering.

+ +

Open /controllers/bookController.js. Find the exported book_list() controller method and replace it with the following code.

+ +
// Display list of all Books.
+exports.book_list = function(req, res, next) {
+
+  Book.find({}, 'title author')
+    .populate('author')
+    .exec(function (err, list_books) {
+      if (err) { return next(err); }
+      //Successful, so render
+      res.render('book_list', { title: 'Book List', book_list: list_books });
+    });
+
+};
+ +

The method uses the model's find() function to return all Book objects, selecting to return only the title and author as we don't need the other fields (it will also return the _id and virtual fields). Here we also call populate() on Book, specifying the author field—this will replace the stored book author id with the full author details.

+ +

On success, the callback passed to the query renders the book_list(.pug) template, passing the title and book_list (list of books with authors) as variables.

+ +

View

+ +

Create /views/book_list.pug and copy in the text below.

+ +
extends layout
+
+block content
+  h1= title
+
+  ul
+    each book in book_list
+      li
+        a(href=book.url) #{book.title}
+        |  (#{book.author.name})
+
+    else
+      li There are no books.
+ +

The view extends the layout.pug base template and overrides the block named 'content'. It displays the title we passed in from the controller (via the render() method) and then iterates through the book_list variable using the each-in-else syntax. A list item is created for each book displaying the book title as a link to the book's detail page followed by the author name. If there are no books in the book_list then the else clause is executed, and displays the text 'There are no books.'

+ +
+

Note: We use book.url to provide the link to the detail record for each book (we've implemented this route, but not the page yet). This is a virtual property of the Book model which uses the model instance's _id field to produce a unique URL path.

+
+ +

Of interest here is that each book is defined as two lines, using the pipe for the second line (highlighted above). This approach is needed because if the author name were on the previous line then it would be part of the hyperlink.

+ +

What does it look like?

+ +

Run the application (see Testing the routes for the relevant commands) and open your browser to http://localhost:3000/. Then select the All books link. If everything is set up correctly, your site should look something like the following screenshot.

+ +

Book List Page - Express Local Library site

+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html new file mode 100644 index 0000000000..3c6cace6a5 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_detail_page_and_challenge/index.html @@ -0,0 +1,91 @@ +--- +title: ブックインスタンス詳細ページとチャレンジ +slug: >- + Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_detail_page_and_challenge +translation_of: >- + Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_detail_page_and_challenge +--- +

BookInstance detail page

+ +

The BookInstance detail page needs to display the information for each BookInstance, identified using its (automatically generated) _id field value. This will include the Book name (as a link to the Book detail page) along with other information in the record.

+ +

Controller

+ +

Open /controllers/bookinstanceController.js. Find the exported bookinstance_detail() controller method and replace it with the following code.

+ +
// Display detail page for a specific BookInstance.
+exports.bookinstance_detail = function(req, res, next) {
+
+    BookInstance.findById(req.params.id)
+    .populate('book')
+    .exec(function (err, bookinstance) {
+      if (err) { return next(err); }
+      if (bookinstance==null) { // No results.
+          var err = new Error('Book copy not found');
+          err.status = 404;
+          return next(err);
+        }
+      // Successful, so render.
+      res.render('bookinstance_detail', { title: 'Book:', bookinstance:  bookinstance});
+    })
+
+};
+
+ +

The method calls BookInstance.findById() with the ID of a specific book instance extracted from the URL (using the route), and accessed within the controller via the request parameters: req.params.id). It then calls populate() to get the details of the associated Book.

+ +

View

+ +

Create /views/bookinstance_detail.pug and copy in the content below.

+ +
extends layout
+
+block content
+
+  h1 ID: #{bookinstance._id}
+
+  p #[strong Title:]
+    a(href=bookinstance.book.url) #{bookinstance.book.title}
+  p #[strong Imprint:] #{bookinstance.imprint}
+
+  p #[strong Status:]
+    if bookinstance.status=='Available'
+      span.text-success #{bookinstance.status}
+    else if bookinstance.status=='Maintenance'
+      span.text-danger #{bookinstance.status}
+    else
+      span.text-warning #{bookinstance.status}
+
+  if bookinstance.status!='Available'
+    p #[strong Due back:] #{bookinstance.due_back}
+
+ +

Everything in this template has been demonstrated in previous sections.

+ +

What does it look like?

+ +

Run the application and open your browser to http://localhost:3000/. Select the All book-instances link, then select one of the items. If everything is set up correctly, your site should look something like the following screenshot.

+ +

BookInstance Detail Page - Express Local Library site

+ +

Challenge

+ +

Currently most dates displayed on the site use the default JavaScript format (e.g. Tue Dec 06 2016 15:49:58 GMT+1100 (AUS Eastern Daylight Time). The challenge for this article is to improve the appearance of the date display for Author lifespan information (date of death/birth) and for BookInstance detail pages to use the format: December 6th, 2016.

+ +
+

Note: You can use the same approach as we used for the Book Instance List (adding the virtual property for the lifespan to the Author model and use moment to format the date strings).

+
+ +

The requirements to meet this challenge:

+ +
    +
  1. Replace the variable due_back with due_back_formatted in the BookInstance detail page.
  2. +
  3. Update the Author module to add a lifespan virtual property. The lifespan should look like: date_of_birth - date_of_death, where both values have the same date format as BookInstance.due_back_formatted.
  4. +
  5. Use Author.lifespan in all views where you currently explicitly use date_of_birth and date_of_death.
  6. +
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html new file mode 100644 index 0000000000..9bc7ee305f --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/bookinstance_list_page/index.html @@ -0,0 +1,69 @@ +--- +title: ブックインスタンスリストページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_list_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_list_page +--- +

Next we'll implement our list of all book copies (BookInstance) in the library. This page needs to include the title of the Book associated with each BookInstance (linked to its detail page) along with other information in the BookInstance model, including the status, imprint, and unique id of each copy. The unique id text should be linked to the BookInstance detail page.

+ +

Controller

+ +

The BookInstance list controller function needs to get a list of all book instances, populate the associated book information, and then pass the list to the template for rendering.

+ +

Open /controllers/bookinstanceController.js. Find the exported bookinstance_list() controller method and replace it with the following code (the changed code is shown in bold).

+ +
// Display list of all BookInstances.
+exports.bookinstance_list = function(req, res, next) {
+
+  BookInstance.find()
+    .populate('book')
+    .exec(function (err, list_bookinstances) {
+      if (err) { return next(err); }
+      // Successful, so render
+      res.render('bookinstance_list', { title: 'Book Instance List', bookinstance_list: list_bookinstances });
+    });
+
+};
+ +

The method uses the model's find() function to return all BookInstance objects. It then daisy-chains a call to populate() with the book field—this will replace the book id stored for each BookInstance with a full Book document.

+ +

On success, the callback passed to the query renders the bookinstance_list(.pug) template, passing the title and bookinstance_list as variables.

+ +

View

+ +

Create /views/bookinstance_list.pug and copy in the text below.

+ +
extends layout
+
+block content
+  h1= title
+
+  ul
+    each val in bookinstance_list
+      li
+        a(href=val.url) #{val.book.title} : #{val.imprint} -
+        if val.status=='Available'
+          span.text-success #{val.status}
+        else if val.status=='Maintenance'
+          span.text-danger #{val.status}
+        else
+          span.text-warning #{val.status}
+        if val.status!='Available'
+          span  (Due: #{val.due_back} )
+
+    else
+      li There are no book copies in this library.
+ +

This view is much the same as all the others. It extends the layout, replacing the content block, displays the title passed in from the controller, and iterates through all the book copies in bookinstance_list. For each copy we display its status (colour coded) and if the book is not available, its expected return date. One new feature is introduced—we can use dot notation after a tag to assign a class. So span.text-success will be compiled to <span class="text-success"> (and might also be written in Pug as span(class="text-success").

+ +

What does it look like?

+ +

Run the application, open your browser to http://localhost:3000/, then select the All book-instances link. If everything is set up correctly, your site should look something like the following screenshot.

+ +

BookInstance List Page - Express Local Library site

+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html new file mode 100644 index 0000000000..58851991b5 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/date_formatting_using_moment/index.html @@ -0,0 +1,60 @@ +--- +title: moment を使用した日付のフォーマット +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Date_formatting_using_moment +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Date_formatting_using_moment +--- +

The default rendering of dates from our models is very ugly: Tue Dec 06 2016 15:49:58 GMT+1100 (AUS Eastern Daylight Time). In this section we'll show how you can update the BookInstance List page from the previous section to present the due_date field in a more friendly format: December 6th, 2016. 

+ +

The approach we will use is to create a virtual property in our BookInstance model that returns the formatted date. We'll do the actual formatting using moment, a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.

+ +
+

Note: It is possible to use moment to format the strings directly in our Pug templates, or we could format the string in a number of other places. Using a virtual property allows us to get the formatted date in exactly the same way as we get the due_date currently. 

+
+ +

Install moment

+ +

Enter the following command in the root of the project:

+ +
npm install moment
+ +

Create the virtual property

+ +
    +
  1. Open ./models/bookinstance.js.
  2. +
  3. At the top of the page, import moment. +
    var moment = require('moment');
    +
  4. +
+ +

Add the virtual property due_back_formatted just after the url property.

+ +
BookInstanceSchema
+.virtual('due_back_formatted')
+.get(function () {
+  return moment(this.due_back).format('MMMM Do, YYYY');
+});
+ +
+

Note: The format method can display a date using almost any pattern. The syntax for representing different date components can be found in the moment documentation.

+
+ +

Update the view

+ +

Open /views/bookinstance_list.pug and replace due_back with due_back_formatted.

+ +
      if val.status!='Available'
+        //span  (Due: #{val.due_back} )
+        span  (Due: #{val.due_back_formatted} )       
+ +

That's it. If you go to All book-instances in the sidebar, you should now see all the due dates are far more attractive!

+ +

 

+ +

Next steps

+ + + +

 

diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html new file mode 100644 index 0000000000..0639f79bc3 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html @@ -0,0 +1,137 @@ +--- +title: async を使用した非同期フロー制御 +slug: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +--- +

 

+ +

ローカルライブラリのいくつかのコントローラは、特定の順序、あるいは平行して要求される複数の非同期リクエストに依存しています。一般的に、操作の流れを制御し、必要となるすべての情報を取得したときにページを表示するために、asyncモジュール が使用されます。

+ +
+

註: この方法以外にも、近年 JavaScript に導入された Promise などの非同期的な振る舞いや操作の流れを制御する方法があります。

+
+ +

Async はいくつもの有用なメソッドを持っています (このドキュメントを参照してください)。 主要なメソッドをいくつか紹介します。:

+ + + +

Why is this needed?

+ +

Most of the methods we use in Express are asynchronous—you specify an operation to perform, passing a callback. The method returns immediately, and the callback is invoked when the requested operation completes. By convention in Express, callback functions pass an error value as the first parameter (or null on success) and the results from the function (if there are any) as the second parameter.

+ +

If a controller only needs to perform one asynchronous operation to get the information required to render a page then the implementation is easy—we simply render the template in the callback. The code fragment below shows this for a function that renders the count of a model SomeModel (using the Mongoose count() method):

+ +
exports.some_model_count = function(req, res, next) {
+
+  SomeModel.count({ a_model_field: 'match_value' }, function (err, count) {
+    // ... do something if there is an err
+
+    // On success, render the result by passing count into the render function (here, as the variable 'data').
+    res.render('the_template', { data: count } );
+  });
+}
+
+ +

However what if you need to make multiple asynchronous queries, and you can't render the page until all the operations have completed? A naive implementation could "daisy chain" the requests, kicking off subsequent requests in the callback of a previous request, and rendering the response in the final callback. The problem with this approach is that our requests would have to be run in series, even though it might be more efficient to run them in parallel. This could also result in complicated nested code, commonly referred to as callback hell.

+ +

A much better solution would be to execute all the requests in parallel and then have a single callback that executes when all of the queries have completed. This is the sort of flow operation that the Async module makes easy!

+ +

Asynchronous operations in parallel

+ +

The method async.parallel() is used to run multiple asynchronous operations in parallel.

+ +

The first argument to async.parallel() is a collection of the asynchronous functions to run (an array, object or other iterable). Each function is passed a callback(err, result) which it must call on completion with an error err (which can be null) and an optional results value.

+ +

The optional second argument to  async.parallel() is a callback that will be run when all the functions in the first argument have completed. The callback is invoked with an error argument and a result collection that contains the results of the individual asynchronous operations. The result collection is of the same type as the first argument (i.e. if you pass an array of asynchronous functions, the final callback will be invoked with an array of results). If any of the parallel functions reports an error the callback is invoked early (with the error value).

+ +

The example below shows how this works when we pass an object as the first argument. As you can see, the results are returned in an object with the same property names as the original functions that were passed in.

+ +
async.parallel({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback
+  function(err, results) {
+    // 'results' is now equal to: {one: 1, two: 2, ..., something_else: some_value}
+  }
+);
+ +

If you instead pass an array of functions as the first argument, the results will be an array (the array order results will match the original order that the functions were declared—not the order in which they completed).

+ +

Asynchronous operations in series

+ +

The method async.series() is used to run multiple asynchronous operations in sequence, when subsequent functions do not depend on the output of earlier functions. It is essentially declared and behaves in the same way as async.parallel().

+ +
async.series({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback after the last asynchronous function completes.
+  function(err, results) {
+    // 'results' is now equals to: {one: 1, two: 2, ..., something_else: some_value} 
+  }
+);
+ +
+

Note: The ECMAScript (JavaScript) language specification states that the order of enumeration of an object is undefined, so it is possible that the functions will not be called in the same order as you specify them on all platforms. If the order really is important, then you should pass an array instead of an object, as shown below.

+
+ +
async.series([
+  function(callback) {
+    // do some stuff ...
+    callback(null, 'one');
+  },
+  function(callback) {
+    // do some more stuff ... 
+    callback(null, 'two');
+  }
+ ],
+  // optional callback
+  function(err, results) {
+  // results is now equal to ['one', 'two'] 
+  }
+);
+ +

Dependent asynchronous operations in series

+ +

The method async.waterfall() is used to run multiple asynchronous operations in sequence when each operation is dependent on the result of the previous operation.

+ +

The callback invoked by each asynchronous function contains null for the first argument and results in subsequent arguments. Each function in the series takes the results arguments of the previous callback as the first parameters, and then a callback function. When all operations are complete, a final callback is invoked with the result of the last operation. The way this works is more clear when you consider the code fragment below (this example is from the async documentation):

+ +
async.waterfall([
+  function(callback) {
+    callback(null, 'one', 'two');
+  },
+  function(arg1, arg2, callback) {
+    // arg1 now equals 'one' and arg2 now equals 'two' 
+    callback(null, 'three');
+  },
+  function(arg1, callback) {
+    // arg1 now equals 'three'
+    callback(null, 'done');
+  }
+], function (err, result) {
+  // result now equals 'done'
+}
+);
+ +

Installing async

+ +

Install the async module using the NPM package manager so that we can use it in our code. You do this in the usual way, by opening a prompt in the root of the LocalLibrary project and enter the following command:

+ +
npm install async
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html new file mode 100644 index 0000000000..40770c5ef2 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/genre_detail_page/index.html @@ -0,0 +1,121 @@ +--- +title: ジャンル詳細ページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Genre_detail_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Genre_detail_page +--- +

The genre detail page needs to display the information for the particular genre instance using its automatically generated _id field value as the identifier. The page should display the genre name, and a list of all books in the genre with links to each book's details page.

+ +

Controller

+ +

Open /controllers/genreController.js and import the async and Book modules at the top of the file.

+ +
var Book = require('../models/book');
+var async = require('async');
+
+ +

Find the exported genre_detail() controller method and replace it with the following code.

+ +
// Display detail page for a specific Genre.
+exports.genre_detail = function(req, res, next) {
+
+    async.parallel({
+        genre: function(callback) {
+            Genre.findById(req.params.id)
+              .exec(callback);
+        },
+
+        genre_books: function(callback) {
+          Book.find({ 'genre': req.params.id })
+          .exec(callback);
+        },
+
+    }, function(err, results) {
+        if (err) { return next(err); }
+        if (results.genre==null) { // No results.
+            var err = new Error('Genre not found');
+            err.status = 404;
+            return next(err);
+        }
+        // Successful, so render
+        res.render('genre_detail', { title: 'Genre Detail', genre: results.genre, genre_books: results.genre_books } );
+    });
+
+};
+
+ +

The method uses async.parallel() to query the genre name and its associated books in parallel, with the callback rendering the page when (if) both requests complete successfully.

+ +

The ID of the required genre record is encoded at the end of the URL and extracted automatically based on the route definition (/genre/:id). The ID is accessed within the controller via the request parameters: req.params.id. It is used in Genre.findById() to get the current genre. It is also used to get all Book objects that have the genre ID in their genre field: Book.find({ 'genre': req.params.id }).

+ +
+

Note: If the genre does not exist in the database (i.e. it may have been deleted) then findById()  will return successfully with no results. In this case we want to display a "not found" page, so we create an Error object and pass it to the next middleware function in the chain. 

+ +
if (results.genre==null) { // No results.
+    var err = new Error('Genre not found');
+    err.status = 404;
+    return next(err);
+}
+
+ +

The message will then propagate through to our error handling code (this was set up when we generated the app skeleton - for more information see Handling Errors).

+
+ +

The rendered view is genre_detail and it is passed variables for the title, genre and the list of books in this genre (genre_books).

+ +

View

+ +

Create /views/genre_detail.pug and fill it with the text below:

+ +
extends layout
+
+block content
+
+  h1 Genre: #{genre.name}
+
+  div(style='margin-left:20px;margin-top:20px')
+
+    h4 Books
+
+    dl
+    each book in genre_books
+      dt
+        a(href=book.url) #{book.title}
+      dd #{book.summary}
+
+    else
+      p This genre has no books
+
+ +

The view is very similar to all our other templates. The main difference is that we don't use the title passed in for the first heading (though it is used in the underlying layout.pug template to set the page title).

+ +

What does it look like?

+ +

Run the application and open your browser to http://localhost:3000/. Select the All genres link, then select one of the genres (e.g. "Fantasy"). If everything is set up correctly, your page should look something like the following screenshot.

+ +

Genre Detail Page - Express Local Library site

+ +
+

You might get an error similar to this:

+ +
Cast to ObjectId failed for value " 59347139895ea23f9430ecbb" at path "_id" for model "Genre"
+
+ +

This is a mongoose error coming from the req.params.id. To solve this problem, first you need to require mongoose on the genreController.js page like this:

+ +
 var mongoose = require('mongoose');
+
+ +

Then use mongoose.Types.ObjectId() to convert the id to a that can be used. For example:

+ +
exports.genre_detail = function(req, res, next) {
+    var id = mongoose.Types.ObjectId(req.params.id);
+    ...
+
+
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/home_page/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/home_page/index.html new file mode 100644 index 0000000000..3e2f337370 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/home_page/index.html @@ -0,0 +1,133 @@ +--- +title: ホームページ +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Home_page +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Home_page +--- +

The first page we'll create will be the website home page, which is accessible from either the site ('/') or catalog (catalog/) root. This will display some static text describing the site, along with dynamically calculated "counts" of different record types in the database.

+ +

We've already created a route for the home page. In order to complete the page we need to update our controller function to fetch "counts" of records from the database, and create a view (template) that we can use to render the page.

+ +

Route

+ +

We created our index page routes in a previous tutorial. As a reminder, all the route functions are defined in /routes/catalog.js:

+ +
// GET catalog home page.
+router.get('/', book_controller.index);  //This actually maps to /catalog/ because we import the route with a /catalog prefix
+ +

Where the callback function parameter (book_controller.index) is defined in /controllers/bookController.js:

+ +
exports.index = function(req, res, next) {
+    res.send('NOT IMPLEMENTED: Site Home Page');
+}
+ +

It is this controller function that we extend to get information from our models and then render it using a template (view).

+ +

Controller

+ +

The index controller function needs to fetch information about how many Book, BookInstance, available BookInstance, Author, and Genre records we have in the database, render this data in a template to create an HTML page, and then return it in an HTTP response.

+ +
+

Note: We use the countDocuments() method to get the number of instances of each model. This is called on a model with an optional set of conditions to match against in the first argument and a callback in the second argument (as discussed in Using a Database (with Mongoose), and you can also return a Query and then execute it with a callback later. The callback will be returned when the database returns the count, with an error value (or null) as the first parameter and the count of records (or null if there was an error) as the second parameter.

+ +
SomeModel.countDocuments({ a_model_field: 'match_value' }, function (err, count) {
+ // ... do something if there is an err
+ // ... do something with the count if there was no error
+ });
+
+ +

Open /controllers/bookController.js. Near the top of the file you should see the exported index() function.

+ +
var Book = require('../models/book')
+
+exports.index = function(req, res, next) {
+ res.send('NOT IMPLEMENTED: Site Home Page');
+}
+ +

Replace all the code above with the following code fragment. The first thing this does is import (require()) all the models (highlighted in bold). We need to do this because we'll be using them to get our counts of records. It then imports the async module.

+ +
var Book = require('../models/book');
+var Author = require('../models/author');
+var Genre = require('../models/genre');
+var BookInstance = require('../models/bookinstance');
+
+var async = require('async');
+
+exports.index = function(req, res) {
+
+    async.parallel({
+        book_count: function(callback) {
+            Book.countDocuments({}, callback); // Pass an empty object as match condition to find all documents of this collection
+        },
+        book_instance_count: function(callback) {
+            BookInstance.countDocuments({}, callback);
+        },
+        book_instance_available_count: function(callback) {
+            BookInstance.countDocuments({status:'Available'}, callback);
+        },
+        author_count: function(callback) {
+            Author.countDocuments({}, callback);
+        },
+        genre_count: function(callback) {
+            Genre.countDocuments({}, callback);
+        }
+    }, function(err, results) {
+        res.render('index', { title: 'Local Library Home', error: err, data: results });
+    });
+};
+ +

The async.parallel() method is passed an object with functions for getting the counts for each of our models. These functions are all started at the same time. When all of them have completed the final callback is invoked with the counts in the results parameter (or an error).

+ +

On success the callback function calls res.render(), specifying a view (template) named 'index' and an object containing the data that is to be inserted into it (this includes the results object that contains our model counts). The data is supplied as key-value pairs, and can be accessed in the template using the key.

+ +
+

Note: The callback function from async.parallel() above is a little unusual in that we render the page whether or not there was an error (normally you might use a separate execution path for handling the display of errors).

+
+ +

View

+ +

Open /views/index.pug and replace its content with the text below.

+ +
extends layout
+
+block content
+  h1= title
+  p Welcome to #[em LocalLibrary], a very basic Express website developed as a tutorial example on the Mozilla Developer Network.
+
+  h1 Dynamic content
+
+  if error
+    p Error getting dynamic content.
+  else
+    p The library has the following record counts:
+
+    ul
+      li #[strong Books:] !{data.book_count}
+      li #[strong Copies:] !{data.book_instance_count}
+      li #[strong Copies available:] !{data.book_instance_available_count}
+      li #[strong Authors:] !{data.author_count}
+      li #[strong Genres:] !{data.genre_count}
+ +

The view is straightforward. We extend the layout.pug base template, overriding the block named 'content'. The first h1 heading will be the escaped text for the title variable that was passed into the render() function—note the use of the 'h1=' so that the following text is treated as a JavaScript expression. We then include a paragraph introducing the LocalLibrary.

+ +

Under the Dynamic content heading we check whether the error variable passed in from the render() function has been defined. If so, we note the error. If not, we get and list the number of copies of each model from the data variable.

+ +
+

Note: We didn't escape the count values (i.e. we used the !{} syntax) because the count values are calculated. If the information was supplied by end-users then we'd escape the variable for display.

+
+ +

What does it look like?

+ +

At this point we should have created everything needed to display the index page. Run the application and open your browser to http://localhost:3000/. If everything is set up correctly, your site should look something like the following screenshot.

+ +

Home page - Express Local Library site

+ +
+

Note: You won't be able to use the sidebar links yet because the urls, views, and templates for those pages haven't been defined. If you try you'll get errors like "NOT IMPLEMENTED: Book list" for example, depending on the link you click on.  These string literals (which will be replaced with proper data) were specified in the different controllers that live inside your "controllers" file.

+
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/index.html new file mode 100644 index 0000000000..5726b6c0e1 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/index.html @@ -0,0 +1,92 @@ +--- +title: 'Express チュートリアル Part 5: ライブラリデータの表示' +slug: Learn/Server-side/Express_Nodejs/Displaying_data +tags: + - Express + - nodejs + - pug + - コントローラ + - テンプレート + - ビュー + - 初心者 + - 学習 +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}
+ +

これで地域図書館の Web サイトの書籍やその他のデータを表示するページを追加する準備が整いました。このページには、各モデルタイプのレコード数と、すべてのモデルのリストおよび詳細ページを示すホームページが含まれます。その過程で、データベースからレコードを取得したり、テンプレートを使用したりする際の実際的な経験を積むことになります。

+ + + + + + + + + + + + +
前提条件:以前のチュートリアルのトピック (Express チュートリアル Part 4: ルートとコントローラを含む) を完了してください。
目標:async モジュールと Pug テンプレート言語の使い方、そしてコントローラ関数の URL からデータを取得する方法を理解すること。
+ +

概要

+ +

前回のチュートリアル記事では、データベースとやり取りするために使用できる Mongoose モデルを定義し、いくつかの初期ライブラリレコードを作成しました。その後、LocalLibrary Web サイトに必要なすべてのルートを作成しましたが、"ダミーコントローラ" 関数 (ページにアクセスすると "未実装" のメッセージを返すだけのスケルトンコントローラ関数) を使用しました。

+ +

次のステップは、私たちの図書館情報を表示するページに適切な実装をすることです (後の記事で情報を作成、更新、または削除するフォームを特徴とする実装ページを見ます)。これには、モデルを使用してレコードを取得するためのコントローラ機能の更新、およびこの情報をユーザに表示するためのテンプレートの定義が含まれます。

+ +

はじめに、コントローラ関数で非同期操作を管理する方法と Pug を使用してテンプレートを作成する方法を説明する概要/入門トピックを提供します。それから、主要な "読み取り専用" ページのそれぞれに、それらが使用する特別な機能や新しい機能についての簡単な説明を付けて実装を提供します。

+ +

この記事が終わるときには、ルート、非同期関数、ビュー、およびモデルが実際にどのように機能するのかについてのエンドツーエンドの理解が十分にあるはずです。

+ +

ライブラリデータチュートリアルサブ記事の表示

+ +

次のサブ記事では、必要な Web サイトページを表示するために必要なさまざまな機能を追加するプロセスについて説明します。次のものに進む前に、順番にこれらのそれぞれを読み、作業する必要があります。

+ +
    +
  1. async を使用した非同期フロー制御
  2. +
  3. テンプレートプライマー
  4. +
  5. LocalLibrary 基本テンプレート
  6. +
  7. ホームページ
  8. +
  9. ブックリストページ
  10. +
  11. ブックインスタンスリストページ
  12. +
  13. moment を使用した日付のフォーマット
  14. +
  15. 著者リストページとジャンルリストページのチャレンジ
  16. +
  17. ジャンル詳細ページ
  18. +
  19. 本の詳細ページ
  20. +
  21. 著者詳細ページ
  22. +
  23. ブックインスタンス詳細ページとチャレンジ
  24. +
+ +

まとめ

+ +

これで、サイトのすべての "読み取り専用" ページを作成しました。各モデルのインスタンスの数を表示するホームページ、および書籍、書籍のインスタンス、作家、ジャンルのリストと詳細ページです。その過程でコントローラ、非同期操作を使用したときのフロー制御の管理、Pug を使用したビューの作成、モデルを使用したデータベースの照会、ビューからテンプレートへの情報の受け渡し方法などについて多くの基礎知識を得て、そしてテンプレートを作成および拡張しました。チャレンジを完了した人たちはまた、moment を使った日付処理について少し学んだことでしょう。

+ +

次回の記事では、サイトに格納されているデータの変更を開始するための HTML フォームとフォーム処理コードを作成して、私たちの知識に基づいて構築します。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html new file mode 100644 index 0000000000..a97c536eb2 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/locallibrary_base_template/index.html @@ -0,0 +1,69 @@ +--- +title: LocalLibrary 基本テンプレート +slug: Learn/Server-side/Express_Nodejs/Displaying_data/LocalLibrary_base_template +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/LocalLibrary_base_template +--- +

Now that we understand how to extend templates using Pug, let's start by creating a base template for the project. This will have a sidebar with links for the pages we hope to create across the tutorial articles (e.g. to display and create books, genres, authors, etc.) and a main content area that we'll override in each of our individual pages.

+ +

Open /views/layout.pug and replace the content with the code below.

+ +
doctype html
+html(lang='en')
+  head
+    title= title
+    meta(charset='utf-8')
+    meta(name='viewport', content='width=device-width, initial-scale=1')
+    link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css')
+    script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js')
+    script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
+    link(rel='stylesheet', href='/stylesheets/style.css')
+  body
+    div(class='container-fluid')
+      div(class='row')
+        div(class='col-sm-2')
+          block sidebar
+            ul(class='sidebar-nav')
+              li
+                a(href='/catalog') Home
+              li
+                a(href='/catalog/books') All books
+              li
+                a(href='/catalog/authors') All authors
+              li
+                a(href='/catalog/genres') All genres
+              li
+                a(href='/catalog/bookinstances') All book-instances
+              li
+                hr
+              li
+                a(href='/catalog/author/create') Create new author
+              li
+                a(href='/catalog/genre/create') Create new genre
+              li
+                a(href='/catalog/book/create') Create new book
+              li
+                a(href='/catalog/bookinstance/create') Create new book instance (copy)
+
+        div(class='col-sm-10')
+          block content
+ +

The template uses (and includes) JavaScript and CSS from Bootstrap to improve the layout and presentation of the HTML page. Using Bootstrap or another client-side web framework is a quick way to create an attractive page that can scale well on different browser sizes, and it also allows us to deal with the page presentation without having to get into any of the details—we just want to focus on the server-side code here!

+ +

The layout should be fairly obvious if you've read our above Template primer. Note the use of block content as a placeholder for where the content for our individual pages will be placed.

+ +

The base template also references a local css file (style.css) that provides a little additional styling. Open /public/stylesheets/style.css and replace its content with the following CSS code:

+ +
.sidebar-nav {
+    margin-top: 20px;
+    padding: 0;
+    list-style: none;
+}
+ +

When we get round to running our site, we should see the sidebar appear! In the next sections we will use the above layout to define the individual pages.

+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/displaying_data/template_primer/index.html b/files/ja/learn/server-side/express_nodejs/displaying_data/template_primer/index.html new file mode 100644 index 0000000000..a68921a6a7 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/displaying_data/template_primer/index.html @@ -0,0 +1,149 @@ +--- +title: テンプレートプライマー +slug: Learn/Server-side/Express_Nodejs/Displaying_data/Template_primer +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/Template_primer +--- +

A template is a text file defining the structure or layout of an output file, with placeholders used to represent where data will be inserted when the template is rendered (in Express, templates are referred to as views).

+ +

Express template choices

+ +

Express can be used with many different template rendering engines. In this tutorial we use Pug (formerly known as Jade) for our templates. This is the most popular Node template language, and describes itself as a "clean, whitespace-sensitive syntax for writing HTML, heavily influenced by Haml".

+ +

Different template languages use different approaches for defining the layout and marking placeholders for data—some use HTML to define the layout while others use different markup formats that can be compiled to HTML. Pug is of the second type; it uses a representation of HTML where the first word in any line usually represents an HTML element, and indentation on subsequent lines is used to represent any content nested within those elements. The result is a page definition that translates directly to HTML, but is arguably more concise and easier to read.

+ +
+

Note: The downside of using Pug is that it is sensitive to indentation and whitespace (if you add an extra space in the wrong place you may get an unhelpful error code). However once you have your templates in place, they are very easy to read and maintain.

+
+ +

Template configuration

+ +

The LocalLibrary was configured to use Pug when we created the skeleton website. You should see the pug module included as a dependency in the website's package.json file, and the following configuration settings in the app.js file. The settings tell us that we're using pug as the view engine, and that Express should search for templates in the /views subdirectory.

+ +
// View engine setup.
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'pug');
+ +

If you look in the views directory you will see the .pug files for the project's default views. These include the view for the home page (index.pug) and base template (layout.pug) that we will need to replace with our own content.

+ +
/express-locallibrary-tutorial  //the project root
+  /views
+    error.pug
+    index.pug
+    layout.pug
+
+ +

Template syntax

+ +

The example template file below shows off many of Pug's most useful features.

+ +

The first thing to notice is that the file maps the structure of a typical HTML file, with the first word in (almost) every line being an HTML element, and indentation being used to indicate nested elements. So for example, the body element is inside an html element, and paragraph elements (p) are within the body element, etc. Non-nested elements (e.g. individual paragraphs) are on separate lines.

+ +
doctype html
+html(lang="en")
+  head
+    title= title
+    script(type='text/javascript').
+  body
+    h1= title
+
+    p This is a line with #[em some emphasis] and #[strong strong text] markup.
+    p This line has un-escaped data: !{'<em> is emphasised</em>'} and escaped data: #{'<em> is not emphasised</em>'}.
+      | This line follows on.
+    p= 'Evaluated and <em>escaped expression</em>:' + title
+
+    <!-- You can add HTML comments directly -->
+    // You can add single line JavaScript comments and they are generated to HTML comments
+    //- Introducing a single line JavaScript comment with "//-" ensures the comment isn't rendered to HTML
+
+    p A line with a link
+      a(href='/catalog/authors') Some link text
+      |  and some extra text.
+
+    #container.col
+      if title
+        p A variable named "title" exists.
+      else
+        p A variable named "title" does not exist.
+      p.
+        Pug is a terse and simple template language with a
+        strong focus on performance and powerful features.
+
+    h2 Generate a list
+
+    ul
+      each val in [1, 2, 3, 4, 5]
+        li= val
+ +

Element attributes are defined in parentheses after their associated element. Inside the parentheses, the attributes are defined in comma- or whitespace- separated lists of the pairs of attribute names and attribute values, for example:

+ + + +

The values of all attributes are escaped (e.g. characters like ">" are converted to their HTML code equivalents like "&gt;") to prevent injection of JavaScript/cross-site scripting attacks.

+ +

If a tag is followed by the equals sign, the following text is treated as a JavaScript expression. So for example, in the first line below, the content of the h1 tag will be variable title (either defined in the file or passed into the template from Express). In the second line the paragraph content is a text string concatented with the title variable. In both cases the default behaviour is to escape the line.

+ +
h1= title
+p= 'Evaluated and <em>escaped expression</em>:' + title
+ +

If there is no equals symbol after the tag then the content is treated as plain text. Within the plain text you can insert escaped and unescaped data using the #{} and !{} syntax, as shown below. You can also add raw HTML within the plain text.

+ +
p This is a line with #[em some emphasis] and #[strong strong text] markup.
+p This line has an un-escaped string: !{'<em> is emphasised</em>'}, an escaped string: #{'<em> is not emphasised</em>'}, and escaped variables: #{title}.
+ +
+

Tip: You will almost always want to escape data from users (via the #{} syntax). Data that can be trusted (e.g. generated counts of records, etc.) may be displayed without escaping the values.

+
+ +

You can use the pipe ('|') character at the beginning of a line to indicate "plain text". For example, the additional text shown below will be displayed on the same line as the preceding anchor, but will not be linked.

+ +
a(href='http://someurl/') Link text
+| Plain text
+ +

Pug allows you to perform conditional operations using if, else , else if and unless—for example:

+ +
if title
+  p A variable named "title" exists
+else
+  p A variable named "title" does not exist
+ +

You can also perform loop/iteration operations using each-in or while syntax. In the code fragment below we've looped through an array to display a list of variables (note the use of the 'li=' to evaluate the "val" as a variable below. The value you iterate across can also be passed into the template as a variable!

+ +
ul
+  each val in [1, 2, 3, 4, 5]
+    li= val
+ +

The syntax also supports comments (that can be rendered in the output—or not—as you choose), mixins to create reusable blocks of code, case statements, and many other features. For more detailed information see The Pug docs.

+ +

Extending templates

+ +

Across a site, it is usual for all pages to have a common structure, including standard HTML markup for the head, footer, navigation, etc. Rather than forcing developers to duplicate this "boilerplate" in every page, Pug allows you to declare a base template and then extend it, replacing just the bits that are different for each specific page.

+ +

For example, the base template layout.pug created in our skeleton project looks like this:

+ +
doctype html
+html
+  head
+    title= title
+    link(rel='stylesheet', href='/stylesheets/style.css')
+  body
+    block content
+ +

The block tag is used to mark up sections of content that may be replaced in a derived template (if the block is not redefined then its implementation in the base class is used).

+ +

The default index.pug (created for our skeleton project) shows how we override the base template. The extends tag identifies the base template to use, and then we use block section_name to indicate the new content of the section that we will override.

+ +
extends layout
+
+block content
+  h1= title
+  p Welcome to #{title}
+ +

Next steps

+ + diff --git a/files/ja/learn/server-side/express_nodejs/forms/index.html b/files/ja/learn/server-side/express_nodejs/forms/index.html new file mode 100644 index 0000000000..ea3d378895 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/forms/index.html @@ -0,0 +1,263 @@ +--- +title: 'Express チュートリアル Part 6: フォームの操作' +slug: Learn/Server-side/Express_Nodejs/forms +translation_of: Learn/Server-side/Express_Nodejs/forms +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs/deployment", "Learn/Server-side/Express_Nodejs")}}
+ +

このチュートリアルでは、Pug を使用して Express で HTML フォームを操作する方法、特にデータベースからドキュメントを作成、更新、削除するためのフォームを作成する方法を説明します。

+ + + + + + + + + + + + +
前提条件:Express チュートリアル Part 5: ライブラリデータの表示など、これまでのチュートリアルのトピックをすべて完了してください。
目標:ユーザからデータを取得するためのフォームの作成方法を理解し、このデータでデータベースを更新する。
+ +

概要

+ +

HTMLフォームとは、サーバーに送信するためにユーザーから情報を収集するために使用できる Web ページ上の 1 つ以上のフィールド/ウィジェットのグループのことです。テキストボックス、チェックボックス、ラジオボタン、日付選択など、さまざまなタイプのデータを入力するのに適したフォーム入力が用意されているので、フォームを使えばユーザーからの入力を柔軟に収集することが出来ます。また、フォームはサーバとデータを共有するための比較的安全な方法でもあり、クロスサイトリクエストフォージェリ保護機能を使ってPOSTリクエストでデータを送信することができます。

+ +

フォームを扱うのは複雑です。開発者はフォーム用の HTML を書き、サーバー上で入力されたデータを検証して特殊文字を置換し、無効なフィールドをユーザーに知らせるためにエラーメッセージを表示してフォームを再度表示し、送信が成功したときにデータを処理し、最後に成功を示す何らかの方法でユーザーに応答しなければなりません。

+ +

このチュートリアルでは、上記の操作をExpressで実行する方法を紹介します。途中で、サンプルとして地域図書館のウェブサイトを拡張して、ユーザーがライブラリからアイテムを作成、編集、削除できるようにします。

+ +
+

Note: サンプルとして準備されている地域図書館のウェブサイトは認証済みユーザのみに閲覧を制限する方法については書いてないので、現時点ではどのユーザでもデータベースに変更を加えることができます。

+
+ +

HTMLフォーム

+ +

最初にHTMLフォームの簡単な概要を説明します。ある「チーム」の名前とそれに関連するラベルを入力するための単一のテキストフィールドを持つシンプルな HTML フォームを考えてみましょう。

+ +

Simple name field example in HTML form

+ +

フォームは HTML で <form>...</form> タグ内の要素の集合として定義され、type="submit" input要素を少なくとも 1 つ含みます。

+ +
<form action="/team_name_url/" method="post">
+    <label for="team_name">名前を入力してください: </label>
+    <input id="team_name" type="text" name="name_field" value="デフォルトのチーム名.">
+    <input type="submit" value="OK">
+</form>
+ +

ここではチーム名を入力するための1つのテキストフィールドだけを含んでいますが、フォームは他の入力要素とそれに関連したラベルをいくつでも含むことができます。フィールドのtype属性はどのような種類のウィジェットが表示されるかを定義します。フィールドのnameidはJavaScript/CSS/HTMLでフィールドを識別するために使われ、valueはフィールドが最初に表示されるときの初期値を定義します。マッチングするチームのラベルは、labelタグ(上記の「名前を入力してください」を参照)を使用して指定され、forフィールドには関連するinputタグのid値が含まれます。

+ +

submit inputタグは標準ではボタンとして表示されます。このボタンは、他のinput要素に含まれるデータをサーバーにアップロードするためにユーザーが押すことができます(この例だとteam_nameだけ)。フォーム属性はデータを送信するために使用されるHTTP methodとサーバー上のデータの送信先(action)を定義します。

+ + + +

フォーム処理工程

+ +

フォームの処理はモデルに関する情報を表示するために学んだのと同じテクニックをすべて使います: ルートはリクエストをコントローラ関数に送り、モデルからのデータの読み込みを含む必要なデータベースアクションを実行し、HTMLページを生成して返します。さらに複雑なのは、サーバーがユーザーによって提供されたデータを処理し、何か問題があればエラー情報とともにフォームを再表示する必要があるということです。

+ +

フォームを含むページのリクエスト(緑色で示されている)から始まる、フォームリクエストを処理するためのプロセスフローチャートを以下に示す。

+ +

上の図のように、フォーム処理のコードが必要とする主なものは以下の通りです。

+ +
    +
  1. ユーザーが最初に要求したときにデフォルトのフォームを表示します。 +
      +
    • フォームには空白のフィールドが含まれていたり (新しいレコードを作成している場合など)、初期値があらかじめ入力されていたり (レコードを変更している場合や、デフォルトの初期値がある場合など) します。
    • +
    +
  2. +
  3. ユーザーから送信されたデータを、通常はHTTP POSTリクエストで受信します。
  4. +
  5. データを検証し、ハッキング防止のために特殊文字を置換(サニタイズ)します。
  6. +
  7. データが無効な場合は、ユーザーが入力した値と問題のあるフィールドのエラーメッセージをフォームに再表示します。
  8. +
  9. すべてのデータが有効な場合、必要なアクションを実行します(例:データベースにデータを保存する、通知メールを送信する、検索結果を返す、ファイルをアップロードするなど)。
  10. +
  11. すべてのアクションが完了したら、ユーザーを別のページにリダイレクトします。
  12. +
+ +

多くの場合、フォーム処理コードは、フォームの初期表示のためのGETルートと、フォームデータの検証と処理のための同じパスへのPOSTルートを使用して実装されています。これがこのチュートリアルで使用されるアプローチです。

+ +

Express 自体はフォーム操作のための特別なサポートを提供していませんが、ミドルウェアを使用してフォームからの POSTGET パラメータを処理したり、それらの値を検証/サニタイズしたりすることができます。

+ +

検証とサニタイズ

+ +

フォームからのデータが保存される前に、それは検証され、サニタイズされなければなりません。

+ + + +

このチュートリアルでは、人気のある express-validator モジュールを使ってフォームデータの検証とサニタイズを行います。

+ +

インストール

+ +

プロジェクトのルートで以下のコマンドを実行してモジュールをインストールします。

+ +
npm install express-validator
+
+ +

express-validatorの使用

+ +
+

Note: Githubのexpress-validatorガイドにAPIの概要が書かれています。(カスタムバリデータの作成を含む) すべての機能を知るには、これを読むことをお勧めします。以下では、サンプルの「地域図書館」にとって有用なサブセットだけを取り上げます。

+
+ +

コントローラでバリデータを使うには、以下のように 'express-validator/check' と 'express-validator/filter'モジュールから使いたい関数を要求(require)しなければなりません。

+ +
const { body,validationResult } = require('express-validator/check');
+const { sanitizeBody } = require('express-validator/filter');
+
+ +

多くの関数が用意されており、リクエストパラメータ、body、ヘッダー、Cookieなどのデータをチェックしてサニタイズすることができますし、一度にすべてのデータをチェックしてサニタイズすることもできます。このチュートリアルでは、主にbodysanitizeBodyvalidationResultを使用します。

+ +

機能は以下のように定義されています。

+ + + +

The validation and sanitization chains are middleware that should be passed to the Express route handler (we do this indirectly, via the controller). When the middleware runs, each validator/sanitizer is run in the order specified.

+ +

We'll cover some real examples when we implement the LocalLibrary forms below.

+ +

Form design

+ +

Many of the models in the library are related/dependent—for example, a Book requires an Author, and may also have one or more Genres. This raises the question of how we should handle the case where a user wishes to:

+ + + +

For this project we will simplify the implementation by stating that a form can only:

+ + + +
+

Note: A more "robust" implementation might allow you to create the dependent objects when creating a new object, and delete any object at any time (for example, by deleting dependent objects, or by removing references to the deleted object from the database).

+
+ +

Routes

+ +

In order to implement our form handling code, we will need two routes that have the same URL pattern. The first (GET) route is used to display a new empty form for creating the object. The second route (POST) is used for validating data entered by the user, and then saving the information and redirecting to the detail page (if the data is valid) or redisplaying the form with errors (if the data is invalid).

+ +

We have already created the routes for all our model's create pages in /routes/catalog.js (in a previous tutorial). For example, the genre routes are shown below:

+ +
// GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id).
+router.get('/genre/create', genre_controller.genre_create_get);
+
+// POST request for creating Genre.
+router.post('/genre/create', genre_controller.genre_create_post);
+
+ +

Express forms subarticles

+ +

The following sub articles will take us through the process of adding the required forms to our example application. You need to read and work through each one in turn, before moving on to the next one.

+ +
    +
  1. Create Genre form — Defining a page to create Genre objects.
  2. +
  3. Create Author form — Defining a page to create Author objects.
  4. +
  5. Create Book form — Defining a page/form to create Book objects.
  6. +
  7. Create BookInstance form — Defining a page/form to create BookInstance objects.
  8. +
  9. Delete Author form — Defining a page to delete Author objects.
  10. +
  11. Update Book form — Defining page to update Book objects.
  12. +
+ +

Challenge yourself

+ +

Implement the delete pages for the Book, BookInstance, and Genre models, linking them from the associated detail pages in the same way as our Author delete page. The pages should follow the same design approach:

+ + + +

A few tips:

+ + + +

Implement the update pages for the BookInstance, Author, and Genre models, linking them from the associated detail pages in the same way as our Book update page.

+ +

A few tips:

+ + + +

まとめ

+ +

NPM の Express、Node、およびサードパーティのパッケージは、Web サイトにフォームを追加するために必要なすべてを提供します。この記事では、Pug を使用してフォームを作成する方法、express-validator を使用して入力を検証およびサニタイズする方法、およびデータベース内のレコードを追加、削除、および変更する方法を学びました。

+ +

これで、基本的なフォームとフォーム処理コードを自分の Node Web サイトに追加する方法を理解したはずです。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs/deployment", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/index.html b/files/ja/learn/server-side/express_nodejs/index.html new file mode 100644 index 0000000000..a7ddf93fe5 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/index.html @@ -0,0 +1,79 @@ +--- +title: Express Web フレームワーク (Node.js/JavaScript) +slug: Learn/Server-side/Express_Nodejs +tags: + - Beginner + - CodingScripting + - Express + - Express.js + - Intro + - JavaScript + - Learn + - Node + - Server-side programming + - node.js + - イントロダクション + - サーバサイドプログラミング + - 初心者 + - 学習 +translation_of: Learn/Server-side/Express_Nodejs +--- +
{{LearnSidebar}}
+ +

Express は、JavaScript で書かれ、Node.js 実行環境内でホストされている、人気の指図しないウェブフレームワークです。このモジュールでは、このフレームワークの主な利点、開発環境の設定方法、一般的なウェブ開発と配置作業の実行方法について説明します。

+ +

前提条件

+ +

このモジュールを始める前に、サーバーサイドのウェブプログラミングとウェブフレームワークが何かを理解する必要があります。理想的なのはサーバーサイドのウェブサイトプログラミングの第一歩モジュールのトピックを読むことです。プログラミングの概念と JavaScript の一般的な知識があることを強くお勧めしますが、中核となる概念を理解するために不可欠ではありません。

+ +
+

メモ: このウェブサイトには、クライアントサイド開発のコンテキストで JavaScript を学習するための多くの有用なリソースがあります。JavaScriptJavaScript ガイドJavaScript の基本JavaScript (学習)。JavaScript のコアとなる言語と概念は、Node.js でのサーバーサイド開発と同じであり、この資料は関連性があります。Node.js は、ブラウザーレス環境で役立つ機能をサポートするための追加の API を提供します (たとえば、HTTP サーバーを作成してファイルシステムにアクセスするため。ただし、ブラウザーおよび DOM を操作するための JavaScript API はサポートしません)。

+ +

このガイドは Node.js と Express を使った作業についての情報を提供します。インターネットや本には他にもたくさんの優れたリソースがあります。これらのうち一部は How do I get started with Node.js (StackOverflow) と What are the best resources for learning Node.js? (Quora) からリンクされています。

+
+ +

ガイド

+ +
+
Express/Node の入門
+
この最初の Express 記事では、"Node とは何ですか?"、"Express とは何ですか?" という質問に答えます。Express ウェブフレームワークが特別になった理由の概要を説明します。主な機能の概要を説明し、Express アプリケーションの主な構成要素をいくつか紹介します (ただし、現時点ではテスト用の開発環境はまだありません)。
+
Node (Express) 開発環境の設定
+
Express の目的がわかったので、Windows、Linux (Ubuntu)、および Mac OS X 上で Node/Express 開発環境を設定およびテストする方法を説明します。この記事は、オペレーティングシステム共通の、Express アプリの開発を始めるために必要なものを提供します。
+
Express チュートリアル: 地域図書館のウェブサイト
+
私たちの実用的なチュートリアルシリーズの最初の記事はあなたが何を学ぶかについて説明して、それを通して研究し、そしてその後の記事で進化するであろう "地域図書館" の例のウェブサイトの概要を提供します。
+
Express チュートリアル Part 2: スケルトンウェブサイトの作成
+
この記事ではどのようにして "スケルトン"ウェブサイトプロジェクトを作成し、その後サイト固有のルート、テンプレート/ビュー、およびデータベースを追加するかを説明します。
+
Express チュートリアル Part 3: データベースの使用 (Mongoose を使用)
+
この記事では、Node/Express 用のデータベースについて簡単に紹介します。続いて、Mongoose を使用して「地域図書館」ウェブサイトへのデータベースアクセスを提供する方法を説明します。オブジェクトスキーマとモデルの宣言方法、主なフィールドタイプ、および基本的な検証について説明します。また、モデルデータにアクセスするための主な方法のいくつかについても簡単に説明します。
+
Express チュートリアル Part 4: ルートとコントローラー
+
このチュートリアルでは、「地域図書館」ウェブサイトで最終的に必要なすべてのリソースエンドポイントに対して、"ダミー" ハンドラ関数を使用してルート (URL 処理コード) を設定します。完成したら、次の記事で実際のハンドラ関数を使って拡張できるように、ルート処理コードのためのモジュール構造を作ります。Express を使用してモジュラールートを作成する方法についても、非常によく理解できるでしょう。
+
Express チュートリアル Part 5: ライブラリデータの表示
+
これで、「地域図書館」のウェブサイトの書籍やその他のデータを表示するページを追加する準備が整いました。このページには、各モデルタイプのレコード数と、すべてのモデルのリストおよび詳細ページを示すホームページが含まれます。その過程で、データベースからレコードを取得したりテンプレートを使用したりする実際的な経験を積むことになります。
+
Express チュートリアル Part 6: フォームの操作
+
このチュートリアルでは Pug を使用して Express で HTML フォームを操作する方法、特にデータベースからドキュメントを作成、更新、削除するためのフォームを作成する方法を説明します。
+
Express チュートリアル Part 7: プロダクションへのデプロイ
+
これで素晴らしい「地域図書館」ウェブサイトを作成したので、それを公共のウェブサーバーにインストールして、図書館のスタッフとメンバーがインターネットを介してアクセスできるようにします。この記事では、ウェブサイトをデプロイするためのホストを見つける方法、およびサイトを運用に向けて準備するために必要な作業の概要について説明します。
+
+ +

関連情報

+ +
+
PWS/Cloud Foundry に LocalLibrary をインストールする
+
この記事では、Pivotal Web サービスの PaaS クラウドに「地域図書館」をインストールする方法の実際的なデモンストレーションを行います。これは、上記のチュートリアルの第7部で使用されている PaaS クラウドサービスである Heroku に代わるフル機能のオープンソースです。PWS/Cloud Foundry は、Heroku (または別の PaaS クラウドサービス) に代わるものを探している場合、または単に何か違うことを試したい場合には、絶対にチェックする価値があります。
+
+ +

チュートリアルを追加する

+ +
+

既存のチュートリアル記事は以上となります。あなたがそれを拡張したいならば、カバーする他の興味深いトピックは以下の通りです:

+ + + +

そしてもちろん、評価作業を行うのは素晴らしいことです。

+
diff --git a/files/ja/learn/server-side/express_nodejs/installing_on_pws_cloud_foundry/index.html b/files/ja/learn/server-side/express_nodejs/installing_on_pws_cloud_foundry/index.html new file mode 100644 index 0000000000..f3a62d8b6e --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/installing_on_pws_cloud_foundry/index.html @@ -0,0 +1,242 @@ +--- +title: PWS/Cloud Foundry に LocalLibrary をインストールする +slug: Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry +translation_of: Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry +--- +
{{LearnSidebar}}
+ +

この記事では Pivotal Web Services の PaaS クラウドに地域図書館をインストールする方法の実際的なデモンストレーションを提供します。これは、チュートリアルのパート7で使用されている PaaS クラウドサービスである Heroku のフル機能のオープンソース代替です。PWS/Cloud Foundry は、Heroku (または別の PaaS クラウドサービス) に代わるものを探している場合、または単に何か違うことを試したい場合には、絶対にチェックする価値があります。

+ +

Why PWS?

+ +

Pivotal Web Services is a public instance of the Open Source Cloud Foundry Platform. It is a polyglot platform supporting many different languages including Node.js, Java, PHP, Python, Staticfiles, and Ruby. It has a introductory free trial and is incredibly efficient for running Node applications! As Node and Express are open source projects, there is consistency with working with an open deployment platform such as Cloud Foundry. You can get under the hood and see how an application is hosted.

+ +

There are multiple reasons to use PWS!

+ + + +

How does PWS work?

+ +

PWS runs websites and applications using containers and has been for many years. Cloud Foundry started using a container technology called Warden and is now using a container system called Garden. These are very similar to the popular Docker container and in fact, many installations of Cloud Foundry support deploying Docker containers.

+ +

One of the advantages of using Cloud Foundry is that you do not need to create the container spec, as Cloud Foundry's buildpacks will manufacture them based on the latest components. Apps on Cloud Foundry should follow 12 Factor guidelines as the containers deployed are ephemeral and may be cleaned up at anytime and redeployed somewhere else in the cloud. This ensures that your apps and platform have the latest software. An application can consist of multiple instances where the application is placed into redundant containers that enable high availability of your app. Cloud Foundry will automatically handle all the load balancing between identical instances. This allows you to scale your application for performance and availability

+ +

Since the file system is ephemeral any temporary storage or services should be located elsewhere using backing services. This can be done using marketplace services available on different providers or by bringing your own via User Provided Services.

+ +

What do we cover below?

+ +

This post covers how to modify the LocalLibrary application from the tutorial for deployment on PWS and Cloud Foundry. In doing so, it covers the basics of deploying any node.js application to PWS with the following steps.

+ + + +

So let's get started. You have two options, you can go through the tutorial from the beginning or you can just download the completed project and modify it from there for use on PWS. To do the latter, you can do the following from a terminal:

+ +
git clone https://github.com/mdn/express-locallibrary-tutorial
+ +

You'll then need to follow the preparation steps listed in the Getting your website ready to publish section of Express Tutorial Part 7: Deploying to production, before then following the steps listed below.

+ +
+

Note: This work flow is based on the Mozilla Heroku work flow in the main Express/Node tutorial series for consistency, to help readers compare and contrast. 

+
+ +

Modifying the LocalLibrary for PWS

+ +

Deployment of a Node application on Cloud Foundry takes the following steps. Using the downloaded 'cf' CLI tool on your environment, your source code and supporting metadata files are uploaded to Cloud Foundry which will assemble and package the components of your application. Note that your files need to be located on your system to deploy or as a zip archive somewhere accessible on the internet. We'll assume the former.

+ +

This means, no assumptions about which source control system is used. As long as you have a complete source tree in your local file system you can deploy the app. There are some things you have to make available to ensure the correctly assembly of your Node application. First Cloud Foundry cf CLI will look for the presence of the 'package.json' file to determine the dependencies and download the necessary components. The rules of this assembly are defined in Cloud Foundry's nodejs buildpack. An optional cloud foundry manifest file can specify information about your application such as name, size and start command if non-standard. In addition to deploying the application, the cf CLI tool can also configure services, set environment variables and view logs. That's all the overview you need in order to get started (see Getting Started on Pivotal Web Services for a more comprehensive guide). Let's start making the changes so you'll need to deploy the LocalLibrary application to  PWS.

+ +

Set node version

+ +

The package.json contains everything needed to work out your application dependencies and what file should be launched to start your site. Cloud Foundry and PWS detects the presence of this file, and will use it to provision your app environment. The only useful information missing in our current package.json is the version of node. We can find the version of node we're using for development by entering the command:

+ +
node --version
+# will return version e.g. v6.10.3
+ +

Open package.json with a text editor, and add this information as an engines > node section as shown (using the version number retrieved above).

+ +
{
+  "name": "express-locallibrary-tutorial",
+  "version": "0.0.0",
+  "engines": {
+    "node": "6.10.3"
+  },
+  "private": true,
+  ...
+
+ +

Database configuration

+ +

So far in this tutorial we've used a single database that is hard coded into the app.js file. Normally we'd like to be able to have a different database for production and development, so next we'll modify the LocalLibrary website to get the database URI from the OS environment, and otherwise use our development database that we added manually earlier. Cloud Foundry has a very flexible services model that enables multiple services of the same type to exist in the environment. It stores all services related configurations in a single parseable JSON object called VCAP_SERVICES. A typical VCAP_SERVICES variable looks like this:

+ +
{
+ "VCAP_SERVICES": {
+  "mlab": [
+   {
+    "credentials": {
+     "uri": "mongodb://CloudFoundry_test_dev:somecr8zypassw0rd@dbhost.mlab.com:57971/CloudFoundry_dbname"
+    },
+    "label": "mlab",
+    "name": "node-express-tutorial-mongodb",
+    "plan": "sandbox",
+    "provider": null,
+    "syslog_drain_url": null,
+    "tags": [
+     "Cloud Databases",
+     "Developer Tools",
+     "Web-based",
+     "Data Store",
+    ],
+    "volume_mounts": []
+   }
+  ]
+ }
+}
+
+
+ +

Writing the code to extract and parse this environment variable is not hard, but it doesn't add a lot of value when others have written libraries to do this. In this case, there is a node.js package we can use called cfenv.

+ +

This will download the cfenv module and its dependencies, and modify the package.json file as required. Open app.js and find the block with all the 'requires' that load the modules into your application. In this example look for the line that looks something like this:

+ +
var expressValidator = require('express-validator');
+ +

If you cannot find that exact line, look for the blocks of 'requires' and look for the last one. Add the following text after it:

+ +
var cfenv = require('cfenv');
+ +
    +
  1. +

    To install the package, go to your terminal and make sure you are in the directory where the package.json file for LocalLibrary is. From the command line, type:

    + +
    npm install cfenv
    +
  2. +
  3. +

    Now that you have loaded the module, this next line will instantiate an object that will contain the app and services information required for deployment. Add the following after the line that contains app.use(helmet());

    + +
    // Set up CF environment variables
    +var appEnv = cfenv.getAppEnv();
    +
    + +

    When this line executes, all the Cloud Foundry application environment information will become available to the application in the appEnv object.

    +
  4. +
  5. +

    Now it is time to update the application to use the database configured by the platform. Find the line that sets the mongoDB connection variable. It will look something like this:

    + +
    var mongoDB = process.env.MONGODB_URI || dev_db_url;
    +
  6. +
  7. +

    You will now modify the line with the following code  appEnv.getServiceURL('node-express-tutorial-mongodb') to get the connection string from an environment variable that is being managed by the cfenv  module. If no service has been created and bound it will use your own database URL you created as part of the tutorial instead of the one from the environment. So replace the line above with the following:

    + +
    var mongoDB = appEnv.getServiceURL('node-express-tutorial-mongodb') || dev_db_url;
    +
    +
  8. +
  9. +

    Now run the site locally (see Testing the routes for the relevant commands) and check that the site still behaves as you expect. At this point your app is ready to use with Cloud Foundry and Pivotal Web Services.

    +
  10. +
+ +

Get a Pivotal Web Services account

+ +

To start using Pivotal Web Services you will first need to create an account (skip ahead to Create and upload the website if you've already got an account and have already installed the PWS cf CLI client).

+ + + +

Install the cf CLI client

+ +

The cf CLI client is a software tool for managing and deploying your application. Download and install the PWS cf CLI client by following the instructions on Pivotal Web Services or downloading directly from GIthub. Be sure to download the correct version for your computer. After the client is installed you will be able run commands, for example to get help on the client:

+ +
cf help
+
+ +

We'll now go through the steps to login to PWS using the CLI and deploy — or in Cloud Foundry parlance "push" your app.

+ +

Create and upload the website

+ +

To create the app we navigate to the directory where our modified files are. This is the same directory where the LocalLibrary package.json file is located. First, let's tell the cf CLI which Cloud Foundry instance you want to use. We need to do this, since the cf CLI tool can be used with any standard Cloud Foundry system, so this command indicates which specific Cloud Foundry you are using. Enter the following terminal command now:

+ +
cf api api.run.pivotal.io
+ +

Next login using the following command (enter your email and password when prompted):

+ +
cf login
+Email: enter your email
+Password: enter your password
+ +

We can now push our app to PWS. In the below example. replace 'some-unique-name' with something you can remember that is likely to be unique. If it isn't unique, the system will let you know. The reason this name has to be unique to the PWS system is it is the address we will use to to access your LocalLibrary application. I used mozilla-express-tutorial-xyzzy. You should use something else.

+ +
cf push some-unique-name -m 256MB
+ +

Note the -m flag we added is not required. We just included it so that we only use 256MB of memory to run the app. Node apps typically can run in 128 MB, but we are being safe. If we didn't specify the memory, the CLI would use the default 1 GB of memory, but we want to make sure your trial lasts longer. You should now see a bunch of text on the screen. It will indicate that the CLI is uploading all your files, that it's using the node buildpack, and it will start the app. If we're lucky, the app is now "running" on the site at the URL https://some-unique-name.cfapps.io. Open your browser and run the new website by going to that URL.

+ +
Note: The site will be running using our hardcoded development database at this time. Create some books and other objects, and check out whether the site is behaving as you expect. In the next section we'll set it to use our new database.
+ +

Setting configuration variables

+ +

You will recall from a preceding section that we need to set NODE_ENV to 'production' in order to improve our performance and generate less-verbose error messages.

+ +
    +
  1. +

    Do this by entering the following command:

    + +
    cf set-env some-unique-name NODE_ENV production
    +
    +
  2. +
  3. +

    We should also use a separate database for production. Cloud Foundry can take advantage of a marketplace to create a new service and automatically bind it to your app. Bind means place the service database credentials in the environment variable space of the container running your application for you to access. Enter the following commands:

    + +
    cf create-service mlab sandbox node-express-tutorial-mongodb
    +cf bind-service some-unique-name node-express-tutorial-mongodb
    +
    +
  4. +
  5. +

    You can inspect your configuration variables at any time using the cf env some-unique-name command — try this now:

    + +
    cf env some-unique-name
    +
    +
  6. +
  7. +

    In order for your applications to use the new credentials you will have to restage your application, meaning that it will restart and apply the new environment variables. This can be done using the following — enter this command now:

    + +
    cf restage some-unique-name
    +
    +
  8. +
  9. +

    If you check the home page now it should show zero values for your object counts, as the changes above mean that we're now using a new (empty) database.

    +
  10. +
+ +

Debugging

+ +

The PWS cf client provides a few tools for debugging:

+ +
>cf logs some-unique-name --recent  # Show current logs
+>cf logs some-unique-name # Show current logs and keep updating with any new results
+ +

Summary

+ +

If you followed the above steps, you should have now deployed the LocalLibrary app to PWS. Well done! If the deployment wasn't successful, double check all the steps.

diff --git a/files/ja/learn/server-side/express_nodejs/introduction/index.html b/files/ja/learn/server-side/express_nodejs/introduction/index.html new file mode 100644 index 0000000000..c194cff772 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/introduction/index.html @@ -0,0 +1,528 @@ +--- +title: Express/Node のイントロダクション +slug: Learn/Server-side/Express_Nodejs/Introduction +tags: + - Beginner + - CodingScripting + - Express + - Learn + - Node + - nodejs + - server-side + - サーバーサイド + - 初心者 +translation_of: Learn/Server-side/Express_Nodejs/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}
+ +

Express の最初の記事では ”Node って何だろう?”、”Express って何だろう?”という疑問に答え、なぜ Express ウェブフレームワークが特別なのかについて概要を説明します。主な特徴、Express アプリケーションの主な基本要素(テスト開発環境についてはここではまだ触れません) を大まかに説明します。

+ + + + + + + + + + + + +
前提条件基本的なコンピューターリテラシー。サーバーサイドのウェブサイトプログラミングの一般的な理解、特にウェブサイトにおけるクライアントとサーバーのやりとりの仕組み。
目標Express の特徴、Node との適合性、提供する機能、Express アプリケーションの主要な基本要素に慣れてください。
+ +

Node の紹介

+ +

Node (正式には Node.js) はオープンソースのクロスプラットフォーム、実行環境で、開発者はあらゆるサーバーサイドのツールやアプリケーションを JavaScript で作成することができます。この実行環境はブラウザーコンテキスト外での使用 (すなわち、コンピューターまたはサーバー OS 上での直接実行) を目的としています。そのため、クライアントサイドではブラウザー固有の JavaScript API が省略され、HTTP やファイルシステムライブラリを含む従来の OS API がサポートされます

+ +

ウェブサーバー開発の観点から Node には多くの利点があります。

+ + + +

Node HTTP パッケージを使用することで、Node.js で簡単な ウェブサーバーを作成できます。

+ +

Hello Node.js

+ +

次の例では、URL http://127.0.0.1:8000/ にあるあらゆる種類の HTTP リクエストを待ち受ける ウェブサーバーを作成します。リクエストが受信されると、スクリプトは "Hello World" という文字列でレスポンスします。すでに Node をインストールしている場合は、次の手順に従ってこの例を試すことができます。

+ +
    +
  1. ターミナルを開きます (Windows ではコマンドラインユーティリティを開きます)。
  2. +
  3. プログラムを保存するフォルダ (たとえば "test-node") を作成し、端末に次のコマンドを入力して移動します。
  4. +
+ +
cd test-node
+ +
    +
  1. 好きなテキストエディタを使って "hello.js" というファイルを作成し、次のコードを貼り付けます。
  2. +
+ +
// HTTPモジュールの読み込み
+var http = require("http");
+
+//  HTTPサーバーを作成し、ポート8000でリクエストを行う
+http.createServer(function(request, response) {
+
+   // HTTP ステータスとコンテントタイプを持つ HTTP ヘッダのレスポンスを設定
+   response.writeHead(200, {'Content-Type': 'text/plain'});
+
+   // レスポンスボディー"Hello World"を送信
+   response.end('Hello World\n');
+}).listen(8000);
+
+//  サーバーにアクセスするための URL を出力
+console.log('Server running at http://127.0.0.1:8000/');
+ +
    +
  1. 上記で作成したフォルダにファイルを保存します。
  2. +
  3. ターミナルに戻り、次のコマンドを入力します。
  4. +
+ +
node "hello.js"
+ +

最後に、ウェブブラウザーで "http://localhost:8000" に移動します。テキスト以外は空の ウェブページの左上に "Hello World" というテキストが表示されます。

+ +

ウェブフレームワーク

+ +

その他の一般的なウェブ開発タスクは、Node 自体では直接サポートされていません。異なる HTTP 動詞 (GET, POST, DELETE など) に特定の処理を追加したい場合、別々の URL パス ("routes") でリクエストを個別に処理したり、静的ファイルを提供したり、テンプレートを使用してレスポンスを動的に作成したり、あなた自身でコードを書く必要があります。そうしない場合はウェブフレームワークを使用して、車輪の再発明を避けることができます。

+ +

Express のイントロダクション

+ +

Express は最も一般的な Node ウェブフレームワークであり、他の多くの一般的な Node ウェブフレームワークの基礎となるライブラリです。それは以下のメカニズムを提供します:

+ + + +

Express 自体はかなりシンプルですが、開発者はほぼすべてのウェブ開発問題に対応する互換性のあるミドルウェアパッケージを作成しています。Cookie、セッション、ユーザーログイン、URL パラメータ、POST データ、セキュリティヘッダーなどを扱うライブラリがあります。Express チームが管理するミドルウェア・パッケージのリストは、Express Middleware (一般的なサード・パーティ・パッケージのリストとともに) にあります。

+ +
+

注: この柔軟性は両刃の剣です。ほぼすべての問題や要件に対応するミドルウェアパッケージがありますが、適切なパッケージを使用して作業することは時には挑戦になることがあります。アプリケーションを構造化する「正しい方法」もなく、インターネット上で見つかる多くの例は最適ではないし、ウェブアプリケーションを開発するために必要なことのほんの一部を示しているだけです。

+
+ +

Node と Express はどこから来たのですか?

+ +

Node は 2009 年に Linux 用に最初にリリースされました。NPM パッケージマネージャは 2010 年にリリースされ、ネイティブ Windows サポートは 2012 年に追加されました。現在の LTS リリースは Node v10.13.0 で、最新のリリースは Node 11.2.0 です。これは、豊かな歴史の小さなスナップショットです。もっと知りたいのであれば、Wikipedia を掘り下げてみてください。

+ +

Express は 2010 年 11 月に最初にリリースされ、現在 API のバージョンが 4.16.3 になっています。現在のリリースの変更点については更新履歴を、詳細な履歴リリースノートについては GitHub を参照してください。

+ +

Node と Express はどれくらい普及していますか?

+ +

ウェブフレームワークの普及は、それが維持されるかどうかの指標であり、ドキュメンテーション、アドオンライブラリ、テクニカルサポートの面でどのようなリソースが利用される可能性が高いかという点で重要です。

+ +

サーバー側のフレームワークの普及率 (Hot Frameworks のようなサイトでは、GitHub プロジェクトの数や各プラットフォームの StackOverflow の質問数などの仕組みを使って人気を評価しようとしています) は、すぐに利用可能で決定的なものではありません。より良い質問は、人気のないプラットフォームの問題を避けるために Node と Express が「人気がある」かどうかです。それらは進化し続けていますか?あなたがそれを必要としたら助けを得ることができますか?あなたが Express を学ぶならば、あなたは職を得る機会がありますか?

+ +

Express を使用している有名企業の数、コードベースに貢献している人の数、および無料と有料の両方でサポートを提供している人の数に基づけば、Express は一般的なフレームワークです。

+ +

Expressは指図をしたがりますか?

+ +

ウェブフレームワークはしばしば自身を「指図をしたがる」または「指図をしない」ものと称します。

+ +

指図をしたがるフレームワークは、特定のタスクを扱うのに「正しい方法」があるという考えを持っています。何であれ正しい方法であれば普通よく理解され細かく文書化されているため、(特定のタイプの問題を解決するような)特定の領域における素早い開発をサポートします。しかしながら、彼らが主眼とする領域の外にある問題を解決するにあたっては柔軟性に劣り、利用できるコンポーネントやアプローチの選択肢が限られたものになりがちです。

+ +

一方、指図をしないフレームワークは、目的の達成のためにコンポーネントをつなぎ合わせる最善の方法や、どのコンポーネントを使うかにさえも、あまり制約を設けません。
+ 開発者は、コンポーネントを自分自身で探す必要があるという手間をかければ、特定のタスクを完了させるのに最適なツールの利用をより容易にします。

+ +

Express は指図をしません。リクエストを処理するチェインの中で、互換性のある好きなミドルウェアを、好きな順番で挿し込むことができます。1 つのファイルまたは複数のファイル、任意のディレクトリ構造を使ってアプリケーションを構成できます。
+ ときに選択肢が多すぎるようにも感じられるでしょう!

+ +

Expressコードはどのように見えますか?

+ +

従来のデータ駆動型ウェブサイトでは、ウェブアプリケーションはウェブブラウザー (または他のクライアント) からの HTTP リクエストを待機します。リクエストが受信されると、アプリケーションは URL パターンと、POST データまたは GET データに含まれる可能性のある関連情報に基づいて、必要なアクションを実行します。必要に応じて、データベースから情報を読み書きしたり、リクエストを満たすために必要な他のタスクを実行することができます。アプリケーションはウェブブラウザーにレスポンスを返し、検索されたデータを HTML テンプレートのプレースホルダに挿入することによってブラウザーが表示する HTML ページを動的に作成することがよくあります。

+ +

Express は特定の HTTP 動詞 (GET, POST, SET など) と URL パターン ("Route") に対してどの関数が呼び出されるかを指定するメソッドと、どのテンプレート ("view") エンジンが使用されるかを指定するメソッドを提供します。テンプレートエンジンを使用するには、レスポンスをレンダリングするためのテンプレートファイルを配置します。Express ミドルウェアを使用して、Cookie、セッション、およびユーザー、POST/GET パラメーターなどのサポートを追加することができます。Node がサポートするデータベース・メカニズムを使用できます (Express はデータベース関連の動作を定義しません)。

+ +

次のセクションでは、Express およびノー​​ド・コードを使用して作業するときに表示される一般的な事項について説明します。

+ +

Helloworld Express

+ +

最初に、標準の Express の Hello World の例を考えてみましょう (これについては、以下の各セクションで説明します)。

+ +
+

Tip: Node と Express がすでにインストールされている場合 (または次の記事のようにインストールする場合) は、このコードを app.js というテキストファイルに保存し、bash コマンドプロンプトで次のように呼び出して実行できます。

+ +

node ./app.js

+
+ +
var express = require('express');
+var app = express();
+
+app.get('/', function(req, res) {
+  res.send('Hello World!');
+});
+
+app.listen(3000, function() {
+  console.log('Example app listening on port 3000!');
+});
+ +

最初の2行は require() で express モジュールをインポートして Express アプリケーションを作成します。このオブジェクトは伝統的に app と呼ばれ、HTTP リクエストのルーティング、ミドルウェアの設定、HTML ビューのレンダリング、テンプレートエンジンの登録、アプリケーションの動作を制御するアプリケーション設定の変更 (環境モード、ルート定義の大文字と小文字の区別など) のためのメソッドがあります。

+ +

コードの中央部分 (app.get で始まる3行) はルート定義を示しています。app.get() メソッドは、サイトルートからの相対パス ('/') を持つ HTTP GET リクエストがあるたびに呼び出されるコールバック関数を指定します。コールバック関数はリクエストとレスポンスオブジェクトを引数として取り、レスポンスに対して単に send() を呼び出して文字列 "Hello World!" を返します。

+ +

最後のブロックは3000番ポートでサーバーを起動し、コンソールにログコメントを出力します。 サーバーが稼働している場合は、ブラウザーの localhost:3000 にアクセスして、レスポンスの例を確認することができます。

+ +

モジュールのインポートと作成

+ +

モジュールは Node の require() 関数を使って他のコードにインポートできる JavaScript ライブラリ/ファイルです。 Express 自体はモジュールです。Express アプリケーションで使用するミドルウェアおよびデータベースライブラリも同様です。

+ +

以下のコードは、例として Express フレームワークを使用して、モジュールを名前でインポートする方法を示しています。 最初に require() 関数を呼び出し、モジュールの名前を文字列 ('express') として指定し、返されたオブジェクトを呼び出して Express アプリケーションを作成します。その後、アプリケーションオブジェクトのプロパティと機能にアクセスできます。

+ +
var express = require('express');
+var app = express();
+ +

独自のモジュールを作成して、同じ方法でインポートすることもできます。

+ +
+

メモ: あなたは自身のモジュールを作成したいと思うでしょう、これはあなたが自身のコードを管理しやすい部品に分けることを可能にします 。ちなみに、モノリシックな単一ファイルのアプリケーションは理解し維持するのが難しいです。モジュールを使用すると、明示的にエクスポートした変数のみがインポートされるため、モジュールを使用すると名前空間を管理するのにも役立ちます。

+
+ +

オブジェクトをモジュールの外部で利用可能にするには、それらを exports オブジェクトの追加プロパティとして公開するだけです。たとえば、以下の square.js モジュールは area() メソッドと perimeter() メソッドをエクスポートしたファイルです。

+ +
exports.area = function(width) { return width * width; };
+exports.perimeter = function(width) { return 4 * width; };
+ +

require() を使ってこのモジュールをインポートし、次に示すようにエクスポートされたメソッドを呼び出すことができます。

+ +
var square = require('./square'); //  require() にはファイル拡張子を除いたファイル名を引数に指定します。
+console.log('The area of a square with a width of 4 is ' + square.area(4));
+ +
+

メモ: モジュールへの絶対パス (または最初に行ったように名前) を指定することもできます。

+
+ +

一度に1つのプロパティを構築するのではなく、1つの割り当てで完全なオブジェクトをエクスポートする場合は、次のように module.exports に割り当てます (これを実行して、エクスポートオブジェクトのルートをコンストラクタまたは他の関数にすることもできます)。

+ +
module.exports = {
+  area: function(width) {
+    return width * width;
+  },
+
+  perimeter: function(width) {
+    return 4 * width;
+  }
+};
+ +
+

Note: あなたは exports を与えられたモジュール内の module.exports へのショートカットとして考えることができます。実際、exports は、モジュールが評価される前に module.exports の値に初期化される単なる変数です。 その値はオブジェクト (この場合は空のオブジェクト) への参照です。これは、exportsmodule.exports によって参照されるのと同じオブジェクトへの参照を保持することを意味します。また、エクスポートに別の値を代入することで、module.exports にバインドされなくなることも意味します。

+
+ +

モジュールの詳細については、モジュール (Node API のドキュメント) を参照してください。

+ +

非同期 API の使用

+ +

JavaScriptコードでは、操作に同期APIよりも非同期APIが頻繁に使用されるため、処理に時間がかかることがあります。 同期APIは、各操作を完了してから次の操作を開始できるAPIです。 たとえば、次のログ関数は同期的で、テキストをコンソールに順番に印刷します(First、Second)。

+ +
console.log('First');
+console.log('Second');
+ +

対照的に、非同期 API は、API が操作を開始してすぐに (操作が完了する前に) 戻るものです。操作が終了すると、API は何かのメカニズムを使用して追加の実行を行います。例えば、次のコードでは最初に setTimeout() メソッドが呼び出されてすぐに返されても、操作が数秒間完了しないため、 "Second, First" が出力されます。

+ +
setTimeout(function() {
+   console.log('First');
+   }, 3000);
+console.log('Second');
+ +

Node はシングルスレッドのイベント駆動型実行環境であるため、ノンブロッキングの非同期 API を使用することは、ブラウザーよりも Node にとってさらに重要です。シングルスレッドとは、サーバーへのすべてのリクエストが (別々のプロセスに分割されるのではなく) 同じスレッドで実行されることを意味します。このモデルは速度とサーバーリソースの点で非常に効率的です。しかし、完了に時間がかかる同期メソッドを呼び出す関数があると、それらは現在のリクエストだけでなく、他のすべてのリクエストがウェブアプリケーションによって処理されることをブロックします。

+ +

非同期 API がアプリケーションに完了したことを通知するにはいくつかの方法があります。最も一般的な方法は、非同期 API を呼び出すときにコールバック関数を登録することです。これは、操作が完了したときにコールバックされます。 これが上記で使用されているアプローチです。

+ +
+

Tip: コールバックを使用することは、順番に実行しなければならない一連の従属非同期操作がある場合、かなり "面倒" になる可能性があります。これは、複数レベルのネストされたコールバックをもたらすためです。この問題は一般に「コールバック地獄」として知られています。この問題は、優れたコーディング方法 ( http://callbackhell.com/ を参照)、async などのモジュールの使用、または Promise などの ES6 機能への移行によっても軽減できます。

+
+ +
+

メモ: Node と Express の一般的な規約は、エラー優先コールバックを使うことです。この規約では、コールバック関数の最初の値はエラー値ですが、後続の引数には成功データが含まれます。 なぜこのアプローチがこのブログで役に立つのかについての良い説明があります:Node.jsの方法 - エラーファーストコールバックについて (fredkschott.com)。

+
+ +

ルートハンドラの作成

+ +

上記の Hello World Express の例では、サイトルート ('/') への HTTP GET リクエストに対して(callback)ルートハンドラ関数を定義しました。

+ +
app.get('/', function(req, res) {
+  res.send('Hello World!');
+});
+ +

コールバック関数はリクエストとレスポンスオブジェクトを引数として取ります。 この場合、メソッドは単にレスポンスに対して send() を呼び出して、文字列 "Hello World!" を返します。リクエスト/レスポンスサイクルを終了するためのレスポンスメソッドは他にも多数あります。たとえば、JSONレスポンスを送信するために res.json() を呼び出し、ファイルを送信するために res.sendFile() を呼び出すことができます。

+ +
+

JavaScript tip: コールバック関数で好きな引数名を使うことができます。 コールバックが呼び出されると、最初の引数は常にリクエストになり、2番目の引数は常にレスポンスになります。 コールバックの本体で作業しているオブジェクトを識別できるようにそれらの名前を付けることは意味があります。

+
+ +

Express アプリケーションオブジェクトには、他のすべての HTTP 動詞のルートハンドラを定義するためのメソッドもあります。これらのメソッドはほとんど同じ方法で使用されます。

+ +

checkout()copy()delete()get()head()lock()merge()mkactivity(), mkcol(), move(), m-search(), notify(), options(), patch(), post(), purge(), put(), report(), search(), subscribe(), trace(), unlock(), unsubscribe().

+ +

app.all() という特別なルーティングメソッドがあります。これはあらゆる HTTP メソッドにレスポンスして呼び出されます。これはすべてのリクエストメソッドの特定のパスにミドルウェア機能をロードするために使用されます。次の例 (Express の資料から) は、使用される HTTP 動詞に関係なく、 /secret へのリクエストに対して実行されるハンドラを示しています(http モジュールでサポートされている場合)。

+ +
app.all('/secret', function(req, res, next) {
+  console.log('Accessing the secret section ...');
+  next(); // 次のハンドラに制御を渡します。
+});
+ +

ルートを使用すると、URL 内の特定のパターンの文字を照合し、URL からいくつかの値を抽出し、それらをパラメータとしてルートハンドラに渡すことができます(パラメータとして渡されるリクエストオブジェクトの属性として)。

+ +

多くの場合、サイトの特定の部分のルートハンドラをまとめて、共通のルートプレフィックスを使用してそれらにアクセスすると便利です (たとえば、Wiki のあるサイトでは、1つのファイルにすべての Wiki 関連ルートがあり、ルートプレフィックス /wiki/ を使用してアクセスすることがあります)。 Expressでは、これは express.Router オブジェクトを使用して実現されます。たとえば、wiki.js という名前のモジュールで Wiki ルートを作成してから、次に示すように Router オブジェクトをエクスポートできます。

+ +
// wiki.js - Wiki ルートモジュール
+
+var express = require('express');
+var router = express.Router();
+
+// ホームページルート
+router.get('/', function(req, res) {
+  res.send('Wiki home page');
+});
+
+// about ページルート
+router.get('/about', function(req, res) {
+  res.send('About this wiki');
+});
+
+module.exports = router;
+ +
+

メモ: Router オブジェクトにルートを追加することは、(前述のように) app オブジェクトにルートを追加するのと同じです。

+
+ +

メインアプリケーションファイルでルーターを使用するには、ルートモジュール (wiki.js) を require() してから、Express アプリケーションで use() を呼び出してミドルウェア処理パスにルーターを追加します。 2つの経路は /wiki//wiki/about/ からアクセス可能になります。

+ +
var wiki = require('./wiki.js');
+// ...
+app.use('/wiki', wiki);
+ +

ルートを扱うことについて、そして特に Router を使うことについてもっとより多くのことがあります。それらについては、リンクされたセクション、ルートとコントローラで説明します。

+ +

ミドルウェアの使用

+ +

ミドルウェアは静的ファイルの提供からエラー処理、HTTP レスポンスの圧縮まで、Express アプリケーションで広く使用されています。ルート関数は HTTP クライアントにレスポンスを返すことで HTTP リクエスト - レスポンスサイクルを終了しますが、ミドルウェア関数は通常、リクエストまたはレスポンスに対して何らかの操作を実行してから、「スタック」内の次の機能を呼び出します。これは、より多くのミドルウェアまたはルートハンドラの場合があります。ミドルウェアが呼び出される順序はアプリ開発者次第です。

+ +
+

Note: ミドルウェアは任意の操作を実行し、任意のコードを実行し、リクエストおよびレスポンスオブジェクトに変更を加えることができ、またリクエスト - レスポンスサイクルを終了することもできます。サイクルが終了しない場合は、next() を呼び出して次のミドルウェア機能に制御を渡す必要があります (そうでない場合、リクエストは中断されたままになります)。

+
+ +

Cookie の操作、セッション、ユーザ認証、リクエスト POST および JSON データへのアクセス、ロギングなどの一般的なウェブ開発タスクを簡素化するために、ほとんどのアプリはサードパーティ製ミドルウェアを使用します。Express チームが管理するミドルウェアパッケージのリストを見つけることができます。(他の人気のあるサードパーティのパッケージも含みます)。他の Express パッケージは NPM パッケージマネージャーで入手できます。

+ +

サードパーティのミドルウェアを使用するには、まず NPM を使用してそれをアプリにインストールする必要があります。たとえば、 morgan という HTTP リクエストロガーミドルウェアをインストールするには、次のようにします。

+ +
$ npm install morgan
+
+ +

次に、Express アプリケーションオブジェクトで use() を呼び出してミドルウェアをスタックに追加できます。

+ +
var express = require('express');
+var logger = require('morgan');
+var app = express();
+app.use(logger('dev'));
+...
+ +
+

メモ: ミドルウェアおよびルーティング機能は、宣言されている順序で呼び出されます。ミドルウェアによっては、順序が重要です (たとえば、セッションミドルウェアが cookie ミドルウェアに依存している場合は、最初に cookie ハンドラを追加する必要があります)。ほとんどの場合、ミドルウェアはルートを設定する前に呼び出されます。そうでないとルートハンドラがミドルウェアによって追加された機能にアクセスすることはできません。

+
+ +

あなたは自身のミドルウェア機能を書くことができ、そうする必要があるでしょう (エラー処理コードを作成するためだけの場合)。ミドルウェア関数とルートハンドラコールバックの唯一の違いは、ミドルウェア関数が次に next 引数を持つことです。ミドルウェア関数はリクエストサイクルを完了させるものではない場合に呼び出されます (ミドルウェア関数が呼び出されるとき、その中には呼び出される next 関数が含まれていなければなりません)。

+ +

ミドルウェアをすべてのレスポンスに適用するのか、特定の HTTP 動詞を含むレスポンス (GETPOST など) に適用するのかに応じて、 app.use() または app.add() のいずれかを使用してミドルウェア機能を処理チェーンに追加できます)。 app.use() を呼び出すときの経路はオプションですが、どちらの場合も同じ経路を指定します。

+ +

以下の例は、ルートの有無に関わらず、両方の方法を使用してミドルウェア関数を追加する方法を示しています。

+ +
var express = require('express');
+var app = express();
+
+// ミドルウェア関数の例
+var a_middleware_function = function(req, res, next) {
+  // ... perform some operations
+  next(); // next() を呼ぶことで Express はチェイン中の次のミドルウェア関数を呼びます。
+
+// すべてのルートと動詞に対して use() で関数を追加します。
+app.use(a_middleware_function);
+
+// 指定ルートに対して use() でミドルウェア関数を追加します。
+app.use('/someroute', a_middleware_function);
+
+// 指定の HTTP 動詞とルートに対してミドルウェア関数を追加します。
+app.get('/', a_middleware_function);
+
+app.listen(3000);
+ +
+

JavaScript Tip: 上記ではミドルウェア関数を別々に宣言してからコールバックとして設定しています。以前のルートハンドラ関数では、使用時にコールバック関数を宣言しました。JavaScript では、どちらの方法も有効です。

+
+ +

Express の資料には、Express ミドルウェアの使用および作成に関するより優れた資料があります。

+ +

静的ファイルの提供

+ +

express.static ミドルウェアを使用して、画像、CSS、JavaScript などの静的ファイルを提供できます (static() は、実際には Express の一部である唯一のミドルウェア関数です)。 たとえば、node を呼び出す場所と同じレベルで、'public' という名前のディレクトリーから画像、CSS ファイル、および JavaScript ファイルを配信するには、次の行を使用します。

+ +
app.use(express.static('public'));
+ +

public ディレクトリー内のファイルはすべて、ベース URL にそのファイル名 (ベースの "public" ディレクトリーに対する相対パス) を追加することによって提供されます。そのため、例えば:

+ +
http://localhost:3000/images/dog.jpg
+http://localhost:3000/css/style.css
+http://localhost:3000/js/app.js
+http://localhost:3000/about.html
+
+ +

static() を複数回呼び出して、複数のディレクトリーを扱うことができます。ファイルが1つのミドルウェア関数で見つからない場合は、そのファイルは後続のミドルウェアに単純に渡されます (ミドルウェアが呼び出される順序は宣言の順序に基づいています)。

+ +
app.use(express.static('public'));
+app.use(express.static('media'));
+ +

ファイルをベース URL に追加するのではなく、静的 URL の仮想プレフィックスを作成することもできます。たとえば、ここではファイルがプレフィックス "/media" でロードされるようにマウントパスを指定します。

+ +
app.use('/media', express.static('public'));
+ +

これで、public ディレクトリーにあるファイルを /media パスプレフィックスから読み込むことができます。

+ +
http://localhost:3000/media/images/dog.jpg
+http://localhost:3000/media/video/cat.mp4
+http://localhost:3000/media/cry.mp3
+
+ +

詳しくは、Expressでの静的ファイルの提供を参照してください。

+ +

エラーの処理

+ +

エラーは、通常の3つの引数ではなく、4つの引数 (err、req、res、next) を持つ1つ以上の特別なミドルウェア関数によって処理されます。例えば:

+ +
app.use(function(err, req, res, next) {
+  console.error(err.stack);
+  res.status(500).send('Something broke!');
+});
+ +

これらは必要なコンテンツを返すことができますが、他のすべての app.use() および呼び出しをルーティングした後に呼び出して、リクエスト処理プロセスの最後のミドルウェアになるようにする必要があります。

+ +

Express にはエラーハンドラが組み込まれています。これは、アプリで発生する可能性がある残りのエラーを処理します。 このデフォルトのエラー処理ミドルウェア関数は、ミドルウェア関数スタックの最後に追加されます。next() にエラーを渡し、それをエラーハンドラで処理しなかった場合、それは組み込みエラーハンドラによって処理されます。エラーはスタックトレースとともにクライアントに書き込まれます。

+ +
+

メモ: スタックトレースは実稼働環境に含まれていません。プロダクションモードで実行するには、環境変数 NODE_ENV を 'production' に設定する必要があります。

+
+ +
+

メモ: HTTP 404 およびその他の "エラー" ステータスコードはエラーとして扱われません。これらを処理したい場合は、ミドルウェア関数を追加して処理することができます。詳しくは FAQ を見てください。

+
+ +

詳しくはエラー処理 (Express ドキュメント) を参照してください。

+ +

データベースの使用

+ +

Express アプリケーションは、Node によってサポートされている任意のデータベースメカニズムを使用できます (Express 自体はデータベース管理のための特定の追加の動作や要件を定義していません)。PostgreSQL、MySQL、Redis、SQLite、MongoDB などを含む多くのオプションがあります。

+ +

これらを使用するには、まず NPM を使用してデータベースドライバをインストールする必要があります。たとえば、一般的な NoSQL MongoDB 用のドライバをインストールするには、次のコマンドを使用します。

+ +
$ npm install mongodb
+
+ +

データベース自体はローカルにインストールすることも、クラウドサーバーにインストールすることもできます。Express コードではドライバが必要で、データベースへの接続から、作成、参照、更新、削除 (CRUD) 操作を実行します。以下の (Express ドキュメントからの) 例は、MongoDB を使ってどのように「哺乳類の」レコードを見つけることができるかを示しています。

+ +
// これは mongodb バージョン 2.2.33 までの古いバージョンで動作します
+var MongoClient = require('mongodb').MongoClient;
+
+MongoClient.connect('mongodb://localhost:27017/animals', function(err, db) {
+  if (err) throw err;
+
+  db.collection('mammals').find().toArray(function (err, result) {
+    if (err) throw err;
+
+    console.log(result);
+  });
+});
+
+
+// mongodb バージョン 3.0 以上のためのコード
+let MongoClient = require('mongodb').MongoClient;
+MongoClient.connect('mongodb://localhost:27017/animals', function(err, client){
+   if(err) throw err;
+
+   let db = client.db('animals');
+   db.collection('mammals').find().toArray(function(err, result){
+     if(err) throw err;
+     console.log(result);
+     client.close();
+   });
+});
+ +

もう1つの一般的な方法は、Object Relational Mapper ( "ORM") を介して間接的にデータベースにアクセスすることです。このアプローチではデータを「オブジェクト」または「モデル」として定義し、ORM はそれらを基礎となるデータベース形式にマッピングします。このアプローチには、開発者としてデータベースのセマンティクスではなく JavaScript オブジェクトの観点から考え続けることができ、受信データの検証とチェックを実行するための明らかな場所があるという利点があります。データベースについての詳細は、後の記事で説明します。

+ +

詳しくはデータベース統合 (Express ドキュメント) を参照してください。

+ +

データのレンダリング (ビュー)

+ +

テンプレートエンジン (Express では「ビューエンジン」と呼ばれます) を使用すると、ページの生成時に埋められるデータのプレースホルダを使用して、テンプレート内の出力ドキュメントの構造を指定できます。テンプレートは HTML の作成によく使用されますが、他の種類の文書も作成できます。 Express はいくつかのテンプレートエンジンをサポートしています。ここでは、より人気の高いエンジンの便利な比較ができます。JavaScript テンプレートエンジンの比較:Jade、Moustache、Dustなど

+ +

次に示すように、アプリケーション設定コードで、使用するテンプレートエンジンと、Express が 'ビュー' および 'ビューエンジン' 設定を使用してテンプレートを探す場所を設定します (テンプレートライブラリを含むパッケージもインストールする必要があります!)

+ +
var express = require('express');
+var app = express();
+
+// ('views') テンプレートを含むディレクトリーを設定
+app.set('views', path.join(__dirname, 'views'));
+
+// 利用するビューエンジン、この場合は 'some_template_engine_name' を設定
+app.set('view engine', 'some_template_engine_name');
+ +

テンプレートの外観は使用するエンジンによって異なります。"title" および "message" という名前のデータ変数のプレースホルダを含む "index.<テンプレート拡張子>" という名前のテンプレートファイルがあると仮定すると、ルートハンドラ関数で Response.render() を呼び出して HTML レスポンスを作成し、送信することになります。

+ +
app.get('/', function(req, res) {
+  res.render('index', { title: 'About dogs', message: 'Dogs rock!' });
+});
+ +

詳しくは Express でのテンプレートエンジンの使用 (Express ドキュメント) を参照してください。

+ +

ファイル構造

+ +

Express は、構造や使用するコンポーネントに関しては何も想定していません。ルート、ビュー、静的ファイル、およびその他のアプリケーション固有のロジックは、任意のディレクトリー構造を持つ任意の数のファイルに存在できます。 Express アプリケーション全体を1つのファイルにまとめることは完全に可能ですが、通常は機能 (アカウント管理、ブログ、ディスカッション掲示板など) およびアーキテクチャ上の問題のドメイン (MVC アーキテクチャを使用している場合は、モデル、ビュー、コントローラーなど) に基づいてアプリケーションをファイルに分割します。

+ +

後のトピックでは、ウェブアプリケーションを作成するために簡単に拡張できるモジュール式のアプリケーションスケルトンを作成する Express Application Generator を使用します。

+ + + +

まとめ

+ +

おめでとうございます、Express/Node の旅の最初のステップを完了しました。これで Express と Node の主な利点と、Express アプリケーションの主要部分がどのように見えるか (ルート、ミドルウェア、エラー処理、およびテンプレートコード) をおおまかに理解できています。また、Express は指図しないフレームワークであるため、これらの部分をどのようにまとめるかやどのライブラリを使用するかは、ほとんどあなた次第です。

+ +

もちろん、Express は意図的に非常に軽量なウェブアプリケーションフレームワークであるため、その利点と可能性の多くはサードパーティのライブラリと機能からもたらされています。以下の記事でそれらをより詳しく見ていきます。次回の記事では、Node 開発環境のセットアップについて見ていきます。そうすれば、いくつかの Express コードが実際に動作しているところを見始めることができます。

+ +

関連情報

+ + + +
{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}
+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/mongoose/index.html b/files/ja/learn/server-side/express_nodejs/mongoose/index.html new file mode 100644 index 0000000000..e6eecb4496 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/mongoose/index.html @@ -0,0 +1,799 @@ +--- +title: 'Express チュートリアル Part 3: データベースの使用 (Mongoose を使用)' +slug: Learn/Server-side/Express_Nodejs/mongoose +translation_of: Learn/Server-side/Express_Nodejs/mongoose +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}
+ +

この記事ではデータベースと、それらを Node/Express アプリケーションで使用する方法について簡単に紹介します。続いて、Mongoose を使用して地域図書館 Web サイトへのデータベースアクセスを提供する方法を説明します。 オブジェクトスキーマとモデルの宣言方法、主なフィールドタイプ、および基本的な検証について説明します。また、モデルデータにアクセスするための主な方法についても簡単に説明します。

+ + + + + + + + + + + + +
前提条件:Express チュートリアル Part 2: スケルトン Web サイトの作成
目標:Mongoose を使用して独自のモデルを設計および作成できるようになる。
+ +

概要

+ +

図書館職員は本と借り手についての情報を保存するためにローカルライブラリ Web サイトを使いますが、図書館員は本をブラウズして検索し、利用可能なコピーがあるかどうかを調べ、そしてそれらを予約または借りるために使います。情報を効率的に保存および取得するために、データベースに保存します。

+ +

Express アプリケーションはさまざまなデータベースを使用できます。作成、読み取り、更新、削除 (CRUD) 操作を実行するために使用できるいくつかのアプローチがあります。 このチュートリアルではいくつかの利用可能なオプションの簡単な概要を説明し、次に選択された特定のメカニズムを詳細に表示します。

+ +

どのデータベースを使用できますか?

+ +

Express アプリは Node でサポートされている任意のデータベースを使用できます (Express 自体はデータベース管理のための特定の追加の動作や要件を定義していません)。 PostgreSQL、MySQL、Redis、SQLite、MongoDB など、多くの一般的なオプションがあります。

+ +

データベースを選択するときは、生産性/学習時間の曲線、パフォーマンス、複製/バックアップの容易さ、コスト、コミュニティサポートなどのことを考慮する必要があります。「最高の」データベースは1つもありませんが、ほとんどの一般的なソリューションは、ローカルライブラリのような中小規模のサイトでは十分条件を満たしているはずです。

+ +

オプションの詳細については、データベース統合 (Express ドキュメント) を参照してください。

+ +

データベースを利用するための最良の方法は何ですか?

+ +

データベースにインタラクティブにアプローチするには2つの方法があります。

+ + + +

SQL、またはデータベースでサポートされているクエリ言語を使用すると、最高のパフォーマンスが得られます。ODM は、変換コードを使用してオブジェクトとデータベース形式の間のマッピングを行うため、処理が遅くなることが多く、最も効率的なデータベースクエリが使用されない可能性があります (これは、ODM がさまざまなデータベースバックエンドをサポートしている場合に特に当てはまります。サポートされているデータベース機能に関して、さらに妥協する必要があります)。

+ +

ORM を使用する利点は、プログラマがデータベースのセマンティクスではなく JavaScript オブジェクトの観点から考え続けることができることです。これは、同じデータベースまたは異なる Web サイトで異なるデータベースを扱う必要がある場合に特に当てはまります。またデータの検証とチェックを実行するための明らかな場所を提供します。

+ +
+

Tip:  ODM/ORM を使用すると、多くの場合、開発と保守のコストが削減されます。ネイティブのクエリ言語に精通しているかパフォーマンスが最優先であるのでなければ、ODM の使用を積極的に検討するべきです。

+
+ +

どの ORM/ODM を使うべきですか?

+ +

NPM パッケージマネージャのサイトには、多数の ODM/ORM ソリューションがあります (サブセットの odm タグおよび orm タグを調べてください)。

+ +

執筆時点で一般的だったいくつかの解決策は、次のとおりです。

+ + + +

原則として、解決策を選択する際には、提供されている機能と "コミュニティ活動" (ダウンロード、コントリビュート、バグレポート、ドキュメントの品質など) の両方を考慮する必要があります。この記事を書いている時点では、Mongoose は最も人気のある ODM であり、データベースに MongoDB を使用している場合は妥当な選択です。

+ +

ローカルライブラリに Mongoose と MongoDB を使用する

+ +

ローカルライブラリの例 (およびこのトピックの残りの部分) では、Mongoose ODM を使用してライブラリデータにアクセスします。Mongoose は、ドキュメント指向のデータモデルを使用するオープンソースの NoSQL データベースである MongoDB のフロントエンドとして機能します。MongoDB データベースの "ドキュメント" の "コレクション" は、リレーショナルデータベースの "行" の "テーブル" に似ています

+ +

この ODM とデータベースの組み合わせは、Node コミュニティで非常に人気があります。これは、ドキュメントの保存とクエリのシステムが JSON に非常に似ているため、JavaScript 開発者にはよく知られているためです。

+ +
+

Tip: Mongoose を使用するために MongoDB を知っている必要はありませんが、Mongoose のドキュメントの一部は、MongoDB に慣れている方が使いやすく理解しやすいものです。

+
+ +

このチュートリアルの残りの部分では、ローカルライブラリ Web サイトの例の Mongoose スキーマとモデルを定義してアクセスする方法を示します。

+ +

ローカルライブラリモデルの設計

+ +

いきなりモデルのコーディングを始める前に、格納する必要があるデータと、さまざまなオブジェクト間の関係について検討することをお勧めします。

+ +

書籍に関する情報 (タイトル、概要、著者、ジャンル、ISBN) を保存する必要があること、および複数のコピーが利用可能であること (グローバルに一意の ID、利用状況など) があることを知っています。著者の名前だけではなく、著者に関するより多くの情報を格納する必要があるかもしれません。また、同じ名前または類似の名前を持つ著者が複数いる可能性があります。書籍のタイトル、著者、ジャンル、およびカテゴリに基づいて情報を並べ替えることができるようにします。

+ +

モデルを設計するときは、すべての "オブジェクト" (関連情報のグループ) ごとに別々のモデルを用意するのが合理的です。 この場合、明らかなオブジェクトは本、本のインスタンス、および作者です。

+ +

Web サイト自体に選択肢をハードコーディングするのではなく、モデルを使用して選択肢の選択肢 (たとえば選択肢のドロップダウンリストなど) を表すこともできます - すべてのオプションが事前にわかっていない場合や変更される可能性がある場合は、これをお勧めします。このタイプのモデルの明らかな候補は本のジャンルです (例:サイエンスフィクション、フランス詩など)。

+ +

モデルとフィールドを決めたら、それらの関係について考える必要があります。

+ +

そのことを念頭に置いて、以下の UML 関連図は、この場合に定義するモデルを (ボックスとして) 示しています。上記で説明したように、本のモデル (本の一般的な詳細)、本のインスタンス (システムで利用可能な本の特定の物理コピーのステータス)、および作成者のモデルを作成しました。また、値を動的に作成できるように、ジャンルのモデルを用意することにしました。BookInstance:status のモデルを使用しないことにしました - 許容値は変更しないと考えられるので、許容値をハードコードします。各ボックス内には、モデル名、フィールド名と型、そしてメソッドとその戻り型が表示されます。

+ +

この図には、モデル間の関係 (それらの多重度も含む) も示されています。多重度は、関係内に存在する可能性がある各モデルの番号 (最大および最小) を示す図上の番号です。たとえば、ボックス間の接続線は、BookGenre が関連していることを示しています。Book モデルに近い数字は、ジャンルに0個以上の Book がある必要があることを示しており、線のもう一方の端にあるGenre の隣の数字は、本に0個以上の関連するGenreがあることを示しています。

+ +
+

メモ: 下記の Mongoose 入門書で説明されているように、1つのモデルだけで documents/models 間の関係を定義するフィールドがあるほうがよいでしょう (他のモデルで関連する _id を検索することによって逆の関係を見つけることができます)。以下では、Book スキーマの Book/Genre と Book/Author の関係、および BookInstance スキーマの Book/BookInstance の関係を定義します。この選択は多少恣意的でした - 他のスキーマでも同じようにフィールドを持つことができました。

+
+ +

Mongoose Library Model  with correct cardinality

+ +
+

メモ: 次のセクションでは、モデルの定義方法と使用方法を説明する基本的な入門書を提供します。お読みになったところで、上の図の各モデルをどのように構築するかを検討してください。

+
+ +

Mongoose 入門書

+ +

このセクションでは、Mongoose を MongoDB データベースに接続する方法、スキーマとモデルを定義する方法、そして基本的なクエリを作成する方法の概要を説明します。

+ +
+

メモ: この入門書は、npm の Mongoose クイックスタート公式ドキュメントに "大きく影響を受けています"。

+
+ +

Mongoose と MongoDB のインストール

+ +

Mongoose は他の依存関係と同じようにあなたのプロジェクト (package.json) にインストールされます。つまり NPM を使用します。インストールするには、プロジェクトフォルダ内で次のコマンドを使用します。

+ +
npm install mongoose
+
+ +

Mongoose をインストールすると、MongoDB データベースドライバを含むすべての依存関係が追加されますが、MongoDB 自体はインストールされません。 MongoDB サーバをインストールする場合は、さまざまな OS 用のインストーラをここからダウンロードしてローカルにインストールできます。クラウドベースの MongoDB インスタンスを使用することもできます。

+ +
+

メモ: このチュートリアルでは、mLab クラウドベースのDatabase as a Service サンドボックス層として使用してデータベースを提供します。これは開発に適しており、オペレーティングシステムの "インストール" に依存しないため (database-as-a-service も本番データベースに使用することができる1つのアプローチです)、チュートリアルに適しています。

+
+ +

MongoDB への接続

+ +

MongooseはMongoDBデータベースへの接続を必要とします。以下のように、require() して mongoose.connect() でローカルにホストされているデータベースに接続することができます。

+ +
//Import the mongoose module
+var mongoose = require('mongoose');
+
+//Set up default mongoose connection
+var mongoDB = 'mongodb://127.0.0.1/my_database';
+mongoose.connect(mongoDB);
+// Get Mongoose to use the global promise library
+mongoose.Promise = global.Promise;
+//Get the default connection
+var db = mongoose.connection;
+
+//Bind connection to error event (to get notification of connection errors)
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

デフォルトの Connection オブジェクトは mongoose.connection で取得できます。接続されると、open イベントが Connection インスタンスで発生します。

+ +
+

Tip: 追加のコネクションを作成する必要がある場合は、mongoose.createConnection() を使用できます。 これは connect() と同じ形式のデータベース URI (ホスト、データベース、ポート、オプションなど) を取り、Connection オブジェクトを返します。

+
+ +

モデルの定義と作成

+ +

モデルは Schema インターフェイスを使用して定義されます。スキーマを使用すると、各ドキュメントに格納されているフィールドとその検証要件およびデフォルト値を定義できます。さらに、データ型や他のフィールドと同じように使用できるが実際にはデータベースに格納されていない仮想プロパティも扱いやすいように、静的メソッドおよびインスタンスヘルパーメソッドを定義できます。(もう少し後で説明します)。

+ +

その後、スキーマは mongoose.model() メソッドを使用してモデルに "コンパイル" されます。モデルを作成したら、それを使用して特定のタイプのオブジェクトを検索、作成、更新、および削除できます。

+ +
+

メモ: 各モデルは MongoDB データベース内のドキュメントのコレクションにマップされます。ドキュメントはモデル Schema で定義されたフィールド/スキーマタイプを含みます。

+
+ +

スキーマの定義

+ +

以下のコードは、単純なスキーマを定義する方法を示しています。最初に mongoose を require() し、次に Schema コンストラクタを使用して新しいスキーマインスタンスを作成し、コンストラクタの object パラメータで内部のさまざまなフィールドを定義します。

+ +
//Require Mongoose
+var mongoose = require('mongoose');
+
+//Define a schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string: String,
+  a_date: Date
+});
+
+ +

上記の場合、文字列と日付の2つのフィールドしかありません。次のセクションでは、他のフィールドタイプ、検証、その他の方法について説明します。

+ +

モデルを作成する

+ +

モデルは、mongoose.model() メソッドを使用してスキーマから作成されます。

+ +
// Define schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string: String,
+  a_date: Date
+});
+
+// Compile model from schema
+var SomeModel = mongoose.model('SomeModel', SomeModelSchema );
+ +

最初の引数はあなたのモデル用に作成されるコレクションの単数形の名前です (Mongoose は上記の SomeModel モデル用のデータベースコレクションを作成します)、そして2番目の引数はモデルの作成に使用したいスキーマです。

+ +
+

メモ: モデルクラスを定義したら、それらを使用してレコードを作成、更新、または削除し、クエリを実行してすべてのレコードまたは特定のレコードのサブセットを取得できます。これを行う方法をモデルの使用セクションで、そしてビューを作成するときに示します。

+
+ +

スキーマ型 (フィールド)

+ +

スキーマには任意の数のフィールドを含めることができます。各フィールドは MongoDB に格納されているドキュメント内のフィールドを表します。一般的なフィールド型の多くとその宣言方法を示すスキーマの例を以下に示します。

+ +
var schema = new Schema(
+{
+  name: String,
+  binary: Buffer,
+  living: Boolean,
+  updated: { type: Date, default: Date.now() },
+  age: { type: Number, min: 18, max: 65, required: true },
+  mixed: Schema.Types.Mixed,
+  _someId: Schema.Types.ObjectId,
+  array: [],
+  ofString: [String], // 他の型でも配列にすることができます。
+  nested: { stuff: { type: String, lowercase: true, trim: true } }
+})
+ +

ほとんどのスキーム型("type:"やフィールド名で記述されるもの)はその名のとおりです。例外は以下のようなものがあります:

+ + + +

このコードはフィールドを宣言する2つのやり方も示しています:

+ + + +

もっとオプションについて見たいならSchemaTypes (Mongoose docs)を見てみてください.

+ +

バリデーション

+ +

Mongooseはビルドインもしくはカスマイズしたバリデータや同期的もしくは非同期的なバリデータを提供しています。 バリデータはすべての場合において、許容範囲または値と検証失敗のエラーメッセージの両方を指定できます。

+ +

ビルドインのバリデータには:

+ + + +

以下の例(Mongooseドキュメントから少し変更しています)では、いくつかのバリデータタイプとエラーメッセージを指定する方法を示しています:

+ +

+    var breakfastSchema = new Schema({
+      eggs: {
+        type: Number,
+        min: [6, 'Too few eggs'],
+        max: 12,
+        required: [true, 'Why no eggs?']
+      },
+      drink: {
+        type: String,
+        enum: ['Coffee', 'Tea', 'Water',]
+      }
+    });
+
+ +

詳しくは Validation (Mongoose docs) を見てみてください。

+ +

Virtual properties

+ +

Virtual properties are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage. The example in the documentation constructs (and deconstructs) a full name virtual property from a first and last name field, which is easier and cleaner than constructing a full name every time one is used in a template.

+ +
+

Note: We will use a virtual property in the library to define a unique URL for each model record using a path and the record's _id value.

+
+ +

For more information see Virtuals (Mongoose documentation).

+ +

Methods and query helpers

+ +

A schema can also have instance methods, static methods, and query helpers. The instance and static methods are similar, but with the obvious difference that an instance method is associated with a particular record and has access to the current object. Query helpers allow you to extend mongoose's chainable query builder API (for example, allowing you to add a query "byName" in addition to the find(), findOne() and findById() methods).

+ +

Using models

+ +

Once you've created a schema you can use it to create models. The model represents a collection of documents in the database that you can search, while the model's instances represent individual documents that you can save and retrieve.

+ +

We provide a brief overview below. For more information see: Models (Mongoose docs).

+ +

Creating and modifying documents

+ +

To create a record you can define an instance of the model and then call save(). The examples below assume SomeModel is a model (with a single field "name") that we have created from our schema.

+ +
// Create an instance of model SomeModel
+var awesome_instance = new SomeModel({ name: 'awesome' });
+
+// Save the new model instance, passing a callback
+awesome_instance.save(function (err) {
+  if (err) return handleError(err);
+  // saved!
+});
+
+ +

Creation of records (along with updates, deletes, and queries) are asynchronous operations — you supply a callback that is called when the operation completes. The API uses the error-first argument convention, so the first argument for the callback will always be an error value (or null). If the API returns some result, this will be provided as the second argument.

+ +

You can also use create() to define the model instance at the same time as you save it. The callback will return an error for the first argument and the newly-created model instance for the second argument.

+ +
SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) {
+  if (err) return handleError(err);
+  // saved!
+});
+ +

Every model has an associated connection (this will be the default connection when you use mongoose.model()). You create a new connection and call .model() on it to create the documents on a different database.

+ +

You can access the fields in this new record using the dot syntax, and change the values. You have to call save() or update() to store modified values back to the database.

+ +
// Access model field values using dot notation
+console.log(awesome_instance.name); //should log 'also_awesome'
+
+// Change record by modifying the fields, then calling save().
+awesome_instance.name="New cool name";
+awesome_instance.save(function (err) {
+   if (err) return handleError(err); // saved!
+   });
+
+ +

Searching for records

+ +

You can search for records using query methods, specifying the query conditions as a JSON document. The code fragment below shows how you might find all athletes in a database that play tennis, returning just the fields for athlete name and age. Here we just specify one matching field (sport) but you can add more criteria, specify regular expression criteria, or remove the conditions altogether to return all athletes.

+ +
var Athlete = mongoose.model('Athlete', yourSchema);
+
+// find all athletes who play tennis, selecting the 'name' and 'age' fields
+Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) {
+  if (err) return handleError(err);
+  // 'athletes' contains the list of athletes that match the criteria.
+})
+ +

If you specify a callback, as shown above, the query will execute immediately. The callback will be invoked when the search completes.

+ +
+

Note: All callbacks in Mongoose use the pattern callback(error, result). If an error occurs executing the query, the error parameter will contain an error document and result will be null. If the query is successful, the error parameter will be null, and the result will be populated with the results of the query.

+
+ +

If you don't specify a callback then the API will return a variable of type Query. You can use this query object to build up your query and then execute it (with a callback) later using the exec() method.

+ +
// find all athletes that play tennis
+var query = Athlete.find({ 'sport': 'Tennis' });
+
+// selecting the 'name' and 'age' fields
+query.select('name age');
+
+// limit our results to 5 items
+query.limit(5);
+
+// sort by age
+query.sort({ age: -1 });
+
+// execute the query at a later time
+query.exec(function (err, athletes) {
+  if (err) return handleError(err);
+  // athletes contains an ordered list of 5 athletes who play Tennis
+})
+ +

Above we've defined the query conditions in the find() method. We can also do this using a where() function, and we can chain all the parts of our query together using the dot operator (.) rather than adding them separately. The code fragment below is the same as our query above, with an additional condition for the age.

+ +
Athlete.
+  find().
+  where('sport').equals('Tennis').
+  where('age').gt(17).lt(50).  //Additional where query
+  limit(5).
+  sort({ age: -1 }).
+  select('name age').
+  exec(callback); // where callback is the name of our callback function.
+ +

The find() method gets all matching records, but often you just want to get one match. The following methods query for a single record:

+ + + +
+

Note: There is also a count() method that you can use to get the number of items that match conditions. This is useful if you want to perform a count without actually fetching the records.

+
+ +

There is a lot more you can do with queries. For more information see: Queries (Mongoose docs).

+ + + +

You can create references from one document/model instance to another using the ObjectId schema field, or from one document to many using an array of ObjectIds. The field stores the id of the related model. If you need the actual content of the associated document, you can use the populate() method in a query to replace the id with the actual data.

+ +

For example, the following schema defines authors and stories. Each author can have multiple stories, which we represent as an array of ObjectId. Each story can have a single author. The "ref" (highlighted in bold below) tells the schema which model can be assigned to this field.

+ +
var mongoose = require('mongoose')
+  , Schema = mongoose.Schema
+
+var authorSchema = Schema({
+  name    : String,
+  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
+});
+
+var storySchema = Schema({
+  author : { type: Schema.Types.ObjectId, ref: 'Author' },
+  title    : String
+});
+
+var Story  = mongoose.model('Story', storySchema);
+var Author = mongoose.model('Author', authorSchema);
+ +

We can save our references to the related document by assigning the _id value. Below we create an author, then a story, and assign the author id to our stories author field.

+ +
var bob = new Author({ name: 'Bob Smith' });
+
+bob.save(function (err) {
+  if (err) return handleError(err);
+
+  //Bob now exists, so lets create a story
+  var story = new Story({
+    title: "Bob goes sledding",
+    author: bob._id    // assign the _id from the our author Bob. This ID is created by default!
+  });
+
+  story.save(function (err) {
+    if (err) return handleError(err);
+    // Bob now has his story
+  });
+});
+ +

Our story document now has an author referenced by the author document's ID. In order to get the author information in the story results we use populate(), as shown below.

+ +
Story
+.findOne({ title: 'Bob goes sledding' })
+.populate('author') //This populates the author id with actual author information!
+.exec(function (err, story) {
+  if (err) return handleError(err);
+  console.log('The author is %s', story.author.name);
+  // prints "The author is Bob Smith"
+});
+ +
+

Note: Astute readers will have noted that we added an author to our story, but we didn't do anything to add our story to our author's stories array. How then can we get all stories by a particular author? One way would be to add our author to the stories array, but this would result in us having two places where the information relating authors and stories needs to be maintained.

+ +

A better way is to get the _id of our author, then use find() to search for this in the author field across all stories.

+ +
Story
+.find({ author : bob._id })
+.exec(function (err, stories) {
+  if (err) return handleError(err);
+  // returns all stories that have Bob's id as their author.
+});
+
+
+ +

This is almost everything you need to know about working with related items for this tutorial. For more detailed information see Population (Mongoose docs).

+ +

One schema/model per file

+ +

While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its own module (file), exporting the method to create the model. This is shown below:

+ +
// File: ./models/somemodel.js
+
+//Require Mongoose
+var mongoose = require('mongoose');
+
+//Define a schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string          : String,
+  a_date            : Date,
+});
+
+//Export function to create "SomeModel" model class
+module.exports = mongoose.model('SomeModel', SomeModelSchema );
+ +

You can then require and use the model immediately in other files. Below we show how you might use it to get all instances of the model.

+ +
//Create a SomeModel model just by requiring the module
+var SomeModel = require('../models/somemodel')
+
+// Use the SomeModel object (model) to find all SomeModel records
+SomeModel.find(callback_function);
+ +

Setting up the MongoDB database

+ +

Now that we understand something of what Mongoose can do and how we want to design our models, it's time to start work on the LocalLibrary website. The very first thing we want to do is set up a MongoDb database that we can use to store our library data.

+ +

For this tutorial, we're going to use mLab's free cloud-hosted "sandbox" database. This database tier is not considered suitable for production websites because it has no redundancy, but it is great for development and prototyping. We're using it here because it is free and easy to set up, and because mLab is a popular database as a service vendor that you might reasonably choose for your production database (other popular choices at the time of writing include Compose, ScaleGrid and MongoDB Atlas).

+ +
+

Note: If you prefer you can set up a MongoDb database locally by downloading and installing the appropriate binaries for your system. The rest of the instructions in this article would be similar, except for the database URL you would specify when connecting.

+
+ +

You will first need to create an account with mLab (this is free, and just requires that you enter basic contact details and acknowledge their terms of service). 

+ +

After logging in, you'll be taken to the home screen:

+ +
    +
  1. Click Create New in the MongoDB Deployments section.
  2. +
  3. This will open the Cloud Provider Selection screen.
    + MLab - screen for new deployment
    + +
      +
    • Select the SANDBOX (Free) plan from the Plan Type section. 
    • +
    • Select any provider from the Cloud Provider section. Different providers offer different regions (displayed below the selected plan type).
    • +
    • Click the Continue button.
    • +
    +
  4. +
  5. This will open the Select Region screen. +

    Select new region screen

    + +
      +
    • +

      Select the region closest to you and then Continue.

      +
    • +
    +
  6. +
  7. +

    This will open the Final Details screen.
    + New deployment database name

    + +
      +
    • +

      Enter the name for the new database as local_library and then select Continue.

      +
    • +
    +
  8. +
  9. +

    This will open the Order Confirmation screen.
    + Order confirmation screen

    + +
      +
    • +

      Click Submit Order to create the database.

      +
    • +
    +
  10. +
  11. +

    You will be returned to the home screen. Click on the new database you just created to open its details screen. As you can see the database has no collections (data).
    + mLab - Database details screen
    +  
    + The URL that you need to use to access your database is displayed on the form above (shown for this database circled above). In order to use this you need to create a database user that you can specify in the URL.

    +
  12. +
  13. Click the Users tab and select the Add database user button.
  14. +
  15. Enter a username and password (twice), and then press Create. Do not select Make read only.
    +
  16. +
+ +

You have now created the database, and have an URL (with username and password) that can be used to access it. This will look something like: mongodb://your_user_namer:your_password@ds119748.mlab.com:19748/local_library.

+ +

Install Mongoose

+ +

Open a command prompt and navigate to the directory where you created your skeleton Local Library website. Enter the following command to install Mongoose (and its dependencies) and add it to your package.json file, unless you have already done so when reading the Mongoose Primer above.

+ +
npm install mongoose
+
+ +

Connect to MongoDB

+ +

Open /app.js (in the root of your project) and copy the following text below where you declare the Express application object (after the line var app = express();). Replace the database url string ('insert_your_database_url_here') with the location URL representing your own database (i.e. using the information from mLab).

+ +
//Set up mongoose connection
+var mongoose = require('mongoose');
+var mongoDB = 'insert_your_database_url_here';
+mongoose.connect(mongoDB);
+mongoose.Promise = global.Promise;
+var db = mongoose.connection;
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

As discussed in the Mongoose primer above, this code creates the default connection to the database and binds to the error event (so that errors will be printed to the console). 

+ +

Defining the LocalLibrary Schema

+ +

We will define a separate module for each model, as discussed above. Start by creating a folder for our models in the project root (/models) and then create separate files for each of the models:

+ +
/express-locallibrary-tutorial  //the project root
+  /models
+    author.js
+    book.js
+    bookinstance.js
+    genre.js
+
+ +

Author model

+ +

Copy the Author schema code shown below and paste it into your ./models/author.js file. The scheme defines an author has having String SchemaTypes for the first and family names, that are required and have a maximum of 100 characters, and Date fields for the date of birth and death.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var AuthorSchema = new Schema(
+  {
+    first_name: {type: String, required: true, max: 100},
+    family_name: {type: String, required: true, max: 100},
+    date_of_birth: {type: Date},
+    date_of_death: {type: Date},
+  }
+);
+
+// Virtual for author's full name
+AuthorSchema
+.virtual('name')
+.get(function () {
+  return this.family_name + ', ' + this.first_name;
+});
+
+// Virtual for author's lifespan
+AuthorSchema
+.virtual('lifespan')
+.get(function () {
+  return (this.date_of_death.getYear() - this.date_of_birth.getYear()).toString();
+});
+
+// Virtual for author's URL
+AuthorSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/author/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('Author', AuthorSchema);
+
+
+ +

We've also declared a virtual for the AuthorSchema named "url" that returns the absolute URL required to get a particular instance of the model — we'll use the property in our templates whenever we need to get a link to a particular author.

+ +
+

Note: Declaring our URLs as a virtual in the schema is a good idea because then the URL for an item only ever needs to be changed in one place.
+ At this point, a link using this URL wouldn't work, because we haven't got any routes handling code for individual model instances. We'll set those up in a later article!

+
+ +

At the end of the module, we export the model.

+ +

Book model

+ +

Copy the Book schema code shown below and paste it into your ./models/book.js file. Most of this is similar to the author model — we've declared a schema with a number of string fields and a virtual for getting the URL of specific book records, and we've exported the model.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookSchema = new Schema(
+  {
+    title: {type: String, required: true},
+    author: {type: Schema.Types.ObjectId, ref: 'Author', required: true},
+    summary: {type: String, required: true},
+    isbn: {type: String, required: true},
+    genre: [{type: Schema.Types.ObjectId, ref: 'Genre'}]
+  }
+);
+
+// Virtual for book's URL
+BookSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/book/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('Book', BookSchema);
+
+ +

The main difference here is that we've created two references to other models:

+ + + +

BookInstance model

+ +

Finally, copy the BookInstance schema code shown below and paste it into your ./models/bookinstance.js file. The BookInstance represents a specific copy of a book that someone might borrow and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookInstanceSchema = new Schema(
+  {
+    book: { type: Schema.Types.ObjectId, ref: 'Book', required: true }, //reference to the associated book
+    imprint: {type: String, required: true},
+    status: {type: String, required: true, enum: ['Available', 'Maintenance', 'Loaned', 'Reserved'], default: 'Maintenance'},
+    due_back: {type: Date, default: Date.now}
+  }
+);
+
+// Virtual for bookinstance's URL
+BookInstanceSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/bookinstance/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('BookInstance', BookInstanceSchema);
+ +

The new things we show here are the field options:

+ + + +

Everything else should be familiar from our previous schema.

+ +

Genre model - challenge!

+ +

Open your ./models/genre.js file and create a schema for storing genres (the category of book, e.g. whether it is fiction or non-fiction, romance or military history, etc).

+ +

The definition will be very similar to the other models:

+ + + +

Testing — create some items

+ +

That's it. We now have all models for the site set up!

+ +

In order to test the models (and to create some example books and other items that we can use in our next articles) we'll now run an independent script to create items of each type:

+ +
    +
  1. Download (or otherwise create) the file populatedb.js inside your express-locallibrary-tutorial directory (in the same level as package.json). + +
    +

    Note: You don't need to know how populatedb.js works; it just adds sample data into the database.

    +
    +
  2. +
  3. Enter the following commands in the project root to install the async module that is required by the script (we'll discuss this in later tutorials, ) +
    npm install async
    +
  4. +
  5. Run the script using node in your command prompt, passing in the URL of your MongoDB database (the same one you replaced the insert_your_database_url_here placeholder with, inside app.js earlier): +
    node populatedb <your mongodb url>​​​​
    +
  6. +
  7. The script should run through to completion, displaying items as it creates them in the terminal.
  8. +
+ +
+

Tip: Go to your database on mLab. You should now be able to drill down into individual collections of Books, Authors, Genres and BookInstances, and check out individual documents.

+
+ +

まとめ

+ +

この記事では、Node/Express 上のデータベースと ORM について、また Mongoose のスキーマとモデルの定義方法について多くのことを学びました。次に、この情報を使用して、ローカルライブラリ Web サイト用の BookBookInstanceAuthor、および Genre を設計および実装しました。

+ +

最後に、(スタンドアロンスクリプトを使用して) 多数のインスタンスを作成することによってモデルをテストしました。次の記事では、これらのオブジェクトを表示するためのページの作成について見ていきます。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/routes/index.html b/files/ja/learn/server-side/express_nodejs/routes/index.html new file mode 100644 index 0000000000..bb3e21898b --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/routes/index.html @@ -0,0 +1,640 @@ +--- +title: 'Express チュートリアル Part 4: ルートとコントローラ' +slug: Learn/Server-side/Express_Nodejs/routes +translation_of: Learn/Server-side/Express_Nodejs/routes +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs")}}
+ +

このチュートリアルでは、地域図書館 Web サイトで最終的に必要となるすべてのリソースエンドポイントに対して、"ダミー" ハンドラ関数を使用してルート (URL 処理コード) を設定します。完成すると、ルート処理コードのためのモジュール構造が得られます。これは、次の記事の実際のハンドラ関数で拡張できます。Express を使ってモジュラールートを作成する方法についても、非常によく理解しています。

+ + + + + + + + + + + + +
前提条件Express/Node のイントロダクションを読んでください。 これまでのチュートリアルのトピック (Express チュートリアル Part 3: データベースを使う (Mongoose を使用)を含む) を完了してください。
目標:単純なルートを作成する方法を理解する。すべての URL エンドポイントを設定します。
+ +

Overview

+ +

In the last tutorial article we defined Mongoose models to interact with the database, and used a (standalone) script to create some initial library records. We can now write the code to present that information to users. The first thing we need to do is determine what information we want to be able to display in our pages, and then define appropriate URLs for returning those resources. Then we're going to need to create the routes (URL handlers) and views (templates) to display those pages.

+ +

The diagram below is provided as a reminder of the main flow of data and things that need to be implemented when handling an HTTP request/response. In addition to the views and routes the diagram shows "controllers" — functions that separate out the code to route requests from the code that actually processes requests.

+ +

As we've already created the models, the main things we'll need to create are:

+ + + +

+ +

Ultimately we might have pages to show lists and detail information for books, genres, authors and bookinstances, along with pages to create, update, and delete records. That's a lot to document in one article. Therefore most of this article will concentrate on setting up our routes and controllers to return "dummy" content. We'll extend the controller methods in our subsequent articles to work with model data.

+ +

The first section below provides a brief "primer" on how to use the Express Router middleware. We'll then use that knowledge in the following sections when we set up the LocalLibrary routes.

+ +

Routes primer

+ +

A route is a section of Express code that associates an HTTP verb (GET, POST, PUT, DELETE, etc.), an URL path/pattern, and a function that is called to handle that pattern.

+ +

There are several ways to create routes. For this tutorial we're going to use the express.Router middleware as it allows us to group the route handlers for a particular part of a site together and access them using a common route-prefix. We'll keep all our library-related routes in a "catalog" module, and, if we add routes for handling user accounts or other functions, we can keep them grouped separately.

+ +
+

Note: We discussed Express application routes briefly in our Express Introduction > Creating route handlers. Other than providing better support for modularization (as discussed in the first subsection below), using Router is very similar to defining routes directly on the Express application object.

+
+ +

The rest of this section provides an overview of how the Router can be used to define the routes.

+ +

Defining and using separate route modules

+ +

The code below provides a concrete example of how we can create a route module and then use it in an Express application.

+ +

First we create routes for a wiki in a module named wiki.js. The code first imports the Express application object, uses it to get a Router object and then adds a couple of routes to it using the get() method. Last of all the module exports the Router object.

+ +
// wiki.js - Wiki route module.
+
+var express = require('express');
+var router = express.Router();
+
+// Home page route.
+router.get('/', function (req, res) {
+  res.send('Wiki home page');
+})
+
+// About page route.
+router.get('/about', function (req, res) {
+  res.send('About this wiki');
+})
+
+module.exports = router;
+
+
+ +
+

Note: Above we are defining our route handler callbacks directly in the router functions. In the LocalLibrary we'll define these callbacks in a separate controller module.

+
+ +

To use the router module in our main app file we first require() the route module (wiki.js). We then call use() on the Express application to add the Router to the middleware handling path, specifying an URL path of 'wiki'.

+ +
var wiki = require('./wiki.js');
+// ...
+app.use('/wiki', wiki);
+ +

The two routes defined in our wiki route module are then accessible from /wiki/ and /wiki/about/.

+ +

Route functions

+ +

Our module above defines a couple of typical route functions. The "about" route (reproduced below) is defined using the Router.get() method, which responds only to HTTP GET requests. The first argument to this method is the URL path while the second is a callback function that will be invoked if an HTTP GET request with the path is received.

+ +
router.get('/about', function (req, res) {
+  res.send('About this wiki');
+})
+
+ +

The callback takes three arguments (usually named as shown: req, res, next), that will contain the HTTP Request object, HTTP response, and the next function in the middleware chain.

+ +
+

Note: Router functions are Express middleware, which means that they must either complete (respond to) the request or call the next function in the chain. In the case above we complete the request using send(), so the next argument is not used (and we choose not to specify it).

+ +

The router function above takes a single callback, but you can specify as many callback arguments as you want, or an array of callback functions. Each function is part of the middleware chain, and will be called in the order it is added to the chain (unless a preceding function completes the request).

+
+ +

The callback function here calls send() on the response to return the string "About this wiki" when we receive a GET request with the path ('/about'). There are a number of other response methods for ending the request/response cycle. For example, you could call res.json() to send a JSON response or res.sendFile() to send a file. The response method that we'll be using most often as we build up the library is render(), which creates and returns HTML files using templates and data—we'll talk a lot more about that in a later article!

+ +

HTTP verbs

+ +

The example routes above use the Router.get() method to respond to HTTP GET requests with a certain path.

+ +

The Router also provides route methods for all the other HTTP verbs, that are mostly used in exactly the same way: post(), put(), delete(), options(), trace(), copy(), lock(), mkcol(), move(), purge(), propfind(), proppatch(), unlock(), report(), mkactivity(), checkout(), merge(), m-search(), notify(), subscribe(), unsubscribe(), patch(), search(), and connect().

+ +

For example, the code below behaves just like the previous /about route, but only responds to HTTP POST requests.

+ +
router.post('/about', function (req, res) {
+  res.send('About this wiki');
+})
+ +

Route paths

+ +

The route paths define the endpoints at which requests can be made. The examples we've seen so far have just been strings, and are used exactly as written: '/', '/about', '/book', '/any-random.path'.

+ +

Route paths can also be string patterns. String patterns use a subset of regular expression syntax to define patterns of endpoints that will be matched. The subset is listed below (note that the hyphen (-) and the dot (.) are interpreted literally by string-based paths):

+ + + +

The route paths can also be JavaScript regular expressions. For example, the route path below will match catfish and dogfish, but not catflap, catfishhead, and so on. Note that the path for a regular expression uses regular expression syntax (it is not a quoted string as in the previous cases).

+ +
app.get(/.*fish$/, function (req, res) {
+  ...
+})
+ +
+

Note: Most of our routes for the LocalLibrary will simply use strings and not string patterns and regular expressions. We'll also use route parameters as discussed in the next section.

+
+ +

Route parameters

+ +

Route parameters are named URL segments used to capture the values specified at their position in the URL. The named segments are prefixed with a colon and then the name (e.g. /:your_parameter_name/. The captured values are stored in the req.params object using the parameter names as keys (e.g. req.params.your_parameter_name).

+ +

So for example, consider a URL encoded to contain information about users and books: http://localhost:3000/users/34/books/8989. We can extract this information as shown below, with the userId and bookId path parameters:

+ +
app.get('/users/:userId/books/:bookId', function (req, res) {
+  // Access userId via: req.params.userId
+  // Access bookId via: req.params.bookId
+  res.send(req.params);
+})
+
+ +

The names of route parameters must be made up of “word characters” (A-Z, a-z, 0-9, and _).

+ +
+

Note: The URL /book/create will be matched by a route like /book/:bookId (which will extract a "bookId" value of 'create'). The first route that matches an incoming URL will be used, so if you want to process /book/create URLs separately, their route handler must be defined before your /book/:bookId route.

+
+ +

That's all you need to get started with routes - if needed you can find more information in the Express docs: Basic routing and Routing guide. The following sections show how we'll set up our routes and controllers for the LocalLibrary.

+ +

Routes needed for the LocalLibrary

+ +

The URLs that we're ultimately going to need for our pages are listed below, where object is replaced by the name of each of our models (book, bookinstance, genre, author), objects is the plural of object, and id is the unique instance field (_id) that is given to each Mongoose model instance by default.

+ + + +

The first home page and list pages don't encode any additional information. While the results returned will depend on the model type and the content in the database, the queries run to get the information will always be the same (similarly the code run for object creation will always be similar).

+ +

By contrast the other URLs are used to act on a specific document/model instance—these encode the identity of the item in the URL (shown as <id> above). We'll use path parameters to extract the encoded information and pass it to the route handler (and in a later article we'll use this to dynamically determine what information to get from the database). By encoding the information in our URL we only need one route for every resource of a particular type (e.g. one route to handle the display of every single book item).

+ +
+

Note: Express allows you to construct your URLs any way you like — you can encode information in the body of the URL as shown above or use URL GET parameters (e.g. /book/?id=6). Whichever approach you use, the URLs should be kept clean, logical and readable (check out the W3C advice here).

+
+ +

Next we create our route handler callback functions and route code for all the above URLs.

+ +

Create the route-handler callback functions

+ +

Before we define our routes, we'll first create all the dummy/skeleton callback functions that they will invoke. The callbacks will be stored in separate "controller" modules for Books, BookInstances, Genres, and Authors (you can use any file/module structure, but this seems an appropriate granularity for this project).

+ +

Start by creating a folder for our controllers in the project root (/controllers) and then create separate controller files/modules for handling each of the models:

+ +
/express-locallibrary-tutorial  //the project root
+  /controllers
+    authorController.js
+    bookController.js
+    bookinstanceController.js
+    genreController.js
+ +

Author controller

+ +

Open the /controllers/authorController.js file and type in the following code:

+ +
var Author = require('../models/author');
+
+// Display list of all Authors.
+exports.author_list = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author list');
+};
+
+// Display detail page for a specific Author.
+exports.author_detail = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author detail: ' + req.params.id);
+};
+
+// Display Author create form on GET.
+exports.author_create_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author create GET');
+};
+
+// Handle Author create on POST.
+exports.author_create_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author create POST');
+};
+
+// Display Author delete form on GET.
+exports.author_delete_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author delete GET');
+};
+
+// Handle Author delete on POST.
+exports.author_delete_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author delete POST');
+};
+
+// Display Author update form on GET.
+exports.author_update_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author update GET');
+};
+
+// Handle Author update on POST.
+exports.author_update_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Author update POST');
+};
+
+ +

The module first requires the model that we'll later be using to access and update our data. It then exports functions for each of the URLs we wish to handle (the create, update and delete operations use forms, and hence also have additional methods for handling form post requests — we'll discuss those methods in the "forms article" later on).

+ +

All the functions have the standard form of an Express middleware function, with arguments for the request, response, and the next function to be called if the method does not complete the request cycle (in all these cases it does!). The methods simply return a string indicating that the associated page has not yet been created. If a controller function is expected to receive path parameters, these are output in the message string (see req.params.id above).

+ +

BookInstance controller

+ +

Open the /controllers/bookinstanceController.js file and copy in the following code (this follows an identical pattern to the Author controller module):

+ +
var BookInstance = require('../models/bookinstance');
+
+// Display list of all BookInstances.
+exports.bookinstance_list = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance list');
+};
+
+// Display detail page for a specific BookInstance.
+exports.bookinstance_detail = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance detail: ' + req.params.id);
+};
+
+// Display BookInstance create form on GET.
+exports.bookinstance_create_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance create GET');
+};
+
+// Handle BookInstance create on POST.
+exports.bookinstance_create_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance create POST');
+};
+
+// Display BookInstance delete form on GET.
+exports.bookinstance_delete_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance delete GET');
+};
+
+// Handle BookInstance delete on POST.
+exports.bookinstance_delete_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance delete POST');
+};
+
+// Display BookInstance update form on GET.
+exports.bookinstance_update_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance update GET');
+};
+
+// Handle bookinstance update on POST.
+exports.bookinstance_update_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: BookInstance update POST');
+};
+
+ +

Genre controller

+ +

Open the /controllers/genreController.js file and copy in the following text (this follows an identical pattern to the Author and BookInstance files):

+ +
var Genre = require('../models/genre');
+
+// Display list of all Genre.
+exports.genre_list = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre list');
+};
+
+// Display detail page for a specific Genre.
+exports.genre_detail = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre detail: ' + req.params.id);
+};
+
+// Display Genre create form on GET.
+exports.genre_create_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre create GET');
+};
+
+// Handle Genre create on POST.
+exports.genre_create_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre create POST');
+};
+
+// Display Genre delete form on GET.
+exports.genre_delete_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre delete GET');
+};
+
+// Handle Genre delete on POST.
+exports.genre_delete_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre delete POST');
+};
+
+// Display Genre update form on GET.
+exports.genre_update_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre update GET');
+};
+
+// Handle Genre update on POST.
+exports.genre_update_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Genre update POST');
+};
+
+ +

Book controller

+ +

Open the /controllers/bookController.js file and copy in the following code. This follows the same pattern as the other controller modules, but additionally has an index() function for displaying the site welcome page:

+ +
var Book = require('../models/book');
+
+exports.index = function(req, res) {
+    res.send('NOT IMPLEMENTED: Site Home Page');
+};
+
+// Display list of all books.
+exports.book_list = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book list');
+};
+
+// Display detail page for a specific book.
+exports.book_detail = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book detail: ' + req.params.id);
+};
+
+// Display book create form on GET.
+exports.book_create_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book create GET');
+};
+
+// Handle book create on POST.
+exports.book_create_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book create POST');
+};
+
+// Display book delete form on GET.
+exports.book_delete_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book delete GET');
+};
+
+// Handle book delete on POST.
+exports.book_delete_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book delete POST');
+};
+
+// Display book update form on GET.
+exports.book_update_get = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book update GET');
+};
+
+// Handle book update on POST.
+exports.book_update_post = function(req, res) {
+    res.send('NOT IMPLEMENTED: Book update POST');
+};
+
+ +

Create the catalog route module

+ +

Next we create routes for all the URLs needed by the LocalLibrary website, which will call the controller functions we defined in the previous section.

+ +

The skeleton already has a ./routes folder containing routes for the index and users. Create another route file — catalog.js — inside this folder, as shown.

+ +
/express-locallibrary-tutorial //the project root
+  /routes
+    index.js
+    users.js
+    catalog.js
+ +

Open /routes/catalog.js and copy in the code below:

+ +
var express = require('express');
+var router = express.Router();
+
+// Require controller modules.
+var book_controller = require('../controllers/bookController');
+var author_controller = require('../controllers/authorController');
+var genre_controller = require('../controllers/genreController');
+var book_instance_controller = require('../controllers/bookinstanceController');
+
+/// BOOK ROUTES ///
+
+// GET catalog home page.
+router.get('/', book_controller.index);
+
+// GET request for creating a Book. NOTE This must come before routes that display Book (uses id).
+router.get('/book/create', book_controller.book_create_get);
+
+// POST request for creating Book.
+router.post('/book/create', book_controller.book_create_post);
+
+// GET request to delete Book.
+router.get('/book/:id/delete', book_controller.book_delete_get);
+
+// POST request to delete Book.
+router.post('/book/:id/delete', book_controller.book_delete_post);
+
+// GET request to update Book.
+router.get('/book/:id/update', book_controller.book_update_get);
+
+// POST request to update Book.
+router.post('/book/:id/update', book_controller.book_update_post);
+
+// GET request for one Book.
+router.get('/book/:id', book_controller.book_detail);
+
+// GET request for list of all Book items.
+router.get('/books', book_controller.book_list);
+
+/// AUTHOR ROUTES ///
+
+// GET request for creating Author. NOTE This must come before route for id (i.e. display author).
+router.get('/author/create', author_controller.author_create_get);
+
+// POST request for creating Author.
+router.post('/author/create', author_controller.author_create_post);
+
+// GET request to delete Author.
+router.get('/author/:id/delete', author_controller.author_delete_get);
+
+// POST request to delete Author.
+router.post('/author/:id/delete', author_controller.author_delete_post);
+
+// GET request to update Author.
+router.get('/author/:id/update', author_controller.author_update_get);
+
+// POST request to update Author.
+router.post('/author/:id/update', author_controller.author_update_post);
+
+// GET request for one Author.
+router.get('/author/:id', author_controller.author_detail);
+
+// GET request for list of all Authors.
+router.get('/authors', author_controller.author_list);
+
+/// GENRE ROUTES ///
+
+// GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id).
+router.get('/genre/create', genre_controller.genre_create_get);
+
+//POST request for creating Genre.
+router.post('/genre/create', genre_controller.genre_create_post);
+
+// GET request to delete Genre.
+router.get('/genre/:id/delete', genre_controller.genre_delete_get);
+
+// POST request to delete Genre.
+router.post('/genre/:id/delete', genre_controller.genre_delete_post);
+
+// GET request to update Genre.
+router.get('/genre/:id/update', genre_controller.genre_update_get);
+
+// POST request to update Genre.
+router.post('/genre/:id/update', genre_controller.genre_update_post);
+
+// GET request for one Genre.
+router.get('/genre/:id', genre_controller.genre_detail);
+
+// GET request for list of all Genre.
+router.get('/genres', genre_controller.genre_list);
+
+/// BOOKINSTANCE ROUTES ///
+
+// GET request for creating a BookInstance. NOTE This must come before route that displays BookInstance (uses id).
+router.get('/bookinstance/create', book_instance_controller.bookinstance_create_get);
+
+// POST request for creating BookInstance.
+router.post('/bookinstance/create', book_instance_controller.bookinstance_create_post);
+
+// GET request to delete BookInstance.
+router.get('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_get);
+
+// POST request to delete BookInstance.
+router.post('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_post);
+
+// GET request to update BookInstance.
+router.get('/bookinstance/:id/update', book_instance_controller.bookinstance_update_get);
+
+// POST request to update BookInstance.
+router.post('/bookinstance/:id/update', book_instance_controller.bookinstance_update_post);
+
+// GET request for one BookInstance.
+router.get('/bookinstance/:id', book_instance_controller.bookinstance_detail);
+
+// GET request for list of all BookInstance.
+router.get('/bookinstances', book_instance_controller.bookinstance_list);
+
+module.exports = router;
+
+ +

The module requires Express and then uses it to create a Router object. The routes are all set up on the router, which is then exported.

+ +

The routes are defined either using .get() or .post() methods on the router object. All the paths are defined using strings (we don't use string patterns or regular expressions). Routes that act on some specific resource (e.g. book) use path parameters to get the object id from the URL.

+ +

The handler functions are all imported from the controller modules we created in the previous section.

+ +

Update the index route module

+ +

We've set up all our new routes, but we still have a route to the original page. Let's instead redirect this to the new index page that we've created at the path '/catalog'.

+ +

Open /routes/index.js and replace the existing route with the function below.

+ +
// GET home page.
+router.get('/', function(req, res) {
+  res.redirect('/catalog');
+});
+ +
+

Note: This is our first use of the redirect() response method. This redirects to the specified page, by default sending HTTP status code "302 Found". You can change the status code returned if needed, and supply either absolute or relative paths.

+
+ +

Update app.js

+ +

The last step is to add the routes to the middleware chain. We do this in app.js.

+ +

Open app.js and require the catalog route below the other routes (add the third line shown below, underneath the other two):

+ +
var indexRouter = require('./routes/index');
+var usersRouter = require('./routes/users');
+var catalogRouter = require('./routes/catalog');  //Import routes for "catalog" area of site
+ +

Next, add the catalog route to the middleware stack below the other routes (add the third line shown below, underneath the other two):

+ +
app.use('/', indexRouter);
+app.use('/users', usersRouter);
+app.use('/catalog', catalogRouter);  // Add catalog routes to middleware chain.
+ +
+

Note: We have added our catalog module at a path '/catalog'. This is prepended to all of the paths defined in the catalog module. So for example, to access a list of books, the URL will be: /catalog/books/.

+
+ +

That's it. We should now have routes and skeleton functions enabled for all the URLs that we will eventually support on the LocalLibrary website.

+ +

Testing the routes

+ +

To test the routes, first start the website using your usual approach

+ + + +

Then navigate to a number of LocalLibrary URLs, and verify that you don't get an error page (HTTP 404). A small set of URLs are listed below for your convenience:

+ + + +

まとめ

+ +

これでサイトのすべてのルートを、後の記事で完全な実装を追加することができるダミーのコントローラ関数もあわせて作成しました。その過程で、Express ルートについての多くの基本的な情報、そしてルートとコントローラを構築するためのいくつかのアプローチを学びました。

+ +

次の記事では、モデルに格納されているビュー (テンプレート) と情報を使用して、サイト用の適切なウェルカムページを作成します。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/skeleton_website/index.html b/files/ja/learn/server-side/express_nodejs/skeleton_website/index.html new file mode 100644 index 0000000000..5b0acfecd2 --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/skeleton_website/index.html @@ -0,0 +1,512 @@ +--- +title: 'Express チュートリアル Part 2: スケルトン Web サイトの作成' +slug: Learn/Server-side/Express_Nodejs/skeleton_website +tags: + - CodingScripting + - Express + - Node + - イントロダクション + - サーバサイド + - 初心者 + - 学習 + - 開発環境 +translation_of: Learn/Server-side/Express_Nodejs/skeleton_website +--- +
{{LearnSidebar}}
+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}

+ +

この Express チュートリアルの2回目の記事では、どのようにして "スケルトン" Web サイトプロジェクトを作成し、サイト固有のルート、テンプレート/ビュー、およびデータベース呼び出しを追加するかを説明します。

+ + + + + + + + + + + + +
前提条件:Node 開発環境を設定します。Express チュートリアルを確認してください。
目標:Express Application Generator を使用して独自の新しい Web サイトプロジェクトを開始できるようにする。
+ +

概要

+ +

この記事では Express Application Generator ツールを使用して "スケルトン" Web サイトを作成する方法を説明します。このツールには、サイト固有のルート、ビュー/テンプレート、およびデータベース呼び出しを追加できます。この場合は、このツールを使用してローカルライブラリ Web サイト用のフレームワークを作成し、後でそのサイトに必要な他のすべてのコードを追加します。プロセスは非常に単純で、必要に応じてサイトのテンプレートエンジンと CSS ジェネレータを指定して、新しいプロジェクト名を指定してコマンドラインでジェネレータを呼び出すだけです。

+ +

次のセクションでは、アプリケーションジェネレータを呼び出す方法を示し、さまざまな ビュー/CSS オプションについて簡単に説明します。また、スケルトン Web サイトの構造についても説明します。最後に、Web サイトを実行してそれが機能することを確認する方法を紹介します。

+ +
+

メモ: Express アプリケーションジェネレータは、Express アプリケーション用の唯一のジェネレータというわけではありません。また、生成されたプロジェクトはファイルやディレクトリを構造化する唯一実行可能な方法というわけではありません。しかしながら、生成されたサイトは、拡張と理解が容易なモジュール構造を持っています。最小限の Express アプリケーションについては、Hello world の例 (Express ドキュメント) を参照してください。

+
+ +

アプリケーションジェネレータを使用する

+ +

Node 開発環境の設定の一部として、ジェネレータをすでにインストールしているはずです。念のため、NPM パッケージマネージャを使用して、サイト全体にジェネレータツールをインストールします。

+ +
npm install express-generator -g
+ +

ジェネレータにはいくつかのオプションがあり、それらは --help (または -h) コマンドを使用してコマンドラインで表示できます。

+ +
> express --help
+
+  Usage: express [options] [dir]
+
+  Options:
+
+    -h, --help           output usage information
+        --version        output the version number
+    -e, --ejs            add ejs engine support
+        --pug            add pug engine support
+        --hbs            add handlebars engine support
+    -H, --hogan          add hogan.js engine support
+    -v, --view <engine>  add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
+    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
+        --git            add .gitignore
+    -f, --force          force on non-empty directory
+
+ +

Jade ビューエンジンとプレーン CSS を使用して、express を指定するだけで現在のディレクトリ内にプロジェクトを作成できます (ディレクトリ名を指定すると、プロジェクトはその名前のサブフォルダに作成されます)。

+ +
express
+ +

--view を使用してビュー (テンプレート) エンジンを選択したり、--css を使用して CSS 生成エンジンを選択したりすることもできます。

+ +
+

メモ: テンプレートエンジンを選択するためのその他のオプション (--hogan--ejs--hbs など) は推奨されません。--view (または -v)を使用してください。

+
+ +

どのビューエンジンを使うべきですか?

+ +

Express Application Generator を使用すると、EJSHbsPug (Jade)、TwigVash など、一般的なビュー/テンプレートエンジンを多数設定できます。ただし、ビューオプションを指定しない場合はデフォルトで Jade が選択されます。 Express 自体は、一般的な他のテンプレート言語の多くをサポートすることができます。

+ +
+

メモ: ジェネレータでサポートされていないテンプレートエンジンを使用したい場合は、Express でテンプレートエンジンを使用する (Express ドキュメント) およびターゲットビューエンジンのドキュメントを参照してください。

+
+ +

一般的に、あなたが必要とするすべての機能を提供し、あなたがより早く生産的になることを可能にするテンプレートエンジンを選ぶべきです ー もしくは言い換えれば、同じ方法で、他のコンポーネントを選択するということです。テンプレートエンジンを比較する際に考慮すべき点がいくつかあります。

+ + + +
+

Tip: インターネット上には、さまざまなオプションを比較するのに役立つ多くのリソースがあります。

+
+ +

このプロジェクトでは、Pug テンプレートエンジン (これは最近名前が変更された Jade エンジンです) を使用します。これは最も一般的な Express/JavaScript テンプレート言語の1つで、ジェネレータによってそのままサポートされているためです。

+ +

どの CSS スタイルシートエンジンを使うべきですか?

+ +

Express Application Generator を使用すると、最も一般的なCSSスタイルシートエンジン (LESSSASSCompassStylus) を使用するように構成されたプロジェクトを作成できます。

+ +
+

メモ: CSS にはいくつかの制限があり、特定のタスクを困難にします。CSS スタイルシートエンジンを使用すると、CSS を定義するためのより強力な構文を使用してから、ブラウザで使用するためにその定義を通常の CSS にコンパイルできます。

+
+ +

テンプレートエンジンと同様に、チームを最も生産的にすることができるスタイルシートエンジンを使用する必要があります。このプロジェクトでは、CSS 要件が他のものを使用することを正当化するのに十分に複雑ではないため、通常のCSS (デフォルト) を使用します。

+ +

どのデータベースを使うべきですか?

+ +

生成されたコードはデータベースを一切使用しません。 Express アプリケーションは、Node によってサポートされている任意のデータベースメカニズムを使用できます (Express自体はデータベース管理のための特定の追加の動作や要件を定義していません)。

+ +

データベースと統合する方法については、後の記事で説明します。

+ +

プロジェクトを作成する

+ +

これから作成するサンプルのローカルライブラリアプリでは、Pug テンプレートライブラリを使用し、CSS スタイルシートエンジンを使用しないで、express-locallibrary-tutorial という名前のプロジェクトを作成します。

+ +

まず、プロジェクトを作成する場所に移動し、次に示すようにコマンドプロンプトで Express Application Generator を実行します。

+ +
express express-locallibrary-tutorial --view=pug
+
+ +

ジェネレータはプロジェクトのファイルを作成 (そして一覧表示) します。

+ +
   create : express-locallibrary-tutorial
+   create : express-locallibrary-tutorial/package.json
+   create : express-locallibrary-tutorial/app.js
+   create : express-locallibrary-tutorial/public/images
+   create : express-locallibrary-tutorial/public
+   create : express-locallibrary-tutorial/public/stylesheets
+   create : express-locallibrary-tutorial/public/stylesheets/style.css
+   create : express-locallibrary-tutorial/public/javascripts
+   create : express-locallibrary-tutorial/routes
+   create : express-locallibrary-tutorial/routes/index.js
+   create : express-locallibrary-tutorial/routes/users.js
+   create : express-locallibrary-tutorial/views
+   create : express-locallibrary-tutorial/views/index.pug
+   create : express-locallibrary-tutorial/views/layout.pug
+   create : express-locallibrary-tutorial/views/error.pug
+   create : express-locallibrary-tutorial/bin
+   create : express-locallibrary-tutorial/bin/www
+
+   install dependencies:
+     > cd express-locallibrary-tutorial && npm install
+
+   run the app:
+     > SET DEBUG=express-locallibrary-tutorial:* & npm start
+ +

出力の最後に、ジェネレータは依存関係をどのようにインストールするか (package.json ファイルにリストされているとおり)、次にアプリケーションを実行する方法についての指示を提供します (上記の手順は Windows 用です。Linux/ macOS では若干異なります)。

+ +

スケルトン Web サイトを実行する

+ +

これで、完全なスケルトンプロジェクトが完成しました。 ウェブサイトは実際にはそれほど多くは行っていませんが、それがどのように機能するかを示すために実行する価値があります。

+ +
    +
  1. まず、依存関係をインストールします (install コマンドはプロジェクトの package.json ファイルにリストされているすべての依存関係パッケージを取得します) + +
    cd express-locallibrary-tutorial
    +npm install
    +
  2. +
  3. その後、アプリケーションを実行します +
      +
    • Windows では、次のコマンドを使用します +
      SET DEBUG=express-locallibrary-tutorial:* & npm start
      +
    • +
    • macOS または Linux では、次のコマンドを使用します +
      DEBUG=express-locallibrary-tutorial:* npm start
      +
      +
    • +
    +
  4. +
  5. その後、ブラウザに http://localhost:3000/ をロードしてアプリにアクセスします
  6. +
+ +

次のようなブラウザページが表示されるはずです。

+ +

Browser for default Express app generator website

+ +

自分自身で localhost:3000 に提供している、動作する Express アプリケーションがあります。

+ +
+

メモ: npm start コマンドを使用してアプリを起動することもできます。示されているように DEBUG 変数を指定すると、コンソールロギング/デバッグが有効になります。たとえば、上記のページにアクセスすると、次のようなデバッグ出力が表示されます。

+ +
>SET DEBUG=express-locallibrary-tutorial:* & npm start
+
+> express-locallibrary-tutorial@0.0.0 start D:\express-locallibrary-tutorial
+> node ./bin/www
+
+  express-locallibrary-tutorial:server Listening on port 3000 +0ms
+GET / 200 288.474 ms - 170
+GET /stylesheets/style.css 200 5.799 ms - 111
+GET /favicon.ico 404 34.134 ms - 1335
+
+ +

ファイルの変更時にサーバの再起動を有効にする

+ +

Express Web サイトに加えた変更は、現在のサーバを再起動するまで表示されません。変更を加えるたびにサーバを停止して再起動する必要があることはすぐに非常に苛立たしいものになるため、必要に応じてサーバの再起動を自動化することに時間をかける価値があります。

+ +

この目的のための最も簡単なツールの1つが nodemon です。 これは通常 "ツール" としてグローバルにインストールされますが、ここでは開発者の依存関係としてローカルにインストールして使用するので、プロジェクトを操作する開発者はアプリケーションをインストールするときに自動的に取得されます。スケルトンプロジェクトのルートディレクトリで次のコマンドを使用します。

+ +
npm install --save-dev nodemon
+ +

プロジェクトの package.json ファイルだけでなく、自分のマシンにグローバルに nodemon をインストールする場合は、次のようにします。

+ +
npm install -g nodemon
+ +

プロジェクトの package.json ファイルを開くと、この依存関係を持つ新しいセクションが表示されます。

+ +
  "devDependencies": {
+    "nodemon": "^1.14.11"
+  }
+
+ +

このツールはグローバルにはインストールされていないので (パスに追加しない限り) コマンドラインから起動することはできませんが、NPM はインストールされているパッケージをすべて知っているので、NPM スクリプトから呼び出すことができます。package.json の scripts セクションを見つけます。最初は "start" で始まる1行が含まれています。その行の末尾にカンマを入れて、以下に見られる "devstart" 行を追加することによってそれを更新します。

+ +
  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+
+ +

devstart コマンドを指定して、以前とほぼ同じ方法でサーバーを起動することができます。

+ + + +
+

メモ: プロジェクト内のファイルを編集した場合は、サーバが再起動します (またはコマンドプロンプトで rs と入力していつでも再起動できます)。あなたはまだページを更新するためにブラウザを再読み込みする必要があるでしょう。

+ +

"start" は実際には名前付きスクリプトにマップされた NPM コマンドなので、ここでは単に npm start ではなく  "npm run <scriptname>" を呼び出す必要があります。起動スクリプトのコマンドを置き換えることもできますが、開発中は nodemon を使用するだけなので、新しいスクリプトコマンドを作成するのが理にかなっています。

+
+ +

生成されたプロジェクト

+ +

今作成したプロジェクトを見てみましょう。

+ +

ディレクトリ構造

+ +

生成されたプロジェクトは、依存関係をインストールしたので、次のようなファイル構造になります (ファイルは "/" が前に付いていない項目です)。package.json ファイルは、アプリケーションの依存関係とその他の情報を定義します。また、アプリケーションのエントリポイントである JavaScript ファイル /bin/www を呼び出す起動スクリプトも定義されています。これにより、アプリケーションのエラー処理がいくつか設定され、その後 app.js が読み込まれて残りの作業が行われます。 アプリのルートは routes/ ディレクトリの下の別々のモジュールに格納されています。 テンプレートは /views ディレクトリの下に格納されています。

+ +
/express-locallibrary-tutorial
+    app.js
+    /bin
+        www
+    package.json
+    /node_modules
+        [about 4,500 subdirectories and files]
+    /public
+        /images
+        /javascripts
+        /stylesheets
+            style.css
+    /routes
+        index.js
+        users.js
+    /views
+        error.pug
+        index.pug
+        layout.pug
+
+
+ +

次のセクションでは、ファイルについてもう少し詳しく説明します。

+ +

package.json

+ +

package.json ファイルは、アプリケーションの依存関係とその他の情報を定義します。

+ +
{
+  "name": "express-locallibrary-tutorial",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+  "dependencies": {
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.16.2",
+    "morgan": "~1.9.0",
+    "pug": "~2.0.0-rc.4",
+    "serve-favicon": "~2.4.5"
+  },
+  "devDependencies": {
+    "nodemon": "^1.14.11"
+  }
+}
+
+ +

依存関係には、express パッケージと選択したビューエンジン (pug) 用のパッケージが含まれます。さらに、多くの Web アプリケーションで役立つ次のパッケージがあります。

+ + + +

scripts セクションは "start" スクリプトを定義します。これは、npm start を呼び出してサーバを起動するときに呼び出すスクリプトです。スクリプトの定義から、これは実際に JavaScript ファイル ./bin/www with node を開始することがわかります。また、"devstart" スクリプトも定義しています。これは、代わりに npm run devstart を呼び出すときに呼び出されます。これは同じ ./bin/www ファイルを開始しますが、node ではなく nodemon を使用します。

+ +
  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+
+ +

www ファイル

+ +

ファイル /bin/www がアプリケーションのエントリポイントです。 これが最初に行うことは、express() アプリケーションオブジェクトを設定して返す "本物の" アプリケーションエントリポイント (プロジェクトルート内の app.js) であるrequire() です。

+ +
#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var app = require('../app');
+
+ +
+

メモ: require() は、現在のファイルにモジュールをインポートするために使われるグローバル Node 関数です。 ここでは相対パスを使用し、オプションの (.js) ファイル拡張子を省略して app.js モジュールを指定します。

+
+ +

このファイルのコードの残りの部分では、特定のポート (環境変数で定義されているか、変数が定義されていない場合は 3000 で定義されている) に設定された app を使用してNode HTTP サーバをセットアップします。 今のところ、コードについて他に何も知る必要はありません (このファイル内のすべてが "定型句" です) が、興味があればお気軽にレビューしてください。

+ +

app.js

+ +

このファイルは、express アプリケーションオブジェクト (慣例では app という名前) を作成し、さまざまな設定とミドルウェアを使用してアプリケーションを設定してから、モジュールからアプリケーションをエクスポートします。以下のコードは、アプリオブジェクトを作成およびエクスポートするファイルの一部だけを示しています。

+ +
var express = require('express');
+var app = express();
+...
+module.exports = app;
+
+ +

上記の www エントリポイントファイルに戻ると、このファイルがインポートされたときに呼び出し元に渡されるのは、この module.exports オブジェクトです。

+ +

app.js ファイルを詳しく見ていきましょう。まず、NPM を使用してアプリケーション用に以前にダウンロードしたexpress、serve-favicon、morgan、cookie-parser など、require() を使用していくつかの便利な Node ライブラリをファイルにインポートします。path は、ファイルとディレクトリのパスを解析するためのコア Node ライブラリです。

+ +
var express = require('express');
+var path = require('path');
+var favicon = require('serve-favicon');
+var logger = require('morgan');
+var cookieParser = require('cookie-parser');
+
+ +

それからroutesディレクトリから require() モジュールを呼び出します。これらのモジュール/ファイルには、関連する "ルート" (URL パス) の特定のセットを処理するためのコードが含まれています。たとえばライブラリ内のすべての本をリストするためにスケルトンアプリケーションを拡張するときは、本関連のルートを処理するための新しいファイルを追加します。

+ +
var indexRouter = require('./routes/index');
+var usersRouter = require('./routes/users');
+
+ +
+

メモ: この時点で、モジュールをインポートしたばかりです。 実際にはまだそのルートを使用していません (これはファイルの少し下まで行われます)。

+
+ +

次に、インポートした Express モジュールを使ってアプリオブジェクトを作成し、それを使ってビュー (テンプレート) エンジンを設定します。エンジンの設定には2つの部分があります。まず、 'views' の値を設定して、テンプレートが保存されるフォルダを指定します (この場合はサブフォルダの /views)。それから 'view engine' の値を設定してテンプレートライブラリ (この場合は "pug") を指定します。

+ +
var app = express();
+
+// view engine setup
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'pug');
+
+ +

次の一連の関数は app.use() を呼び出してミドルウェアライブラリをリクエスト処理チェーンに追加します。以前インポートしたサードパーティのライブラリに加えて、Express がプロジェクトルートの /public ディレクトリにあるすべての静的ファイルを処理するようにするために、express.static ミドルウェアを使用します。

+ +
// uncomment after placing your favicon in /public
+//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
+app.use(logger('dev'));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use(express.static(path.join(__dirname, 'public')));
+
+ +

他のすべてのミドルウェアがセットアップされたので、(以前にインポートした) ルート処理コードをリクエスト処理チェーンに追加します。 インポートされたコードは、サイトのさまざまな部分に特定のルートを定義します。

+ +
app.use('/', indexRouter);
+app.use('/users', usersRouter);
+
+ +
+

メモ: 上記で指定されたパス ('/' と '/users') は、インポートされたファイルで定義されているルートの接頭辞として扱われます。たとえば、インポートされたユーザーモジュールが /profile のルートを定義している場合は、/users/profile でそのルートにアクセスします。 ルートの詳細については後の記事で説明します。

+
+ +

ファイルの最後のミドルウェアは、エラーと HTTP 404 レスポンス用のハンドラメソッドを追加します。

+ +
// catch 404 and forward to error handler
+app.use(function(req, res, next) {
+  var err = new Error('Not Found');
+  err.status = 404;
+  next(err);
+});
+
+// error handler
+app.use(function(err, req, res, next) {
+  // set locals, only providing error in development
+  res.locals.message = err.message;
+  res.locals.error = req.app.get('env') === 'development' ? err : {};
+
+  // render the error page
+  res.status(err.status || 500);
+  res.render('error');
+});
+
+ +

Express アプリケーションオブジェクト (app) が完全に設定されました。最後のステップはそれをモジュールのエクスポートに追加することです (これは /bin/www によってインポートされることを可能にするものです)。

+ +
module.exports = app;
+ +

ルート

+ +

ルートファイル /routes/users.js を以下に示します (ルートファイルは同様の構造を共有しているので、index.js も表示する必要はありません)。まず、express モジュールをロードし、それを使って express.Router オブジェクトを取得します。それからそのオブジェクトのルートを指定し、最後にモジュールからルーターをエクスポートします (これがファイルが app.js にインポートされることを可能にするものです)。

+ +
var express = require('express');
+var router = express.Router();
+
+/* GET users listing. */
+router.get('/', function(req, res, next) {
+  res.send('respond with a resource');
+});
+
+module.exports = router;
+
+ +

このルートは、正しいパターンの HTTP GET リクエストが検出されたときに必ず呼び出されるコールバックを定義します。一致パターンは、モジュールのインポート時に指定された経路 ('/users') と、このファイルで定義されているもの ('/') です。 つまり、このルートは /users/ の URL が受信されたときに使用されます。

+ +
+

Tip: これを試すには、node を使用してサーバを実行し、ブラウザの URL (http://localhost:3000/users/) にアクセスしてください。「リソースで応答してください」というメッセージが表示されます。

+
+ +

上記の関心事の1つは、コールバック関数が3番目の引数 'next' を持ち、したがって単純なルートコールバックではなくミドルウェア関数であることです。このコードでは現在 next 引数を使用していませんが、'/' ルートパスに複数のルートハンドラを追加したい場合、将来的には役に立つかもしれません。

+ +

ビュー (テンプレート)

+ +

ビュー (テンプレート) は /views ディレクトリ (app.js で指定されている) に保存され、ファイル拡張子 .pug が与えられます。Response.render() メソッドは、オブジェクトに渡された名前付き変数の値とともに指定されたテンプレートをレンダリングし、その結果をレスポンスとして送信するために使用されます。以下の /routes/index.js のコードでは、テンプレート変数 "title" を渡した "index" テンプレートを使用して、そのルートがどのようにレスポンスをレンダリングするかを確認できます。

+ +
/* GET home page. */
+router.get('/', function(req, res) {
+  res.render('index', { title: 'Express' });
+});
+
+ +

上記のルートに対応するテンプレートを以下に示します(index.pug)。構文については後で詳しく説明します。今のところ知る必要があるのは、(変数 'Express' を持つ) title変数がテンプレートの指定された場所に挿入されることだけです。

+ +
extends layout
+
+block content
+  h1= title
+  p Welcome to #{title}
+
+ +

自分自身で挑戦

+ +

/routes/users.js に新しいルートを作成し、URL /users/cool/ に "You're so cool" というテキストを表示します。 サーバーを実行し、ブラウザで http://localhost:3000/users/cool/ にアクセスしてテストしてください。

+ + + +

まとめ

+ +

これで、ローカルライブラリ用のスケルトン Web サイトプロジェクトを作成し、それが Node を使用して実行されることを確認しました。最も重要なのは、プロジェクトの構造も理解しているので、ローカルライブラリのルートとビューを追加するために変更を加える必要がある場所をよく理解していることです。

+ +

次に、図書館の Web サイトとして機能するようにスケルトンを変更します。

+ +

あわせて参照

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/ja/learn/server-side/express_nodejs/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..9e4dc43e1e --- /dev/null +++ b/files/ja/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -0,0 +1,98 @@ +--- +title: 'Express チュートリアル: 地域図書館の Web サイト' +slug: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +tags: + - Beginner + - CodingScripting + - Express + - Intro + - Learn + - Node + - Tutorial + - nodejs + - イントロダクション + - サーバサイド + - 初心者 + - 学習 +translation_of: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}
+ +

実用的なチュートリアルシリーズの最初の記事では、これから学ぶことについて説明します。そして、私たちがこれから取り組んでいき、その後の記事で進化していく「地域図書館」のサンプルウェブサイトの概要を説明します。

+ + + + + + + + + + + + +
前提条件:Express のイントロダクションを読んでください。以下の記事では、Node 開発環境を設定する必要もあります。
目標:このチュートリアルで使用されているサンプルアプリケーションを紹介し、どのトピックがカバーされるのかを読者が理解できるようにします。
+ +

概要

+ +

MDN "Local Library" Express (Node) チュートリアルへようこそ。このチュートリアルでは、地域図書館の目録を管理するために使用される可能性があるウェブサイトを開発します。

+ +

この一連のチュートリアル記事では、次のことを行います。

+ + + +

あなたはすでにこれらのトピックのいくつかについて学び、他のものについても簡単に触れました。チュートリアルシリーズの最後までに、簡単な Express アプリケーションを自分で開発するのに十分な知識があるはずです。

+ +

LocalLibrary ウェブサイト

+ +

LocalLibrary は、この一連のチュートリアルの過程で作成および進化するウェブサイトの名前です。ご想像のとおり、この ウェブサイトの目的は利用できる書籍を閲覧したり自分のアカウントを管理したりできる、地元の小さな図書館用のオンライン目録を提供することです。

+ +

この例は慎重に選択されています。必要なだけ詳細を表示することも、ほとんどすべての Express 機能を見せるために使用することもできるためです。さらに重要なことに、それはどんなウェブサイトでも必要とする機能性へのガイド付きの道筋を提供することができます:

+ + + +

これは非常に拡張可能な例ですが、LocalLibrary と呼ばれる理由があります。私たちは Express をすぐに使い始めるための最小限の情報を示すことを望んでいます。その結果、私たちは本に関する情報、本のコピー、作者、その他の重要な情報を保存します。ただし、図書館が貸し出す可能性のある他のアイテムに関する情報を保存したり、複数の図書館サイトやその他の "大きな図書館" 機能をサポートするために必要なインフラストラクチャを提供することはしません。

+ +

私は立ち往生しています、どこでソースを入手できますか?

+ +

チュートリアルを進めていくうちに、適切なコードスニペットを各ポイントにコピーして貼り付けることができます。また、他のコードも (ある程度の手引きを付けて) 自身で拡張することを望んでいます。

+ +

すべてのコードスニペットをコピーして貼り付けるのではなく、それらを入力してみてください。次回同様のコードを書くときに、コードに慣れ親しんでいることになるので、長期的に役に立ちます。

+ +

あなたが立ち往生したならば、Github のここで ウェブサイトの完全に開発されたバージョンを見つけることができます。

+ +
+

メモ: この文書でテストされた Node、Express、および他のモジュールの特定のバージョンは、プロジェクト package.json にリストされています。

+
+ +

まとめ

+ +

LocalLIbrary ウェブサイトと、これから学ぶことについて少し知りました。今度は私たちの例を含むスケルトンプロジェクトの作成を開始します。

+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}

+ +

このモジュールの中

+ + diff --git a/files/ja/learn/server-side/first_steps/client-server_overview/index.html b/files/ja/learn/server-side/first_steps/client-server_overview/index.html new file mode 100644 index 0000000000..a99e34eff0 --- /dev/null +++ b/files/ja/learn/server-side/first_steps/client-server_overview/index.html @@ -0,0 +1,329 @@ +--- +title: クライアント - サーバの概要 +slug: Learn/Server-side/First_steps/Client-Server_overview +tags: + - Beginner + - CodingScripting + - イントロダクション + - ガイド + - サーバ + - サーバサイドプログラミング + - 学習 +translation_of: Learn/Server-side/First_steps/Client-Server_overview +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}
+ +

サーバサイドプログラミングの目的と潜在的な利点を知ったので、サーバがブラウザーから "動的リクエスト" を受け取ったときに起こることを詳細に検討します。ほとんどの Web サイトのサーバサイドコードは同様の方法でリクエストとレスポンスを処理するので、これは自身のコードの大部分を書くときに何が必要かを理解するのに役立ちます。

+ + + + + + + + + + + + +
前提条件基本的なコンピュータリテラシー。Web サーバの基本的な理解。
目的動的な Web サイトにおけるクライアントとサーバのやりとり、特にサーバサイドのコードで実行する必要がある操作を理解する。
+ +

私たちはまだコードを書くために使う Web フレームワークを選択していないので、議論には本当のコードはありません! ただし、どのプログラミング言語または Web フレームワークを選択したかに関係なく、記述された動作はサーバ側のコードで実装する必要があるため、この説明は依然として非常に重要です。

+ +

Web サーバと HTTP (入門書)

+ +

Web ブラウザは、HyperText Transfer Protocol (HTTP) を使用して Web サーバと通信します。Web ページのリンクをクリックしたり、フォームを送信したり、検索を実行したりすると、ブラウザは HTTP リクエストをサーバに送信します。

+ +

このリクエストに含まれるもの:

+ + + +

Web サーバはクライアントリクエストメッセージを待ち、メッセージが到着したときにそれらを処理し、HTTP レスポンスメッセージで Web ブラウザにレスポンスします。レスポンスには、リクエストが成功したかどうかを示す HTTP レスポンスステータスコード (例: 成功した場合は "200 OK"、リソースが見つからない場合は "404 Not Found"、ユーザがリソースを見ることを許可されていない場合は "403 Forbidden"など) が含まれます。GET リクエストに対する成功したレスポンスの本文には、リクエストされたリソースが含まれます。

+ +

HTML ページが返されると、Web ブラウザによってレンダリングされます。 処理の一部として、ブラウザは他のリソースへのリンクを発見することができ (例えば HTML ページは通常 JavaScript と CSS ページを参照します)、これらのファイルをダウンロードするために別々の HTTP リクエストを送信します。

+ +

静的および動的 Web サイト (以降のセクションで説明) は、まったく同じ通信プロトコル/パターンを使用しています。

+ +

GET リクエスト/レスポンス 例

+ +

リンクをクリックするか (検索エンジンホームページのように) サイトを検索することで簡単な GET リクエストをすることができます。たとえば、MDNで「クライアント - サーバの概要」という用語を検索したときに送信される HTTP リクエストは、次のようになります (メッセージの一部はあなたのブラウザや設定に依存するので、同一にはなりません)。

+ +
+

HTTP メッセージのフォーマットは「Web 標準」(RFC7230) で定義されています。このレベルの詳細を知る必要はありませんが、少なくとも今、これら全てがどこから来たのかを知っています!

+
+ +

リクエスト

+ +

リクエストの各行にはそれに関する情報が含まれています。 最初の部分はヘッダーと呼ばれ、HTML head に HTML 文書に関する有用な情報が含まれるのと同じで、リクエストに関する有用な情報が含まれます (ただし、実際のコンテンツ自体は含まれません)。

+ +
GET https://developer.mozilla.org/en-US/search?q=client+server+overview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev HTTP/1.1
+Host: developer.mozilla.org
+Connection: keep-alive
+Pragma: no-cache
+Cache-Control: no-cache
+Upgrade-Insecure-Requests: 1
+User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+Referer: https://developer.mozilla.org/en-US/
+Accept-Encoding: gzip, deflate, sdch, br
+Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
+Accept-Language: en-US,en;q=0.8,es;q=0.6
+Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _gat=1; _ga=GA1.2.1688886003.1471911953; ffo=true
+
+ +

1行目と2行目には、上記で説明したほとんどの情報が含まれています。

+ + + +

最後の行にはクライアントサイドの Cookie に関する情報が含まれています。この場合、Cookie にはセッションを管理するための ID (Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...) が含まれています。

+ +

残りの行には、使用されているブラウザとそれが処理できるレスポンスの種類に関する情報が含まれています。たとえば、次のようになります。

+ + + +

HTTP リクエストもボディを持つことができますが、この場合は空です。

+ +

レスポンス

+ +

このリクエストに対するレスポンスの最初の部分を以下に示します。ヘッダーには、次のような情報が含まれています。

+ + + +

メッセージの最後に body があります。これにはリクエストによって返された実際の HTML が含まれています。

+ +
HTTP/1.1 200 OK
+Server: Apache
+X-Backend-Server: developer1.webapp.scl3.mozilla.com
+Vary: Accept,Cookie, Accept-Encoding
+Content-Type: text/html; charset=utf-8
+Date: Wed, 07 Sep 2016 00:11:31 GMT
+Keep-Alive: timeout=5, max=999
+Connection: Keep-Alive
+X-Frame-Options: DENY
+Allow: GET
+X-Cache-Info: caching
+Content-Length: 41823
+
+
+
+<!DOCTYPE html>
+<html lang="en-US" dir="ltr" class="redesign no-js"  data-ffo-opensanslight=false data-ffo-opensans=false >
+<head prefix="og: http://ogp.me/ns#">
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=Edge">
+  <script>(function(d) { d.className = d.className.replace(/\bno-js/, ''); })(document.documentElement);</script>
+  ...
+ +

レスポンスヘッダの残りの部分には、レスポンス (たとえば、いつ生成されたか)、サーバ、およびブラウザがページを処理する方法についての情報が含まれます (たとえば、X-Frame-Options: DENY 行は、このページを別のサイトの {{htmlelement("iframe")}} に埋め込むことを許可しないようにブラウザに指示します)。

+ +

POST リクエスト/レスポンス 例

+ +

HTTP POST は、サーバに保存する情報を含むフォームを送信したときに作成されます。

+ +

リクエスト

+ +

以下のテキストは、ユーザがこのサイトに新しいプロファイルの詳細を送信したときに行われる HTTP リクエストを示しています。最初の行はこのリクエストを POST として識別しますが、リクエストのフォーマットは前述の GET リクエストの例とほぼ同じです。

+ +
POST https://developer.mozilla.org/en-US/profiles/hamishwillee/edit HTTP/1.1
+Host: developer.mozilla.org
+Connection: keep-alive
+Content-Length: 432
+Pragma: no-cache
+Cache-Control: no-cache
+Origin: https://developer.mozilla.org
+Upgrade-Insecure-Requests: 1
+User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
+Content-Type: application/x-www-form-urlencoded
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+Referer: https://developer.mozilla.org/en-US/profiles/hamishwillee/edit
+Accept-Encoding: gzip, deflate, br
+Accept-Language: en-US,en;q=0.8,es;q=0.6
+Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; _gat=1; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _ga=GA1.2.1688886003.1471911953; ffo=true
+
+csrfmiddlewaretoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT&user-username=hamishwillee&user-fullname=Hamish+Willee&user-title=&user-organization=&user-location=Australia&user-locale=en-US&user-timezone=Australia%2FMelbourne&user-irc_nickname=&user-interests=&user-expertise=&user-twitter_url=&user-stackoverflow_url=&user-linkedin_url=&user-mozillians_url=&user-facebook_url=
+ +

主な違いは URL にパラメータがないことです。ご覧のとおり、フォームからの情報はリクエストの本文にエンコードされています (たとえば、新しいユーザーの fullname は &user-fullname=Hamish+Willee を使用して設定されます)。

+ +

レスポンス

+ +

リクエストからのレスポンスは以下のとおりです。ステータスコード "302 Found" は、投稿が成功したこと、および Location フィールドで指定されたページを読み込むために2番目の HTTP リクエストを発行する必要があることをブラウザに通知します。その他の点では、この情報は GET リクエストへのレスポンスに関する情報と似ています。

+ +
HTTP/1.1 302 FOUND
+Server: Apache
+X-Backend-Server: developer3.webapp.scl3.mozilla.com
+Vary: Cookie
+Vary: Accept-Encoding
+Content-Type: text/html; charset=utf-8
+Date: Wed, 07 Sep 2016 00:38:13 GMT
+Location: https://developer.mozilla.org/en-US/profiles/hamishwillee
+Keep-Alive: timeout=5, max=1000
+Connection: Keep-Alive
+X-Frame-Options: DENY
+X-Cache-Info: not cacheable; request wasn't a GET or HEAD
+Content-Length: 0
+
+ +
+

メモ: これらの例に示されている HTTP レスポンスとリクエストは Fiddler アプリケーションを使ってキャプチャされました、しかしあなたはウェブスニファ (例えば Websniffer) または HttpFox のようなブラウザ拡張を使って同様の情報を得ることができます。あなたはこれを自分で試すことができます。リンクされているツールを使用してから、サイト内を移動してプロファイル情報を編集し、さまざまなリクエストとレスポンスを確認します。最近のほとんどのブラウザには、ネットワーク要求を監視するツール (たとえば、Firefox のネットワークモニタツール) もあります。

+
+ +

静的サイト

+ +

静的サイトは、特定のリソースがリクエストされたときはいつでもサーバから同じハードコードされたコンテンツを返すものです。たとえば、製品に関するページが /static/myproduct1.html にある場合、この同じページがすべてのユーザに返されます。サイトに他の似たような製品を追加するならば、別のページ (例えば myproduct2.html) を追加する必要があるでしょう。これは本当に非効率的になり始めます — 何千もの製品ページにたどり着くとどうなるでしょう? 各ページ (基本的なページテンプレート、構造など) に渡って多くのコードを繰り返すことになります。ページ構造について何か変更したい場合 (たとえば、新しい「関連商品」セクションを追加するなど) 各ページを個別に変更する必要があります。

+ +
+

メモ: ページ数が少なく、すべてのユーザに同じコンテンツを送信したい場合は、静的サイトが優れています。ただし、ページ数が増えると、管理に多大なコストがかかる可能性があります。

+
+ +

前回の記事で見た静的サイトのアーキテクチャ図をもう一度見て、これがどのように機能するのかを要約しましょう。

+ +

A simplified diagram of a static web server.

+ +

ユーザがページにナビゲートしたい場合、ブラウザはその HTML ページの URL を指定した HTTP GET リクエストを送信します。サーバはファイルシステムからリクエストされた文書を検索し、その文書と "200 OK" の HTTP レスポンスステータスコード (成功を示す) を含む HTTP レスポンスを返します。ファイルがサーバに存在しない場合は "404 Not Found"、ファイルが存在するが別の場所にリダイレクトされている場合は "301 Moved Permanently" など、サーバは別のステータスコードを返すことがあります。

+ +

静的サイトのサーバは可変データを格納しないため、GET リクエストを処理するだけで済みます。また、HTTP リクエストデータ (URL パラメータやクッキーなど) に基づいてレスポンスを変更することもありません。

+ +

それでも、動的サイトは静的ファイル (CSS、JavaScript、静的イメージなど) に対するリクエストをまったく同じ方法で処理するため、静的サイトの機能を理解することはサーバーサイドプログラミングを学ぶときに役立ちます。

+ +

動的サイト

+ +

動的サイトとは、特定のリクエスト URL とデータに基づいてコンテンツを生成して返すことができる (特定の URL に対して常に同じハードコードファイルを返すのではない) サイトです。製品サイトの例を使用すると、サーバは個々の HTML ファイルではなくデータベースに製品の「データ」を保管します。商品の HTTP GET リクエストを受信すると、サーバは商品 ID を決定し、データベースからデータを取得してから、そのデータを HTML テンプレートに挿入することによって、レスポンス用の HTML ページを作成します。これは静的サイトよりも大きな利点があります。

+ +

データベースを使用すると、製品情報を簡単に拡張、変更、および検索可能な方法で効率的に格納できます。

+ +

HTML テンプレートを使用すると、HTML 構造の変更が非常に簡単になります。これは 1つの場所、1つのテンプレート内で行う必要があるだけで、潜在的に何千もの静的ページでは行わないためです。

+ +

動的リクエストの構造

+ +

このセクションでは、前回の記事で説明した内容に基づいて、「動的な」HTTP リクエストとレスポンスのサイクルの概要を段階的に説明します。"物事を現実のものにする" ために、コーチが HTML 形式で彼らのチーム名とチームサイズを選択して、彼らの次のゲームのために提案された "最高のラインナップ" を取り戻すことができるスポーツチームマネージャーウェブサイトのコンテキストを使います。

+ +

以下の図は、"チームコーチ" Web サイトの主な要素と、コーチが "ベストチーム"リストにアクセスしたときの一連の操作の番号付きラベルを示しています。サイトの一部は Web アプリケーション (これは HTTP リクエストを処理し、HTTP レスポンスを返すサーバーサイドコードを指す方法です)、データベース、これにはプレイヤー、チーム、コーチ、そして彼らの関係についての情報が含まれています、そして HTML テンプレートです。

+ +

This is a diagram of a simple web server with step numbers for each of step of the client-server interaction.

+ +

コーチがチーム名と選手の数を記入したフォームを送信した後、一連の操作は次のようになります。

+ +
    +
  1. Web ブラウザはリソースのベース URL (/best) を使用し、URL パラメータ (例: /best?team=my_team_name&show=11) または URL パターンの一部 (例: /best/my_team_name/11/) としてチームと選手の番号をエンコードしたものを使用して、サーバへの HTTP GET リクエストを作成します。 GET リクエストが使用されるのは、リクエストがデータをフェッチするだけである (データを変更しない) ためです。
  2. +
  3. Web サーバはリクエストが「動的」であることを検出し、それを処理 (Web サーバは、その構成で定義されたパターンマッチング規則に基づいてさまざまな URL を処理する方法を決定します) のために Web アプリケーションに転送します。
  4. +
  5. Web アプリケーションは、リクエストの意図が URL (/best/) に基づいて「最善のチームリスト」を取得することであることを識別し、URL から必要なチーム名とプレーヤーの数を見つけます。その後、Web アプリケーションはデータベースから必要な情報を取得します (どのプレーヤーが「最高」であるかを定義するために追加の「内部」パラメータを使用し、クライアント側の Cookie からログインしたコーチの身元も取得する可能性があります)。
  6. +
  7. Web アプリケーションは、(データベースからの) データを HTML テンプレート内のプレースホルダに入れることで、HTML ページを動的に作成します。
  8. +
  9. Web アプリケーションは、生成された HTML を HTTP ステータスコード 200 ("成功") とともに (Web サーバ経由で) Web ブラウザに返します。HTML が返されるのを妨げるものがあると、Web アプリケーションは別のコードを返します。たとえば、"404" はチームが存在しないことを示します。
  10. +
  11. Web ブラウザは返された HTML の処理を開始し、それが参照する他の CSS または JavaScript ファイルを取得するための個別のリクエストを送信します (手順7を参照)。
  12. +
  13. Web サーバはファイルシステムから静的ファイルをロードして直接ブラウザに返します (これも正しいファイル処理は設定ルールと URL パターンマッチングに基づいています)。
  14. +
+ +

データベース内のレコードを更新する操作も同様に処理されます。データベースの更新と同じですが、ブラウザからの HTTP リクエストは POST リクエストとしてエンコードされるはずです。

+ +

他の仕事をする

+ +

Web アプリケーションの仕事は、HTTP リクエストを受信し、HTTP レスポンスを返すことです。情報を取得または更新するためにデータベースと相互にやり取りすることは非常に一般的な作業ですが、コードは同時に他のことを実行することも、データベースとやり取りしないこともあります。

+ +

Web アプリケーションが実行する追加のタスクの良い例は、ユーザにメールを送信してサイトへの登録を確認することです。サイトはロギングやその他の操作も実行する可能性があります。

+ +

HTML 以外のものを返す

+ +

サーバサイドの Web サイトのコードは、レスポンスに HTML スニペット/ファイルを返す必要はありません。代わりに動的に他の種類のファイル (テキスト、PDF、CSV など) あるいはデータ (JSON、XML など) を作成して返すことができます。

+ +

データを動的に更新して自身のコンテンツ ({{glossary("AJAX")}}) を更新できるようにするために Web ブラウザにデータを返すという考えはかなり前からありました。ごく最近では、必要に応じて動的に更新される単一の HTML ファイルを使用して Web サイト全体が作成される「シングルページアプリケーション」が普及しています。このスタイルのアプリケーションを使用して作成された Web サイトは、サーバから Web ブラウザに多くの計算コストをかけます。その結果、Web サイトは (応答性が高いなど) ネイティブアプリケーションのように動作するように見えます。

+ +

Web フレームワークはサーバサイドの Web プログラミングを簡素化します

+ +

サーバサイド Web フレームワークにより、上記の操作を処理するコードを非常に簡単に書くことができます。

+ +

それらが実行する最も重要な操作の1つは、異なるリソース/ページの URL を特定のハンドラ関数にマッピングするための単純なメカニズムを提供することです。これにより、各タイプのリソースに関連付けられているコードを別々にしておくことが容易になります。また、ハンドラ機能を変更することなく、特定の機能を提供するために使用される URL を1か所で変更できるため、メンテナンスの面でもメリットがあります。

+ +

たとえば、2つの URL パターンを2つのビュー関数にマップする次の Django (Python) コードを考えてみましょう。最初のパターンは、/best のリソース URL を持つ HTTP リクエストが views モジュールの index() という名前の関数に渡されることを保証します。パターン "/best/junior" を持つリクエストは、代わりに junior() ビュー関数に渡されます。

+ +
# file: best/urls.py
+#
+
+from django.conf.urls import url
+
+from . import views
+
+urlpatterns = [
+    # example: /best/
+    url(r'^$', views.index),
+    # example: /best/junior/
+    url(r'^junior/$', views.junior),
+]
+ +
+

メモ: url() 関数の最初のパラメータは、「正規表現」(RegEx, または RE) と呼ばれるパターンマッチング手法を使用するため、少し奇妙に見える (たとえば、r'^junior/$') ことがあります。この時点で正規表現がどのように機能するのかを知る必要はありませんが、(上のハードコードされた値ではなく) URL のパターンと一致させてビュー関数のパラメータとして使用できるという点が異なります。例として、非常に単純な RegExは、「1つの大文字に一致し、その後に4〜7つの小文字を一致させる」と言うかもしれません。

+
+ +

Web フレームワークはまた、ビュー関数がデータベースから情報を取得するのを容易にします。データの構造はモデルで定義されています。これは基礎となるデータベースに格納されるフィールドを定義する Python クラスです。"team_type" のフィールドを持つ Team というモデルがある場合は、単純なクエリ構文を使用して特定のタイプを持つすべてのチームを取り戻すことができます。

+ +

以下の例では、 "大文字と小文字を区別する" 正確な team_type が "junior" であるすべてのチームのリストを取得します — フォーマットに注意してください。フィールド名 (team_type) の後に二重下線、そして使用する一致のタイプ (この場合は exact) です。他にもたくさんの種類の一致があり、それらをデイジーチェーンでつなげることができます。 順序と返される結果の数も制御できます。

+ +
#best/views.py
+
+from django.shortcuts import render
+
+from .models import Team
+
+
+def junior(request):
+    list_teams = Team.objects.filter(team_type__exact="junior")
+    context = {'list': list_teams}
+    return render(request, 'best/index.html', context)
+
+ +

junior() 関数は、ジュニアチームのリストを取得した後、render() 関数を呼び出して、元の HttpRequest、HTML テンプレート、およびテンプレートに含める情報を定義する  "context"  オブジェクトを渡します。render() 関数は、コンテキストと HTML テンプレートを使用して HTML を生成し、それを HttpResponse オブジェクトに返す便利な関数です。

+ +

明らかに Web フレームワークは他にも多くのタスクで役に立ちます。次の記事では、さらに多くの利点といくつかの一般的な Web フレームワークの選択について説明します。

+ +

まとめ

+ +

この時点で、サーバサイドコードが実行しなければならない操作の概要を把握し、サーバーサイド Web フレームワークがこれを容易にする方法をいくつか知っているはずです。

+ +

次のモジュールでは、最初のサイトに最適な Web フレームワークを選択する手助けをします。

+ +

{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}

+ +

このモジュールの記事一覧

+ + diff --git a/files/ja/learn/server-side/first_steps/index.html b/files/ja/learn/server-side/first_steps/index.html new file mode 100644 index 0000000000..d5acb8040f --- /dev/null +++ b/files/ja/learn/server-side/first_steps/index.html @@ -0,0 +1,47 @@ +--- +title: サーバサイドの Web サイトプログラミングの第一歩 +slug: Learn/Server-side/First_steps +tags: + - CodingScripting + - Intro + - Landing + - ガイド + - サーバサイドプログラミング + - 初心者 + - 学習 +translation_of: Learn/Server-side/First_steps +--- +
{{LearnSidebar}}
+ +

このモジュールでは、サーバーサイドプログラミングに関するいくつかの基本的な質問、"これは何?"、"クライアントサイドプログラミングとどう違うの?"、"なぜ便利なの?" について答えます。次に、最も人気のあるサーバーサイドの ウェブフレームワークの概要と、最初のサイトを作成するための最適なフレームワークの選択方法に関するガイダンスを提供します。最後に、ウェブサーバーのセキュリティに関する高度な入門記事を提供します。

+ +

前提条件

+ +

このモジュールを開始する前に、サーバーサイドのウェブサイトプログラミングやその他のプログラミングの知識は必要ありません。

+ +

しかしながら、"ウェブがどのように動作するか" を理解する必要があります。まず以下のトピックスを読むことをお勧めします:

+ + + +

基本的な事を理解できれば、このセクションを読み進む準備が整います。

+ +

ガイド

+ +
+
サーバーサイドの概要
+
MDN のサーバーサイドプログラミング入門コースにようこそ!この最初の記事では、「それはどんなもの?」、「クライアントサイドプログラミングとはどう違う?」、「なぜ便利なの?」 という質問に答えながら、ハイレベルな視点からサーバーサイドプログラミングを見ていきます。この記事を読めば、サーバーサイドコーディングを行うことで、 ウェブサイトにどんな機能を加えることができるか、理解できるようになります。
+
クライアント-サーバーの概要
+
サーバーサイドプログラミングの目的と潜在的な利点を知ったので、サーバーがブラウザーから "動的リクエスト" を受け取ったときに起こることを詳細に検討します。ほとんどのウェブサイトのサーバーサイドコードは同様の方法でリクエストとレスポンスを処理するので、これは自身のコードの大部分を書くときに何が必要かを理解するのに役立ちます
+
サーバーサイドウェブフレームワーク
+
前の記事では、ウェブクライアントとサーバー間の通信、HTTP リクエストとレスポンスの性質、およびウェブブラウザーからのリクエストにレスポンスするためにサーバーサイドウェブアプリケーションが実行する必要があることについて説明しました。この知識をもとに、ウェブフレームワークがどのようにこれらのタスクを単純化できるかを探り、最初のサーバーサイドウェブアプリケーションのためのフレームワークをどのように選択するかを考えてみましょう。
+
ウェブサイトのセキュリティ
+
ウェブサイトのセキュリティでは、ウェブサイトのデザインと使用方法のあらゆる面で警戒が必要です。この入門記事ではウェブサイトのセキュリティの第一人者にはなりませんが、脅威がどこから発生するのか、そして最も一般的な攻撃に対して Web アプリケーションを強化するために何ができるのかを理解するのに役立ちます。
+
+ +

課題

+ +

コードをまだ説明していないため、この "概要" モジュールでは課題はありません。サーバーサイドプログラミングを使用して提供できる機能の種類が何かをよく理解していることを期待しています。また、初めてのウェブサイトを作成するために使用するサーバーサイドの ウェブフレームワークについて決断していることを望みます。

diff --git a/files/ja/learn/server-side/first_steps/introduction/index.html b/files/ja/learn/server-side/first_steps/introduction/index.html new file mode 100644 index 0000000000..5c269c2d6a --- /dev/null +++ b/files/ja/learn/server-side/first_steps/introduction/index.html @@ -0,0 +1,227 @@ +--- +title: サーバサイドの概要 +slug: Learn/Server-side/First_steps/Introduction +translation_of: Learn/Server-side/First_steps/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}
+ +

MDN のサーバサイドプログラミング入門コースにようこそ!この最初の記事では、「それはどんなもの?」、「クライアントサイドプログラミングとはどう違う?」、「なぜ便利なの?」 という質問に答えながら、ハイレベルな視点からサーバサイドプログラミングを見ていきます。この記事を読めば、サーバサイドコーディングを行うことで、 Web サイトにどんな機能を加えることができるか、理解できるようになります。

+ + + + + + + + + + + + +
学習の前提:基本的なコンピュータリテラシーと、Webサーバーとはどんなものかという基礎知識を有していること
学習の目的:サーバーサイドプログラミングとは何か、何ができるのか、クライアントサイドプログラミングとどこが違うのか、といった点を理解すること
+ +

大規模なウエブサイトの多くは、サーバーサイドコードを使うことで、必要に応じた、異なるデータを動的に表示しています。このデータは、サーバーのデータベースから取り出され、クライアントに送られると、(HTMLやJavaScriptで記述された)クライアントサイドコードで表示されます。 

+ +

サーバーサイドコードを使う最大の利点は、個々のユーザーにあわせて、ウエブサイトのコンテンツ調整できることでしょう。動的サイトでは、ユーザーの好みや傾向をもとに、より適切なコンテンツを強調表示することができます。また、ユーザーの好みや情報を取り込んで利用することにより、サイトを使いやすくすることもできます。例えば、クレジットカード情報を保管して、次の支払いが簡単に済むようにできます。

+ +

加えて、通知や更新情報などを電子メールなどで送ることで、サイトユーザーとの更なるやりとりが可能になります。このような機能を活用することで、ユーザーとの繋がりをより強固なものにできるのです。.

+ +

現代のウエブ開発では、サーバーサイドプログラミングを習得することが求められるようになってきました。.

+ +

サーバーサイドプログラミングとは何か?

+ +

Webブラウザは、「ハイパー・テキスト・トランスファー・プロトコル ({{glossary("HTTP")}})」を使ってWebサーバーと通信します。Webページのリンクをクリックしたり、入力フォームを送信したり、検索を実行したりすると、ブラウザからサーバーへHTTP要求(Request)が送信されます。

+ +

この要求には、関係するデータを指定するURLや、要求するアクションを定めるメソッド(データの取得、削除、送付など)が含まれます。さらに追加情報を含むこともあります。たとえば(HTTP POSTメソッドを使ったデータ送付のように)URLのパラメータとしてクエリー文字列を付加したり、{{glossary("Cookie", "クッキー")}}を使ったりします。

+ +

Webサーバーはクライアントからの要求を待ちうけ、受信したら、処理を行ってからHTTP応答(Response)メッセージをブラウザに返します。このとき応答には、要求の実行が成功したか否かの結果(例えば成功したら"HTTP/1.1 200 OK")を含めます。 

+ +

成功したときの応答には、要求されたデータ(例えば、新しいHTMLページやが画像など)が含まれ、ブラウザ上に表示されることになります。

+ +

静的サイト

+ +

下図に静的サイトとなるWebサーバーの動作を示します。静的サイトは、要求されたデータに対して、常に一定のコンテンツを返します。新しいページに移るときには、ブラウザから、そのURLを指定したHTTP GET(取得)要求を送ります。

+ +

サーバーは要求された文書をファイルシステムから取り出し、成功ステータス(通常は"200 OK")と一緒にHTTPレスポンスに入れて送り返します。何らかの原因でファイルが取り出せないときは、エラーステータス(クライアント側エラーあるいはサーバー側エラー)を送り返します。

+ +

A simplified diagram of a static web server.

+ +

動的サイト

+ +

動的ウエブサイトでは、応答に含まれるコンテンツの一部が、必要に応じて「動的に」生成されます。多くの場合、動的ウエブサイトのHTMLページは、データベースから取り出したデータを、HTML雛型の指定された場所に埋め込むことで作られます。これは大量のコンテンツを保存するのに、静的ウエブサイトと比べて、はるかに効率的な方法と言えます。 

+ +

動的サイトは、ユーザーから与えられた情報や保存された好みに応じて、同じURL要求であっても異なるデータを返すことができます。また、応答を返すときに他の操作(例えば通知をするなど)を行うこともできます。

+ +

動的ウエブサイトを実現するコードの大部分は、サーバー上で実行されます。このコードを作ることを、「サーバーサイドプログラミング」(あるいは「バックエンドスクリプティング」)と言います。

+ +

比較的簡単な動的ウエブサイトの動作を下図に示します。ブラウザがHTTP要求を送ると、サーバーがその要求を処理して、HTTP応答を返すところは、静的ウエブサイトの場合と同じです。

+ +

静的データを要求されたときは、静的サイトと同じ動作をします。静的データはファイルとして保存されており、変更されることはありません。例えば、CSS、JavaScript、画像、事前に作成されたPDFファイルなどが、これにあたります。 

+ +

A simplified diagram of a web server that uses server-side programming to get information from a database and construct HTML from templates. This is the same diagram as is in the Client-Server overview.

+ +

動的データを要求されたときは、②の矢印が示すように、(図では「Webアプリケーション」と表示されている)他のサーバーサイドコードに転送されます。そこで要求を解釈し、必要なデータをデータベースから取り出し(③)、HTML雛型に埋め込みます(④)。それを応答としてブラウザに送り返します(⑤と⑥)。 

+ +
+

サーバーサイドプログラミングとクライアントサイドプログラミングは同じものか?

+
+ +

サーバーサイドプログラミングとクライアントサイドプログラミングを比較してみましょう。両者には明確な差異があります。

+ + + +

ブラウザで走るコードはクライアントサイドコードと呼ばれ、主要な課題は表示されるページの外観や動作を実現することにあります。例えば、どんなユーザーインターフェースを選んでまとめるか、どう配置するか、ナビゲーションをどう支援するか、フォームの入力をどう検証するかといった検討が重要です。いっぽうサーバーサイドプログラミングで重視されるのは、要求に合わせて返すコンテンツをどう選択するかということです。サーバーサイドコードが扱うのは、送付されてきたデータと要求を整合させること、データベースへのデータ登録と取り出し、要求に合致したデータを送り返すことなどです。

+ +

クライアントサイドコードに使う言語は、HTMLCSS、それにJavaScript です。コードはブラウザ内で実行され、OSへのアクセスはないか、あってもわずかです。ファイルシステムへのアクセスも限定的です

+ +

ユーザーが使うブラウザを、Web開発者が選ぶことはできません。クライアントサイドコードを実行するとき、ブラウザの互換性が問題になることがあります。実のところ、ブラウザ間の互換性の差異を克服することが、クライアントサイドプログラミングの大きな課題になっています。

+ +

サーバーサイドコードを書くのには、さまざまな言語が使えます。主な例をあげると、PHP、 Python、 Ruby、 C#、NodeJS(JavaScript)などがあります。サーバーサイドコードはサーバーのOSを全面的に利用します。開発者は自分の用途に最適な言語(さらにはバージョンまで)を選ぶことになります。

+ +

コードの開発には、Webフレームワーク がよく使われます。フレームワークとは、関数やオブジェクト、規則やコード構造などを集めたものです。よく出会う問題を解決したり、開発期間を短縮したり、ある分野で直面する様々な課題を単純化するのに役立てることができます。.

+ +

フレームワークは、クライアントサイドコードでもサーバーサイドコードで使われます。しかし、くり返しになりますが、両者には明確な差があり、フレームワークも同じものではありえません。クライアントサイドWebフレームワークが配置と表現力を改善するだけなのに対し、サーバーサイドWebフレームワークはWebサーバーに共通する機能を提供しています。それを使わないとすると、多くの機能を自分で実装する必要があります。例えば、対話セッション、ユーザー認証、データベースへのアクセス、ライブラリの雛型化はフレームワークで実現できます。

+ +
+

:クライアントサイドフレームワークは、クライアントサイドコードの開発を加速するのによく使われます。いっぽう、すべてのコードを手作りすることも可能です。実際のところ、単純なユーザーインターフェースしか必要としない小規模なWebサイトであれば、手作りの方が短期間で効率的な開発ができます。

+ +

これに反して、Webアプリのサーバーサイドコンポーネントの開発は、フレームワークなしでは考えられません。HTTPサーバーのように重要な機能を最初から、例えばPythonで記述するのは、非常に困難なことです。ところがDjangoのようのPython Webフレームワークなら、すぐに使えるし、多くの有用なツールも提供されます。

+
+ +
+

サーバーサイドではどんなことができるのか?

+ +

サーバーサイドプログラミングが役に立つのは、ユーザーごとに仕立てられた情報を、効率的に提供できるからです。またそのおかげで、ユーザーにとって使い勝手がよくなるからです。

+
+ +

例えばアマゾンのような会社では、サーバーサイドプログラミングによって、商品を検索したり、顧客の好みや過去の購入履歴から商品を勧めたり、すぐに購入できるようにしたりすることができます。

+ +

銀行でのサーバーサイドプログラミングでは、口座情報を保管し、それを見たり送金したりするのは、認証の済んだ顧客だけができるようにしています。外にも、Facebook、Twitter、InstagramあるいはWikipdeiaでは、サーバーサイドプログラミングを使って、興味あるコンテンツを取り上げて公開するときのアクセス制限を行っています。

+ +

サーバーサイドプログラミングの主な用途とその利点を以下にまとめます。一部は重複しているのが分かると思います。

+ +

情報を効率的に保管し、提供する

+ +

アマゾンには何点の商品があるのか、考えたことはありますか? Facebookへの投稿件数はどうでしょう? それぞれの商品や投稿ごとに静的なページを作るのは、まったく不可能なことです。

+ +

それに代わって、サーバーサイドプログラミングでは、データベースにデータを格納し、動的にページを構成して、HTMLや他の形式(例えばPDFや画像など)のファイルを送り返します。あるいは、{{glossary("JSON")}}や {{glossary("XML")}}などのファイルを送り返すだけで、クライアントサイドの適切なフレームワークに処理を任せることもできます。こうするとサーバーの負荷を軽減し、送るデータ量を削減することができます。

+ +

サーバーの送り返す情報は、データベースから取り出したものだけに限りません。他のソフトウエアツールの処理結果だったり、通信サービスが受信したものでも構いません。さらに言うと、ユーザーが使っている機器に合わせて、コンテンツを調整することもできます。

+ +

上方がデータベースに保管されているので、他のビジネスシステムが読み取ったり、変更することも可能です。例えば、商品が店舗で売れようと、オンラインで売れようと、一括して在庫を管理できるようになります。

+ +
+

実例:以下の例を見れば、サーバーサイドコードが、情報の効率的な保管と提供に役立つことが実感できるでしょう。

+ +
    +
  1. アマゾンなどの通販サイトを見てください。
  2. +
  3. キーワードを与えて商品を検索します。検索結果はさまざまですが、結果のページの構造は一定です。 
  4. +
  5. 検索結果から各商品のページをを比較してみましょう。ページの構造や配置は全く同じことが分かります。商品ごとの情報をデータベースから取り出して、埋め込んでいるからです。
  6. +
+ +

「魚」といった一般的な検索語を使うと、それこそ何百万件もの結果が出てきます。データベースを使うことで、これだけの情報を保管して提供できるのです。ただし、その情報は常に同じ場所に埋め込まれるのです。

+
+ +

ユーザーごとに使い勝手を改善する

+ +

サーバーが保管しているクライアントの情報を活用すれば、ユーザーにとって便利なものになり、使い勝手が向上します。例えば、多くの販売サイトではクレジットカード情報を保管して、再入力の手間がかからないようにしています。Googleマップのようなサイトでは、ユーザーの現在位置や保管していた位置を使って、経路情報を提供したり、検索や実際の旅行記録から現地のお勧め場所を表示したりします。

+ +

ユーザーの関心を良く分析することで、どこに行きたいかを予想し、それに合わせた応答や通知ができるのです。例えば、以前に行った場所とか、人気の場所を地図上に表示します。

+ +
+

実例:Googleマップ はユーザーの検索や移動の履歴を保管しています。よく行く場所や検索が多い場所を、優先して表示しています。

+ +

Google検索の結果は、以前の検索履歴によって優先づけられています。

+ +
    +
  1.  Google検索のページを開いてください。
  2. +
  3.  まず「サッカー」を検索します。
  4. +
  5.  今度は、検索語欄に「好きな」と入力して、そのあとに続く語句の候補を見てください。
  6. +
+ +

偶然だろうって? とんでもない!

+
+ +

コンテンツへのアクセスを制限する

+ +

サーバーサイドプログラミングでは、認証ユーザーのデータへのアクセスを制限し、別のユーザーには許可された情報のみを表示します。

+ +

こんな実例があります:

+ + + +
+

実例:コンテンツへのアクセスを制限している実例を見てみましょう。銀行のオンラインサイトにアクセスすると、何が見えますか? あなたの口座にログインすると、どんな情報が出てきますか? どれが変更できますか? 銀行側にしか変更できない情報は何でしょう?

+
+ +

セッションや途中状態の情報を保管する

+ +

サーバーサイドプログラミングでは、「セッション」を実装できます。これは、現在のサイトユーザーの情報を保管して、それに基づいた応答を返すようにしたものです。

+ +

この機能により、ユーザーのログイン履歴を知ることで、電子メールや過去に購入した商品へのリンクを表示できます。オンラインゲームであれば、途中結果を保存して、そこから再開できるできるようになります。

+ +
+

実例:購読型の新聞サイト(例えばThe Ageなど)を開いて、無料で記事を読んでみてください。数時間か数日読み続けると、購読について説明するページに誘導され、それ以上記事が読めなくなります。これはクッキーで保管されたセッション情報を活用する一例です。(訳注:日本の新聞サイトでは、最初に無料登録を求められますが、そのあとは同じです。)

+
+ +

通知やメッセージを送る

+ +

サーバーは一般的なお知らせやユーザー毎のお知らせをすることができます。ウエブサイトで表示するだけでなく、電子メールやSNS、インスタントメッセージ、ビデオ会議など、さまざまな通信を使っています。

+ +

例をあげてみましょう:

+ + + +
+

実例:: いちばんよくある通知の例は、登録確認のお知らせでしょう。興味のある大規模サイト(Google、アマゾンや Instagramなど)ならどこでもいいので、電子メールアドレスを使ってアカウント作ってみてください。すぐに電子メールが届いて、登録完了を知らせてくるか、登録を確認してアカウントを有効にするよう求められます。

+
+ +

データを分析する

+ +

ウエブサイトはユーザーに関する大量のデータを収集します。何を検索したか、どんな商品を購入したか、何を推奨したか、そのページにどれだけ長く留まっていたかなどです。サーバーサイドプログラミングでは、このデータを分析することで、応答を改善できるのです。

+ +

例えばアマゾンやGoogleは、どちらも以前の検索(や購入)をもとに、商品の宣伝を表示します。

+ +
+

実例: Facebookユーザーの方は、自分のフィードにある投稿を見てください。 記事が、時間順になっていないときがあります。新しい投稿より、「いいね!」が多いもののほうがリストの前の方に現れたりします。

+ +

サイトに表示される広告を見てください。その中には、他のサイトで閲覧したものがあります。Facebookがどんなアルゴリズムでコンテンツや広告を処理しているのか不明な点もありますが、あなたの「いいね!」や閲覧履歴をもとにしていることだけは確かです。

+
+ +

まとめ

+ +

サーバーサイドプログラミングの最初の記事はこれで終わりです。お疲れさまでした。 

+ +

ここまでで、サーバーサイドコードはWebサーバー上で実行され、ユーザーにどんな情報を送るか決めるのが主な目的であることを学びました。(ちなみにクライアントサイドコードは、そのデータを配置したり表現したりするのが目的です。)

+ +

その有用性は、ウエブサイトが個々のユーザーに合わせた情報を効率的に提供できることと、サーバーサイドで実現できる機能について様々なアイディアが提供できることにあることも、理解いただけたでしょう。

+ +

それから、サーバーサイドコードを書く言語は何種類もあり、Webフレームワークを使えば簡単に作れることも、お分かりいただけましたでしょうか。 

+ +

次からの記事では、どのフレームワークを選べばよいか考えます。それから、クライアント・サーバー間の相互作用について、もう少し詳しく説明します。

+ +

{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}

+ +

このモジュールの記事一覧

+ + diff --git a/files/ja/learn/server-side/first_steps/web_frameworks/index.html b/files/ja/learn/server-side/first_steps/web_frameworks/index.html new file mode 100644 index 0000000000..5d26d30fa1 --- /dev/null +++ b/files/ja/learn/server-side/first_steps/web_frameworks/index.html @@ -0,0 +1,328 @@ +--- +title: サーバーサイドウェブフレームワーク +slug: Learn/Server-side/First_steps/Web_frameworks +tags: + - Beginner + - CodingScripting + - Guide + - Intro + - Learn + - Server + - Server-side programming + - Web frameworks +translation_of: Learn/Server-side/First_steps/Web_frameworks +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}
+ +

前の記事では、ウェブクライアントとサーバー間の通信、HTTP リクエストとレスポンスの性質、およびウェブブラウザーからのリクエストにレスポンスするためにサーバーサイドウェブアプリケーションが実行する必要があることについて説明しました。この知識をもとに、ウェブフレームワークがどのようにこれらのタスクを単純化できるかを探り、最初のサーバーサイドウェブアプリケーションのためのフレームワークをどのように選択するかを考えてみましょう。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー。サーバー側のコードがHTTP リクエストを処理しレスポンスする方法 (クライアント - サーバーの概要を参照) についての基本的な知識。
目的:ウェブフレームワークがサーバーサイドコードの開発/メンテナンスをどのように簡略化できるかを理解し、自分たちの開発のためのフレームワークの選択を考えさせるため。
+ +

次のセクションでは、実際のウェブフレームワークから取得したコードフラグメントを使用していくつかのポイントを説明します。今ではすべてが意味をなさない場合でも、心配しないでください、フレームワーク固有のモジュールコードを通して作業していきますので。

+ +

概要

+ +

サーバーサイドウェブフレームワーク (別名「ウェブアプリケーションフレームワーク」)は、ウェブアプリケーションの作成、保守、および拡張を容易にするソフトウェアフレームワークです。適切なハンドラーへの URL のルーティング、データベースとのやり取り、セッションとユーザー認証のサポート、出力のフォーマット (HTML、JSON、XML など)、ウェブ攻撃に対するセキュリティの向上など、一般的なウェブ開発タスクを簡素化するツールとライブラリーを提供します。

+ +

次のセクションでは、ウェブフレームワークによってウェブアプリケーションの開発がどのように容易になるかについて、もう少し詳しく説明します。次に、ウェブフレームワークを選択するために使用できる基準のいくつかを説明し、次にいくつかの選択肢をリストします。

+ +

ウェブフレームワークで何ができますか?

+ +

ウェブフレームワークは、一般的なウェブ開発操作を簡素化するためのツールとライブラリーを提供します。サーバーサイドのウェブフレームワークを使う必要はありませんが、使用することを強くお勧めします。それはあなたの人生をずっと楽にするでしょう。

+ +

このセクションでは、ウェブフレームワークによって提供されることが多い機能の一部について説明します (必ずしもすべてのフレームワークがこれらの機能のすべてを提供するわけではありません!)。

+ +

HTTP リクエストとレスポンスを直接操作する

+ +

前回の記事で見たように、ウェブサーバーとブラウザーは HTTP プロトコルを介して通信します。サーバーはブラウザーからの HTTP リクエストを待ってから HTTP レスポンスで情報を返します。ウェブフレームワークを使用すると、これらのリクエストとレスポンスを処理するためのサーバーサイドコードを生成する単純化された構文を作成できます。これは、低レベルのネットワークプリミティブよりも、より簡単な、より高レベルのコードと対話する、より簡単な仕事を持つことを意味します。

+ +

以下の例は、Django (Python) ウェブフレームワークでどのように機能するかを示しています。すべての "view" 関数 (リクエストハンドラー) はリクエスト情報を含む HttpRequest オブジェクトを受け取り、フォーマットされた出力 (この場合は文字列) と共に HttpResponse オブジェクトを返す必要があります。

+ +
# Django view function
+from django.http import HttpResponse
+
+def index(request):
+    # Get an HttpRequest (request)
+    # perform operations using information from the request.
+    # Return HttpResponse
+    return HttpResponse('Output string to return')
+
+ +

適切なハンドラーにリクエストをルーティングする

+ +

ほとんどのサイトは、別々の URL からアクセス可能なさまざまなリソースを数多く提供します。これらすべてを 1 つの関数で処理するのは管理が難しいため、ウェブフレームワークは URL パターンを特定のハンドラー関数にマッピングするための単純なメカニズムを提供します。ベースとなるコードを変更することなく特定の機能を提供するために使用される URL を変更できるため、このアプローチにはメンテナンスの面でも利点があります。

+ +

フレームワークが異なると、マッピングに異なるメカニズムを使用します。たとえば、Flask (Python) ウェブフレームワークは、デコレーターを使用してビュー関数への経路を追加します。

+ +
@app.route("/")
+def hello():
+    return "Hello World!"
+ +

Django は開発者が URLパターンとビュー関数の間の URLマッピングのリストを定義することを期待しています。

+ +
urlpatterns = [
+    url(r'^$', views.index),
+    # example: /best/myteamname/5/
+    url(r'^(?P<team_name>\w.+?)/(?P<team_number>[0-9]+)/$', views.best),
+]
+
+ +

リクエスト内のデータに簡単にアクセスできるようにする

+ +

データはさまざまな方法で HTTP リクエストにエンコードできます。サーバーからファイルまたはデータを取得するためのHTTP GET リクエストは、URL パラメータまたは URL 構造内で必要なデータをエンコードすることができます。サーバー上のリソースを更新するための HTTP POST リクエストは、代わりに更新情報をリクエストの本文内に「POST データ」として含めます。HTTP リクエストはまた、現在のセッションまたはユーザーに関する情報をクライアント側のクッキーに含めることができます。

+ +

ウェブフレームワークは、この情報にアクセスするためのプログラミング言語に適したメカニズムを提供します。
+ たとえば、Django がすべてのビュー関数に渡す HttpRequest オブジェクトには、対象の URL にアクセスするためのメソッドとプロパティ、リクエストの種類 (HTTP GET など)、GET または POST パラメーター、cookie、セッションデータなどが含まれます。Django は URL マッパーで「キャプチャパターン」を定義することで URL の構造にエンコードされた情報を渡すこともできます (上のセクションの最後のコードを見てください)。

+ +

データベースアクセスを抽象化および単純化する

+ +

ウェブサイトは、データベースを使用して、ユーザと共有するための情報とユーザに関する情報の両方を保存します。ウェブフレームワークは多くの場合、データベースの読み取り、書き込み、照会、および削除操作を抽象化するデータベース層を提供します。この抽象化層は、オブジェクトリレーショナルマッパー (ORM) と呼ばれます。

+ +

ORM を使用することには、2 つのメリットがあります。

+ + + +

たとえば、Django のウェブフレームワークは ORM を提供し、レコードの構造をモデルとして定義するために使用されるオブジェクトを参照します。モデルは格納されるべきフィールドタイプを特定し、それはどの情報を格納することができるかについてのフィールドレベルの検証 (例えば、メールフィールドは有効なメールアドレスのみを許可する) を提供できます。フィールド定義では、最大サイズ、デフォルト値、選択リストのオプション、ドキュメントのヘルプテキスト、フォームのラベルテキストなども指定できます。コードとは別に変更されるかもしれない設定であるため、モデルは基礎となるデータベースについてのいかなる情報も述べません。

+ +

以下の最初のコードスニペットは、Team オブジェクト用の非常に単純な Django モデルを示しています。これは、チーム名とチームレベルを文字フィールドとして格納し、各レコードに格納する最大文字数を指定します。team_level は選択項目なので、表示される選択項目と保管されるデータの間のマッピング、およびデフォルト値も提供します。

+ +
#best/models.py
+
+from django.db import models
+
+class Team(models.Model):
+    team_name = models.CharField(max_length=40)
+
+    TEAM_LEVELS = (
+        ('U09', 'Under 09s'),
+        ('U10', 'Under 10s'),
+        ('U11, 'Under 11s'),
+        ...  #list our other teams
+    )
+    team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
+
+ +

Django モデルはデータベースを検索するための簡単なクエリ API を提供します。これは、異なる基準 (正確、大文字と小文字を区別しない、より大きいなど) を使用して一度に多数のフィールドに対して一致させることができ、複雑なステートメント (たとえば、"Fr" で始まるチーム名、または "al" で終わるチーム名を持つ U11 チームの検索を指定できます) をサポートすることができます。

+ +

2番目のコードスニペットは、すべての U09 チームを表示するための表示機能 (リソースハンドラー) を示しています。この場合、team_level フィールドのテキストが 'U09' であるすべてのレコード (この基準が、2つの下線で区切られたフィールド名と一致タイプを持つ引数、つまり team_level__exact として filter() 関数に渡されることに注意してください) をフィルタリングしたいと指定します。

+ +
#best/views.py
+
+from django.shortcuts import render
+from .models import Team
+
+def youngest(request):
+    list_teams = Team.objects.filter(team_level__exact="U09")
+    context = {'youngest_teams': list_teams}
+    return render(request, 'best/index.html', context)
+
+ +
+
+ +

データのレンダリング

+ +

ウェブフレームワークは通常テンプレートシステムを提供します。これにより、ページが生成されたときに追加されるデータのプレースホルダーを使用して、出力文書の構造を指定できます。テンプレートは HTML の作成によく使用されますが、他の種類の文書も作成できます。

+ +

ウェブフレームワークは多くの場合、{{glossary("JSON")}} や {{glossary("XML")}} など、格納されているデータから他のフォーマットを簡単に生成するためのメカニズムを提供します。

+ +

たとえば、Django テンプレートシステムでは、"double-handlebars" 構文 (例えば {{ variable_name }}) を使って変数を指定することができます。これは、ページがレンダリングされるときにビュー関数から渡された値に置き換えられます。テンプレートシステムは式のサポート (構文: {% expression %}) も提供します。これによりテンプレートは、渡されたリスト値を繰り返すような単純な操作を実行できます。

+ +
+

メモ: Jinja2 (Python)、handlebars (JavaScript)、moustache (JavaScript) など、他の多くのテンプレートシステムでも同様の構文が使用されています。

+
+ +

以下のコードスニペットはこれがどのように機能するかを示しています。前のセクションの「最年少チーム」の例を続けると、HTML テンプレートにはビューによって youngest_teams というリスト変数が渡されます。HTML スケルトンの内部には、最初に youngest_teams 変数が存在するかどうかを確認し、次に for ループ内でそれを繰り返す式があります。各イテレーションで、テンプレートはチームの team_name 値をリストアイテムに表示します。

+ +
#best/templates/best/index.html
+
+<!DOCTYPE html>
+<html lang="en">
+<body>
+
+ {% if youngest_teams %}
+    <ul>
+    {% for team in youngest_teams %}
+        <li>\{\{ team.team_name \}\}</li>
+    {% endfor %}
+    </ul>
+{% else %}
+    <p>利用できるチームがありません。</p>
+{% endif %}
+
+</body>
+</html>
+
+ +

ウェブフレームワークの選び方

+ +

使いたいと思うかもしれないほとんどすべてのプログラミング言語には多数のウェブフレームワークが存在します (次のセクションでもっと人気のあるフレームワークの一部をリストします)。選択肢が多すぎると、どのウェブフレームワークが新しいウェブアプリケーションの最適な出発点になるかを判断するのが難しくなります。

+ +

決定に影響を与える可能性がある要因の一部は以下のとおりです。

+ + + +

ライセンス、フレームワークが活発に開発されているかどうかなど、他にも多くの要因が考えられます。

+ +

プログラミングの完全な初心者であるならば、おそらく「学びやすさ」に基づいてフレームワークを選ぶでしょう。言語自体の「使いやすさ」に加えて、高品質のドキュメント/チュートリアル、および新しいユーザーを支援する活発なコミュニティが最も貴重なリソースです。コースの後半で例を書くために Django (Python) と Express (Node/JavaScript) を選択しました。これは主にそれらが習得が容易で優れたサポートがあるためです。

+ +
+

メモ: Django (Python) と Express (Node/JavaScript) のメインウェブサイトに行き、それらのドキュメントとコミュニティを調べてみましょう。

+ +
    +
  1. メインサイトに移動する (上記のリンク先) +
      +
    • Documentation メニューのリンク (Documentation、Guide、API Reference、Getting Started など) をクリックします。
    • +
    • URL ルーティング、テンプレート、データベース/モデルの設定方法を説明したトピックはありますか?
    • +
    • ドキュメントは明確ですか?
    • +
    +
  2. +
  3. 各サイトのメーリングリストに移動します (コミュニティリンクからアクセス可能)。 +
      +
    • 過去数日間に投稿された質問の数
    • +
    • 回答はいくつありますか?
    • +
    • 彼らは活発なコミュニティを持っていますか?
    • +
    +
  4. +
+
+ +

いくつかの良いウェブフレームワークとは?

+ +

それでは次に、いくつかのサーバーサイドウェブフレームワークについて説明しましょう。

+ +

以下のサーバーサイドフレームワークは、執筆時点で入手可能な最も人気のあるものの一部を表しています。オープンソースで、活発に開発されており、熱心なコミュニティがドキュメントを作成し、ディスカッション掲示板でユーザーを支援しています。また、多数の有名ウェブサイトで使用されています。他にも基本的なインターネット検索を使用して見つけられる多くの素晴らしいサーバーサイドフレームワークがあります。

+ +
+

メモ: 説明は (一部) フレームワークウェブサイトから引用しています。

+
+ +

Django (Python)

+ +

Django は、迅速な開発とクリーンで実用的なデザインを促進する高レベルの Python ウェブフレームワークです。

+ +

経験豊富な開発者によって構築されており、ウェブ開発における面倒なことの大部分を世話します、そのため、車輪の再発明をする必要なく、アプリの作成に集中できます。無料でオープンソースです。

+ +

Django は「バッテリー同梱」という哲学に従い、ほとんどの開発者が「一般的に」実行したいと思うほとんどすべてのことを提供します。すべてが含まれているので、すべて一緒に機能し、一貫した設計原理に従い、そして広範囲かつ最新のドキュメントがあります。また、高速で安全、そして非常にスケーラブルです。Python をベースにしているので、Django のコードは読みやすく、保守も簡単です。

+ +

(Django のホームページから) Django を使っている人気のあるサイトには、Disqus、Instagram、Knight Foundation、MacArthur Foundation、Mozilla、National Geographic、Open Knowledge Foundation、Pinterest、Open Stack などがあります。

+ +

Flask (Python)

+ +

Flask は Python 用のマイクロフレームワークです。

+ +

最小構成ですが、Flask は一般的に真面目なウェブサイトを作成することができます。開発サーバーとデバッガーが含まれており、Jinja2 テンプレート、セキュアクッキー、ユニットテスト、および RESTful リクエストのディスパッチをサポートしています。良いドキュメントと活発なコミュニティも持っています。

+ +

Flask は、特に小規模でリソースに制約のあるシステムでウェブサービスを提供する必要がある開発者 (たとえば、Raspberry Pi でウェブサーバーを実行する、Drone コントローラーなど) にとって非常に人気があります。

+ +

Express (Node.js/JavaScript)

+ +

Express は、Node.js 用の高速で、独創的で、柔軟で最小限のウェブフレームワークです (node は JavaScript を実行するためのブラウザーなしの環境です)。ウェブおよびモバイルアプリケーションに堅牢な機能を提供し、便利な HTTP ユーティリティメソッドとミドルウェアを提供します。

+ +

Express はクライアントサイドの JavaScript ウェブプログラマーのサーバーサイド開発への移行が容易である、およびリソース効率が良い (基盤となるノード環境は、新しいウェブリクエストごとに別々のプロセスを生成するのではなく、スレッド内で軽量のマルチタスクを使用します) という部分で、非常に人気があります。

+ +

Express は最小限のウェブフレームワークであるため、使用するすべてのコンポーネントが組み込まれているわけではありません (たとえば、データベースへのアクセス、ユーザーおよびセッションのサポートは、独立したライブラリーを通じて提供されます)。多くの優れた独立したコンポーネントがありますが、特定の目的に最適なものを見つけるのが難しい場合があります。

+ +

FeathersItemsAPIKeystoneJSKrakenLoopBackMEAN、および Sails を含む、多くの一般的なサーバーサイドおよびフルスタックフレームワーク (サーバーサイドフレームワークとクライアントサイドフレームワークの両方を含む) がExpress に基づいています。

+ +

Uber、Accenture、IBM などを含む多くの有名企業が Express を使用しています (リストはこちら)。

+ +

Ruby on Rails (Ruby)

+ +

Rails (通常 "Ruby on Rails" と呼ばれる) は、Ruby プログラミング言語用に書かれたウェブフレームワークです。

+ +

Rails は Django と非常によく似た設計思想に従っています。 Django と同様に、URL のルーティング、データベースからのデータへのアクセス、テンプレートからの HTML の生成、および {{glossary("JSON")}} または {{glossary("XML")}} としてのデータの書式設定のための標準メカニズムを提供します。それは同様に DRY ("自分で繰り返してはいけない" — 可能であれば一度だけコードを書く)、MVC (model-view-controller) そして他の多くのようなデザインパターンの使用を奨励します。

+ +

もちろん、特定の設計上の決定と言語の性質により、多くの違いがあります。

+ +

Rails は、BasecampGitHubShopifyAirbnbTwitchSoundCloudHuluZendeskSquareHighrise などの有名なサイトに使用されています。

+ +

Laravel (PHP)

+ +

Laravel は表現力豊かで洗練された構文を持つウェブアプリケーションフレームワークです。Laravel は、次のようなウェブプロジェクトの大部分で使用されている一般的な作業を軽減することで、開発の手間を省くことを試みています。

+ + + +

Laravel はアクセシビリティに優れながら強力であり、大規模で堅牢なアプリケーションに必要なツールを提供します。

+ +

ASP.NET

+ +

ASP.NET は、現代のウェブアプリケーションおよびサービスを構築するために Microsoft によって開発されたオープンソースウェブフレームワークです。ASP.NET を使用すると、HTML、CSS、および JavaScript に基づいてウェブサイトを迅速に作成し、何百万ものユーザーが使用できるように拡張し、ウェブ API、データフォーム、リアルタイム通信などのより複雑な機能を簡単に追加できます。

+ +

ASP.NET の差別化要因の1つは、共通言語ランタイム (CLR) 上に構築されていることです。プログラマは、サポートされている .NET 言語 (C#、Visual Basic など) を使用して ASP.NET コードを書くことができます。多くのマイクロソフト製品と同様に、優れたツール (多くの場合無料)、活発な開発者コミュニティ、および適切に記述されたドキュメントから恩恵を受けます。

+ +

ASP.NET は、Microsoft、Xbox.com、Stack Overflow、その他多くのユーザーによって使用されています。

+ +

Mojolicious (Perl)

+ +

Mojolicious は、Perl プログラミング言語用の次世代ウェブフレームワークです。

+ +

ウェブの初期の頃、CGI と呼ばれる素晴らしい Perl ライブラリーのおかげで、多くの人が Perl を学びました。それは言語についてあまり知らなくても始めるには十分に単純で、続けるには十分に強力でした。Mojolicious は、最先端のテクノロジを使ってこのアイデアを実現しています。

+ +

Mojolicious が提供する機能のいくつかは以下の通りです。
+ リアルタイムウェブフレームワーク、つまり単一ファイルのプロトタイプを構造化された MVC ウェブアプリケーションに簡単に拡張できます。RESTful なルート、プラグイン、コマンド、Perl 風のテンプレート、コンテンツネゴシエーション、セッション管理、フォーム検証、テストフレームワーク、静的ファイルサーバー、CGI/PSGI 検出、ファーストクラス Unicode サポート。IPv6、TLS、SNI、IDNA、HTTP/SOCKS 5 プロキシー、UNIX ドメインソケット、Comet (ロングポーリング)、キープアライブ、コネクションプーリング、タイムアウト、Cookie、マルチパートおよび gzip 圧縮サポートを備えたフルスタックの HTTP および WebSocket クライアント/サーバー実装。CSS セレクターをサポートする JSON および HTML/XML パーサーおよびジェネレーター。隠された魔法のない、とてもきれいで、移植性があり、オブジェクト指向の純粋な Perl API。
+ 長年の経験に基づく新鮮なコード、無料およびオープンソース。

+ +

Spring Boot (Java)

+ +

Spring Boot は、Spring が提供している数多くのプロジェクトのうちの 1 つです。Java を使用してサーバーサイドのウェブ開発を行う良い出発点です。

+ +

Java をベースとした唯一のフレームワークではないことは間違いありませんが、スタンドアローンのプロダクショングレードの Spring ベースのアプリケーションを簡単に実行することができます。これは Spring プラットフォームと他社製ライブラリーの見解に基づいた見方ですが、最小限の手間と設定で始めることができます。

+ +

小さな問題にも使用できますが、その強みはクラウドアプローチを使用する大規模アプリケーションを構築することです。通常、複数のアプリケーションが互いに並行して実行され、ユーザーとのインタラクションを提供するものと、バックエンド作業を実行するもの (データベースやその他のサービスへのアクセスなど) のみがあります。ロードバランサーは、冗長性と信頼性を確保したり、ユーザーのリクエストを地理的に処理してレスポンス性を確保したりするのに役立ちます。

+ +

まとめ

+ +

この記事では、ウェブフレームワークによって、サーバーサイドコードの開発と保守が容易になることを示しました。また、いくつかの一般的なフレームワークの概要とウェブアプリケーションフレームワークの選択基準についても説明しました。これで、少なくとも自身のサーバーサイド開発用のウェブフレームワークを選択する方法についてのアイデアが得られました。 そうでなくても心配しないでください。コースの後半で Django と Express に関する詳細なチュートリアルを提供して、ウェブフレームワークを実際に使用する経験をいくつか提供します。

+ +

このモジュールの次の記事では、方向を少し変えてウェブセキュリティについて考えます。

+ +

{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}

+ +

このモジュールの記事一覧

+ + diff --git a/files/ja/learn/server-side/first_steps/website_security/index.html b/files/ja/learn/server-side/first_steps/website_security/index.html new file mode 100644 index 0000000000..59c9a7dbf7 --- /dev/null +++ b/files/ja/learn/server-side/first_steps/website_security/index.html @@ -0,0 +1,181 @@ +--- +title: Web サイトのセキュリティ +slug: Learn/Server-side/First_steps/Website_security +tags: + - CodingScripting + - Web サイトセキュリティ + - Web セキュリティ + - イントロダクション + - ガイド + - サーバサイドプログラミング + - セキュリテイ + - 初心者 + - 学習 +translation_of: Learn/Server-side/First_steps/Website_security +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}
+ +

ウェブサイトのセキュリティでは、ウェブサイトのデザインと使用方法のあらゆる面で警戒が必要です。この入門記事だけではウェブサイトのセキュリティの第一人者にはなれませんが、脅威がどこから発生するのか、そして最も一般的な攻撃に対してウェブアプリケーションを強化するために何ができるのかを理解するのに役立ちます。

+ + + + + + + + + + + + +
前提条件:基本的なコンピューターリテラシー
目標:ウェブアプリケーションのセキュリティに対する最も一般的な脅威と、サイトがハッキングされるリスクを減らすためにできることを理解する。
+ +

ウェブサイトのセキュリティとは?

+ +

インターネットは危険な場所です。定期的に、サービス拒否攻撃によってウェブサイトが利用できなくなったり、自分のホームページに変更された (多くの場合有害な) 情報を表示したりすることがあります。その他の注目を集める事例では、何百万ものパスワード、メールアドレス、およびクレジットカードの詳細がパブリックドメインに漏洩し、ウェブサイトの利用者を個人的な当惑と経済的リスクの両方にさらしています。

+ +

ウェブサイトのセキュリティの目的は、これらの (または任意の) 種類の攻撃を防ぐことです。ウェブサイトセキュリティのより正式な定義は、許可されていないアクセス、使用、改変、破壊、または混乱からウェブサイトを保護することです

+ +

効果的なウェブサイトセキュリティでは、ウェブアプリケーション、Web サーバーの設定、パスワードの作成と更新に関するポリシー、およびクライアント側のコードなど、ウェブサイト全体にわたる設計作業が必要です。すべて不吉に聞こえるかもしれませんが、サーバーサイド Web フレームワークを使用している場合、多くの一般的な攻撃に対して「デフォルトで」堅牢でよく考え抜かれた防御メカニズムがほぼ確実に有効になります。HTTPS を有効にするなど、他の攻撃は Web サーバーの設定を通じて軽減できます。最後に、明らかな間違いを犯したかどうかを確認するのに役立つ、公開されている脆弱性スキャナツールがあります。

+ +

この記事の残りの部分では、いくつかの一般的な脅威と、サイトを保護するために実行できる簡単な手順の詳細について説明します。

+ +
+

メモ: これは導入トピックであり、ウェブサイトのセキュリティについて考え始めるのに役立つように設計されていますが、網羅的なものではありません。

+
+ +

ウェブサイトのセキュリティ上の脅威

+ +

このセクションでは、最も一般的なウェブサイトの脅威をいくつか紹介し、それらがどのように軽減されるのかを示します。お読みになったところでは、ウェブアプリケーションがブラウザーから来るデータについて信頼しているか、または十分に妄想的ではない場合に、脅威が最も効果的であることに注意してください。

+ +

クロスサイトスクリプティング (XSS)

+ +

XSS は、攻撃者がウェブサイトを通じて他のユーザーのブラウザーにクライアントサイドのスクリプトを挿入することを可能にする一連の攻撃を表すために使用される用語です。注入されたコードはサイトからブラウザーに送信されるため、コードは信頼されており、ユーザーのサイト認証 Cookie を攻撃者に送信するなどのことが可能です。攻撃者が Cookie を持っていると、あたかもユーザーであるかのようにサイトにログインし、クレジットカードの詳細へのアクセス、連絡先の詳細の表示、パスワードの変更など、ユーザーができることなら何でもできます。

+ +
+

メモ: XSS 脆弱性は、他のどの種類のセキュリティの脅威よりも歴史的に一般的です。

+
+ +

XSS 脆弱性は、サイトが挿入されたスクリプトをブラウザーに返す方法に基づいて、反映型永続型に分けられます。

+ + + +

POST または GET リクエストからのデータが XSS の脆弱性の最も一般的な原因ですが、ブラウザーによって表示される Cookie データやアップロードされて表示されるユーザーファイルなど、ブラウザーからのデータはすべて潜在的に脆弱です。

+ +

XSS の脆弱性に対する最善の防御策は、コードを実行するための命令を含む可能性があるマークアップを削除または無効にすることです。HTML の場合、これには <script><object><embed>、および <link> などの要素が含まれます。

+ +
+

スクリプトを実行したり、サーバーコードの実行に影響を与えたりすることができないようにユーザーデータを変更するプロセスは、入力サニタイズと呼ばれます。多くのウェブフレームワークは、デフォルトで HTML フォームからのユーザー入力を自動的にサニタイズします。

+
+ +

SQL インジェクション

+ +

SQL インジェクションの脆弱性により、悪意のあるユーザーはデータベース上で任意の SQL コードを実行することができ、ユーザーの許可に関係なくデータへのアクセス、変更、削除ができます。インジェクション攻撃が成功すると、ID を偽装したり、管理者権限を持つ新しい ID を作成したり、サーバー上のすべてのデータにアクセスしたり、データを破壊または変更して使用できなくなる可能性があります。

+ +
+

SQL インジェクションの種類には、エラーベースの SQL インジェクション、ブールエラーに基づく SQL インジェクション、および時間ベースの SQL インジェクションがあります。

+
+ +

ベースとなる SQL ステートメントに渡されるユーザー入力がステートメントの意味を変更する可能性がある場合に、この脆弱性が存在します。たとえば、次のコードは、HTML フォームから提供された特定の名前 (userName) を持つすべてのユーザーを一覧表示することを目的としています。

+ +
statement = "SELECT * FROM users WHERE name = '" + userName + "';"
+ +

ユーザーが実名を指定した場合、そのステートメントは意図したとおりに機能します。ただし、悪意のあるユーザーは userName に太字のテキストを指定するだけで、この SQL ステートメントの動作を次の例の新しいステートメントに完全に変更する可能性があります。

+ +
SELECT * FROM users WHERE name = 'a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't';
+
+ +

変更された文は、users テーブルを削除し、userinfo テーブルからすべてのデータを選択する (すべてのユーザーの情報を表示する) 有効な SQL 文を作成します。これは、挿入されたテキストの最初の部分 (a';) が元の文を完成させるために機能します。

+ +

この種の攻撃を回避するには、SQL クエリに渡されるユーザーデータがクエリの性質を変更できないようにする必要があります。これを行う 1 つの方法は、SQL で特別な意味を持つユーザー入力内のすべての文字をエスケープすることです。

+ +
+

メモ: SQL ステートメントは、' 文字を文字列リテラルの開始と終了として扱います。この文字の前に円記号を入れる (\') ことで、シンボルをエスケープし、代わりにそれを文字 (文字列の一部) として扱うように SQL に指示します。

+
+ +

次の文では、' 文字をエスケープします。SQL は名前を太字の文字列全体として解釈します (これは非常に奇妙な名前ですが、有害ではありません)。

+ +
SELECT * FROM users WHERE name = 'a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t';
+
+ +

ウェブフレームワークはしばしばあなたのためにエスケープする文字の面倒を見るでしょう。たとえば、Django はクエリセット (モデルクエリ) に渡されたユーザーデータが確実にエスケープされるようにします。

+ +
+

メモ: このセクションはここウィキペディアの情報に大きく依存しています。

+
+ +

クロスサイトリクエストフォージェリ (CSRF)

+ +

CSRF 攻撃は、悪意のあるユーザーが他のユーザーの資格情報を使用して、そのユーザーの知らないうちに同意なしでアクションを実行することを可能にします。

+ +

この種の攻撃は、例で最もよく説明されています。John は、特定のサイトでログインユーザーがアカウント名と金額を含む HTTP POST リクエストを使用して特定のアカウントに送金できることを知っている悪意のあるユーザーです。John は、自分の銀行の詳細と金額を隠しフィールドとして含むフォームを作成し、それを他のサイトユーザーにメールで送信します ([送信] ボタンは [早く金持ちになる] サイトへのリンクとして偽装)。

+ +

ユーザーが[送信]ボタンをクリックすると、トランザクションの詳細と、サイトに関連付けられているブラウザーが要求したクライアント側の Cookie を含む HTTP POST リクエストがサーバーに送信されます (リクエストに関連サイトの Cookie を追加するのは通常のブラウザーの動作です)。サーバーは Cookie をチェックし、それらを使用してユーザーがログインしていてトランザクションを実行する権限を持っているかどうかを判断します。

+ +

その結果、取引サイトにログインしている間に [送信] ボタンをクリックしたすべてのユーザーが取引を行うことになります。John は金持ちになります。

+ +
+

メモ: ここでのトリックは、John がユーザーの cookie (またはアクセス資格情報) にアクセスする必要がないことです。ユーザーのブラウザーはこの情報を保存し、関連するサーバーへのすべてのリクエストに自動的に含めます。

+
+ +

この種の攻撃を防ぐ 1 つの方法は、サーバーが POST リクエストにユーザー固有のサイト生成のシークレット情報を含めることを要求することです。転送に使用されるウェブフォームを送信するときに、シークレットがサーバーによって提供されます。この方法では、サーバーからユーザーに提供されているシークレットを知っている必要があるため、John は独自のフォームを作成できません。たとえ彼がシークレットを見つけて特定のユーザーのためにフォームを作成したとしても、彼はもはやその同じフォームを使用してすべてのユーザーを攻撃することはできないでしょう。

+ +

ウェブフレームワークには、そのような CSRF 防止メカニズムが含まれていることがよくあります。

+ +

その他の脅威

+ +

その他の一般的な攻撃/脆弱性は次のとおりです。

+ + + +

ウェブサイトのセキュリティ脅威の包括的な一覧については、Category: Web security exploits (Wikipedia) および Category: Attack (Open Web Application Security Project) を参照してください。

+ +

いくつかの重要なメッセージ

+ +

ウェブアプリケーションがブラウザーからのデータを信頼している場合、前のセクションのセキュリティ上の悪用のほとんどすべてが成功します。ウェブサイトのセキュリティを向上させるために他に何をしても、ブラウザーから表示される前、SQL クエリで使用される前、または OS やファイルシステムの呼び出しに渡される前に、すべてのユーザー発信データをサニタイズする必要があります。

+ +
+

重要:ウェブサイトのセキュリティについて学ぶことができる最も重要な教訓は、ブラウザーからのデータを決して信用しないことです。これには GET リクエスト、POST リクエスト、HTTP ヘッダと Cookie、およびユーザーがアップロードしたファイルの URL パラメータのデータが含まれますが、これらに限りません。すべての受信データを常にチェックしてサニタイズしてください。常に最悪の事態を想定してください。

+
+ +

あなたが取れる他の具体的な対策はいくつかあります:

+ + + +

ウェブフレームワークは、より一般的な脆弱性の多くを軽減するのに役立ちます。

+ +

まとめ

+ +

この記事では、ウェブセキュリティの概念と、ウェブサイトが保護しようとする一般的な脅威について説明しました。最も重要なことは、ウェブアプリケーションはウェブブラウザーからのデータを信頼できないということです。すべてのユーザーデータは、表示する前にサニタイズするか、SQL クエリやファイルシステムコールで使用する必要があります。

+ +

この記事で、モジュールの終わりに来ました。サーバーサイドのウェブサイトプログラミングの最初のステップをカバーしました。これらの基本概念を学んで楽しんでいただければ幸いです。これでウェブフレームワークを選択してプログラミングを開始する準備が整いました。

+ +

{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}

+ +

このモジュールの記事一覧

+ + diff --git a/files/ja/learn/server-side/index.html b/files/ja/learn/server-side/index.html new file mode 100644 index 0000000000..728f2c0fac --- /dev/null +++ b/files/ja/learn/server-side/index.html @@ -0,0 +1,59 @@ +--- +title: サーバサイド Web サイトプログラミング +slug: Learn/Server-side +tags: + - CodingScripting + - Landing + - NeedsTranslation + - Server + - Server-side programming + - Topic + - TopicStub + - 初学者 + - 学習 + - 導入部 +translation_of: Learn/Server-side +--- +
{{LearnSidebar}}
+ +

Dynamic(動的な)Webサイト サーバサイドプログラミング のトピックは、動的な Web サイト (HTTP リクエストに応じてカスタマイズされた情報を届ける Web サイト) の作り方を説明する一連のモジュールです。各モジュールは、一般的なサーバサイドプログラミングへの導入となる情報を提供するほか、特に初学者に向けて、Django (Python) や Express (Node.js/JavaScript) といった基礎的なアプリケーションを構築するためのWebフレームワークの使用方法について説明しています。

+ +

ほとんどの有名な Web サイトでは、必要に応じてさまざまなデータを動的に表示するために、何らかのサーバサイドの技術を使用しています。例えば Amazon の場合を考えてみましょう。非常にたくさんの商品が扱われていますね。また Facebook にも大量の投稿があります。これら全てを表示するために別々の静的なページをいくつも作っていっても、絶対に非効率です。ですのでその代わりに、こういったサイトでは静的なテンプレート (HTML, CSS, JavaScript で構築します) を表示し、テンプレートの内部で必要に応じ、表示される情報を動的に更新しています。例えば、Amazon で今見ている商品とは違う商品を見ようとするときに、この更新がおこなわれています。

+ +

現代の Web 開発においては、サーバサイド開発を学ぶことが強く推奨されています。

+ +

学習の道筋

+ +

サーバサイドプログラミングを始めるのは、一般的にいってクライアントサイドの開発を始めるよりも簡単です。なぜなら動的な Web サイトはどれも非常によく似た操作 (データベースからデータを読み出してそれをページに表示し、ユーザが入力したデータをヴァリデーションしてそれをデータベースに保存し、ユーザの権限をチェックした後にユーザをログインさせる、といったようなことです) を行うからです。また、動的な Web サイトはこういった一般的な Web サーバ側での操作を簡単にしてくれる Web・フレームワークを用いて作られているからです。

+ +

プログラミング概念の基本知識 (あるいは特定のプログラミング言語の知識) は役立ちますが、必要ではありません。つまり、クライアントサイドコーディングの熟達は必要ではなく、基本知識はクライアントサイドの Web「フロントエンド」の開発者とうまく共同作業するのに役立つでしょう。

+ +

「Webの動作原理」を理解する必要があります。最初に次のトピックを読むのをお勧めします:

+ + + +

基本的な理解があれば、この節のモジュールに進む準備ができているでしょう。

+ +

モジュール

+ +

このトピックは次のモジュールがあります。最初のモジュールから始めるべきで、次に続くモジュールのどれかに進んで、そこでWebフレームワークを使ってとても有名な2つのサーバサイド言語を使う方法が示されます。

+ +
+
サーバサイド Web サイトプログラミングの最初の一歩
+
このモジュールではサーバ技術の無知な人向けに、サーバサイド Web プログラミングについての情報を提供します。それにはサーバサイドプログラミングについての基本的な質問 — "それは何なのか", "クライアントサイドプログラミングと何が違うのか", "なぜ便利なのか" — や、サーバサイド Web フレームワークの概要や、あなたのサイトに最も合うものを選ぶ方法のガイドが含まれます。最後に Web サーバセキュリティの入門セクションがあります。
+
Django Web フレームワーク (Python)
+
Django は Python で書かれた、極めて人気のある、完全な機能のあるサーバサイドフレームワークです。このモジュールではなぜ Django がこうも良い Web サーバフレームワークであるのかや、開発環境のセットアップ方法や、これを使ってよくあるタスクを行う方法を説明します。
+
Express Web フレームワーク (Node.js/JavaScript)
+
Express は JavaScript で書かれて node.js の実行環境でホストされる、人気のある Web フレームワークです。このモジュールではこのフレームワークの主な利点や、開発環境のセットアップ方法や、よくある Web 開発・デプロイのタスクを行う方法を説明します。
+
+ +

あわせて参照

+ +
+
フレームワークなしの Node サーバ
+
この記事では、フレームワークを使用せずに、Node.jsだけで構築された単純な静的ファイルサーバを紹介します。
+
diff --git a/files/ja/learn/server-side/node_server_without_framework/index.html b/files/ja/learn/server-side/node_server_without_framework/index.html new file mode 100644 index 0000000000..a7ca7493b5 --- /dev/null +++ b/files/ja/learn/server-side/node_server_without_framework/index.html @@ -0,0 +1,163 @@ +--- +title: フレームワークなしの Node.js サーバ +slug: Learn/Server-side/Node_server_without_framework +tags: + - JavaScript + - NeedsContent + - Node + - サーバ + - フレームワークなし +translation_of: Learn/Server-side/Node_server_without_framework +--- +
{{LearnSidebar}}
+ +

この記事では、フレームワークを使用せずに、Node.jsだけで構築された単純な静的ファイルサーバを紹介します。

+ +

Node.js用に、サーバを稼働させるのに役立つ多くのフレームワークがあります。

+ +

最も人気があるのは、次のようなものです:

+ + + +

これらは、どんな状況にも適しているというわけではありません。開発者は既存のフレームワークに依存することなく、独自のサーバを構築する必要があることもあるでしょう。

+ +

静的ファイルサーバーの例

+ +

Node.jsで構築された、簡単な静的ファイルサーバの例を以下に示します。

+ +
var http = require('http');
+var fs = require('fs');
+var path = require('path');
+
+http.createServer(function (request, response) {
+    console.log('request ', request.url);
+
+    var filePath = '.' + request.url;
+    if (filePath == './') {
+        filePath = './index.html';
+    }
+
+    var extname = String(path.extname(filePath)).toLowerCase();
+    var mimeTypes = {
+        '.html': 'text/html',
+        '.js': 'text/javascript',
+        '.css': 'text/css',
+        '.json': 'application/json',
+        '.png': 'image/png',
+        '.jpg': 'image/jpg',
+        '.gif': 'image/gif',
+        '.wav': 'audio/wav',
+        '.mp4': 'video/mp4',
+        '.woff': 'application/font-woff',
+        '.ttf': 'application/font-ttf',
+        '.eot': 'application/vnd.ms-fontobject',
+        '.otf': 'application/font-otf',
+        '.svg': 'application/image/svg+xml'
+    };
+
+    var contentType = mimeTypes[extname] || 'application/octet-stream';
+
+    fs.readFile(filePath, function(error, content) {
+        if (error) {
+            if(error.code == 'ENOENT') {
+                fs.readFile('./404.html', function(error, content) {
+                    response.writeHead(200, { 'Content-Type': contentType });
+                    response.end(content, 'utf-8');
+                });
+            }
+            else {
+                response.writeHead(500);
+                response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
+                response.end();
+            }
+        }
+        else {
+            response.writeHead(200, { 'Content-Type': contentType });
+            response.end(content, 'utf-8');
+        }
+    });
+
+}).listen(8125);
+console.log('Server running at http://127.0.0.1:8125/');
+ +

各部の説明

+ +

第1行から第3行までは、Node.jsが提供するモジュールを組み込みます。おおむね「インポート」に似たような手続きです。

+ +
var http = require('http');
+var fs = require('fs');
+var path = require('path');
+
+ +

次にある関数で、サーバーを生成します。 https.createServerは、サーバーオブジェクトを返しますが、下の例ではポート8125で要求の受付を開始します。

+ +
http.createServer(function (request, response) {
+    ...
+}).listen(8125);
+
+ +

次の4行では、要求があったURLから、ファイルへのパスを決定します。ファイル名が明示されていないときは、デフォルト名を使うようにします。

+ +
var filePath = '.' + request.url;
+if (filePath == './') {
+    filePath = './index.html';
+}
+
+ +

例えば、example.orgというURLを要求されたときは、example.org/index.html.のことだと解釈します。

+ +

次に、要求されたファイルの拡張子を調べ、以下に定義するMIMEタイプのどれかと一致したら、そのタイプを使います。一致しない場合には、デフォルトのタイプapplication/octet-streamを使うようにします。.

+ +
var mimeTypes = {
+    '.html': 'text/html',
+    '.js': 'text/javascript',
+    '.css': 'text/css',
+    '.json': 'application/json',
+    '.png': 'image/png',
+    '.jpg': 'image/jpg',
+    '.gif': 'image/gif',
+    '.wav': 'audio/wav',
+    '.mp4': 'video/mp4',
+    '.woff': 'application/font-woff',
+    '.ttf': 'application/font-ttf',
+    '.eot': 'application/vnd.ms-fontobject',
+    '.otf': 'application/font-otf',
+    '.svg': 'application/image/svg+xml'
+};
+
+var contentType = mimeTypes[extname] || 'application/octet-stream';
+
+ +

最後に、ファイルの情報をクライアントに返送します。この関数では、あらかじめ用意してあったfilePath変数を使ってファイルを読み込みます。

+ +
fs.readFile(filePath, function(error, content) {
+    ...
+});
+
+ +

関数のなかで最初にやることは、起こりうるエラーへの対応です。一番多いのは、存在しないファイルを要求された場合(ENOENT)で、エラーコード404に対応するページを返してやります。

+ +
if(error.code == 'ENOENT') {
+    fs.readFile('./404.html', function(error, content) {
+        response.writeHead(200, { 'Content-Type': contentType });
+        response.end(content, 'utf-8');
+    });
+}
+else {
+    response.writeHead(500);
+    response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
+    response.end();
+}
+ +

何もエラーが検出されなかったら、MIME型をヘッダーに付けて、要求されたファイルを返してやります。

+ +
response.writeHead(200, { 'Content-Type': contentType });
+response.end(content, 'utf-8');
+ +

拡張の検討

+ +

静的なファイルの返送機能だけでなく、要求の度にページを動的に生成する機能を付け加えることを考えてみてください。

diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html new file mode 100644 index 0000000000..f49b505c56 --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/index.html @@ -0,0 +1,138 @@ +--- +title: Understanding client-side JavaScript frameworks +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +tags: + - Beginner + - Frameworks + - JavaScript + - Learn + - NeedsTranslation + - TopicStub + - client-side +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +--- +
{{LearnSidebar}}
+ +

JavaScriptフレームワークは、最新のフロントエンドWeb開発に欠かせないものであり、開発者にスケーラブルでインタラクティブなWebアプリケーションを構築するための試行錯誤されたツールを提供しています。現代の多くの企業では、フレームワークをツールの標準的な一部として使用しているため、多くのフロントエンド開発の仕事でフレームワークの経験が必要とされています。

+ +

フロントエンド開発者を目指していると、フレームワークを学ぶ際にどこから始めればいいのか悩むことがあります。— there are so many different frameworks to choose from, new ones appear all the time, they mostly work in a similar way but do some things differently, and there are some specific things to be careful about when using frameworks.

+ +

この記事では、あなたがフレームワークを学び始めるための快適な出発点を提供することを目的としています。私たちは、React/ReactDOMやVue、その他の特定のフレームワークについて知っておく必要があるすべてのことを網羅的に教えることを目指しているわけではありません。その代わりに、以下のようなより基本的な質問に答えたいと思います。

+ + + +

その後、異なるフレームワークの選択の要点をカバーするチュートリアルをいくつか提供し、あなたが自分自身でより深く学び始めるのに十分なコンテキストと親しみやすさを提供します。アクセシビリティなどのウェブプラットフォームの基本的なベストプラクティスを忘れずに、実用的な方法でフレームワークについて学んでいただきたいと思います。

+ +

Get started now, with "Introduction to client-side frameworks"

+ +

Prerequisites

+ +

You should really learn the basics of the core web languages first before attempting to move on to learning client-side frameworks — HTML, CSS, and especially JavaScript.

+ +

Your code will be richer and more professional as a result, and you'll be able to troubleshoot problems with more confidence if you understand the fundamental web platform features that the frameworks are building on top of.

+ +

Introductory guides

+ +
+
1. Introduction to client-side frameworks
+
We begin our look at frameworks with a general overview of the area, looking at a brief history of JavaScript and frameworks, why frameworks exist and what they give us, how to start thinking about choosing a framework to learn, and what alternatives there are to client-side frameworks.
+
2. Framework main features
+
Each major JavaScript framework has a different approach to updating the DOM, handling browser events, and providing an enjoyable developer experience. This article will explore the main features of “the big 4” frameworks, looking at how frameworks tend to work from a high level and the differences between them.
+
+ +

React tutorials

+ +
+

Note: React tutorials last tested in May 2020, with React/ReactDOM 16.13.1 and create-react-app 3.4.1.

+ +

If you need to check your code against our version, you can find a finished version of the sample React app code in our todo-react repository. For a running live version, see https://mdn.github.io/todo-react-build/.

+
+ +
+
1. Getting started with React
+
In this article we will say hello to React. We'll discover a little bit of detail about its background and use cases, set up a basic React toolchain on our local computer, and create and play with a simple starter app, learning a bit about how React works in the process.
+
2. Beginning our React todo list
+
Let's say that we’ve been tasked with creating a proof-of-concept in React – an app that allows users to add, edit, and delete tasks they want to work on, and also mark tasks as complete without deleting them. This article will walk you through putting the basic App component structure and styling in place, ready for individual component definition and interactivity, which we'll add later.
+
3. Componentizing our React app
+
At this point, our app is a monolith. Before we can make it do things, we need to break it apart into manageable, descriptive components. React doesn’t have any hard rules for what is and isn’t a component – that’s up to you! In this article, we will show you a sensible way to break our app up into components.
+
4. React interactivity: Events and state
+
With our component plan worked out, it's now time to start updating our app from a completely static UI to one that actually allows us to interact and change things. In this article we'll do this, digging into events and state along the way.
+
5. React interactivity: Editing, filtering, conditional rendering
+
As we near the end of our React journey (for now at least), we'll add the finishing touches to the main areas of functionality in our Todo list app. This includes allowing you to edit existing tasks and filtering the list of tasks between all, completed, and incomplete tasks. We'll look at conditional UI rendering along the way.
+
6. Accessibility in React
+
In our final tutorial article, we'll focus on (pun intended) accessibility, including focus management in React, which can improve usability and reduce confusion for both keyboard-only and screen reader users.
+
7. React resources
+
Our final article provides you with a list of React resources that you can use to go further in your learning.
+
+ +

Ember tutorials

+ +
+

Note: Ember tutorials last tested in May 2020, with Ember/Ember CLI version 3.18.0.

+ +

If you need to check your code against our version, you can find a finished version of the sample Ember app code in the ember-todomvc-tutorial repository. For a running live version, see https://nullvoxpopuli.github.io/ember-todomvc-tutorial/ (this also includes a few additional features not covered in the tutorial).

+
+ +
+
1. Getting started with Ember
+
In our first Ember article we will look at how Ember works and what it's useful for, install the Ember toolchain locally, create a sample app, and then do some initial setup to get it ready for development.
+
2. Ember app structure and componentization
+
In this article we'll get right on with planning out the structure of our TodoMVC Ember app, adding in the HTML for it, and then breaking that HTML structure into components.
+
3. Ember interactivity: Events, classes and state
+
At this point we'll start adding some interactivity to our app, providing the ability to add and display new todo items. Along the way, we'll look at using events in Ember, creating component classes to contain JavaScript code to control interactive features, and setting up a service to keep track of the data state of our app.
+
4. Ember Interactivity: Footer functionality, conditional rendering
+
Now it's time to start tackling the footer functionality in our app. Here we'll get the todo counter to update to show the correct number of todos still to complete, and correctly apply styling to completed todos (i.e. where the checkbox has been checked). We'll also wire up our "Clear completed" button. Along the way, we'll learn about using conditional rendering in our templates.
+
5. Routing in Ember
+
In this article we learn about routing or URL-based filtering as it is sometimes referred to. We'll use it to provide a unique URL for each of the three todo views — "All", "Active", and "Completed".
+
6. Ember resources and troubleshooting
+
Our final Ember article provides you with a list of resources that you can use to go further in your learning, plus some useful troubleshooting and other information.
+
+ +

Vue tutorials

+ +
+

Note: Vue tutorials last tested in May 2020, with Vue 2.6.11.

+ +

If you need to check your code against our version, you can find a finished version of the sample Vue app code in our todo-vue repository. For a running live version, see https://mdn.github.io/todo-vue/dist/.

+
+ +
+
1. Getting started with Vue
+
Now let's introduce Vue, the third of our frameworks. In this article, we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.
+
2. Creating our first Vue component
+
Now it's time to dive deeper into Vue, and create our own custom component — we'll start by creating a component to represent each item in the todo list. Along the way, we'll learn about a few important concepts such as calling components inside other components, passing data to them via props and saving data state.
+
3. Rendering a list of Vue components
+
At this point we've got a fully working component; we're now ready to add multiple ToDoItem components to our App. In this article we'll look at adding a set of todo item data to our App.vue component, which we'll then loop through and display inside ToDoItem components using the v-for directive.
+
4. Adding a new todo form: Vue events, methods, and models
+
We now have sample data in place and a loop that takes each bit of data and renders it inside a ToDoItem in our app. What we really need next is the ability to allow our users to enter their own todo items into the app, and for that, we'll need a text <input>, an event to fire when the data is submitted, a method to fire upon submission to add the data and rerender the list, and a model to control the data. This is what we'll cover in this article.
+
5. Styling Vue components with CSS
+
The time has finally come to make our app look a bit nicer. In this article, we'll explore the different ways of styling Vue components with CSS.
+
6. Using Vue computed properties
+
In this article we'll add a counter that displays the number of completed todo items, using a feature of Vue called computed properties. These work similarly to methods but only re-run when one of their dependencies changes.
+
7. Vue conditional rendering: editing existing todos
+
Now it is time to add one of the major parts of functionality that we're still missing — the ability to edit existing todo items. To do this, we will take advantage of Vue's conditional rendering capabilities — namely v-if and v-else — to allow us to toggle between the existing todo item view and an edit view where you can update todo item labels. We'll also look at adding functionality to delete todo items.
+
8. Focus management with Vue refs
+
We are nearly done with Vue. The last bit of functionality to look at is focus management, or put another way, how we can improve our app's keyboard accessibility. We'll look at using Vue refs to handle this — an advanced feature that allows you to have direct access to the underlying DOM nodes below the virtual DOM, or direct access from one component to the internal DOM structure of a child component.
+
9. Vue resources
+
Now we'll round off our study of Vue by giving you a list of resources that you can use to go further in your learning, plus some other useful tips.
+
+ +

Which frameworks did we choose?

+ +

We are publishing our initial set of articles with guides focusing on three of the major frameworks out there — React/ReactDOM, Ember, and Vue. There is a variety of reasons for this:

+ + + +

We want to say this upfront — we've not chosen the frameworks we are focusing on because we think they are the best, or because we endorse them in any way. We just think they score highly on the above criteria.

+ +

Note that we were hoping to have more frameworks included upon initial publication, but we decided to release the content and then add more framework guides later, rather than delay it longer. If your favourite framework is not represented in this content and you'd like to help change that, feel free to discuss it with us! Get in touch with us via Matrix, or Discourse, or drop us a mail on the mdn-admins list.

diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html new file mode 100644 index 0000000000..43eedc76eb --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_components/index.html @@ -0,0 +1,450 @@ +--- +title: React アプリのコンポーネント化 +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

この時点では、アプリは一枚岩です。アプリに何かをさせる前に、管理しやすく、記述しやすいコンポーネントに分解する必要があります。React には、何がコンポーネントで何がコンポーネントでないかという難しいルールはありません。それはあなた次第なのです!この記事では、アプリをコンポーネントに分解するための賢明な方法を紹介します。

+ + + + + + + + + + + + +
前提条件: +

HTMLCSSJavaScript のコア言語に精通していること、ターミナル/コマンドラインの知識があること。

+
目的:Todo リストアプリをコンポーネントに分割するための賢明な方法を示すこと。
+ +

最初のコンポーネントの定義

+ +

コンポーネントの定義は、ある程度練習をするまでは難しいと思われるかもしれませんが、要点は以下の通りです。

+ + + +

2 番目の箇条書きは特に価値があります: 一般的な UI 要素からコンポーネントを作成することで、コードを一箇所で変更することができ、そのコンポーネントが使用される場所のどこでも変更内容を確認することができます。また、すぐにすべてをコンポーネントに分割する必要もありません。2 つ目の箇条書きをヒントに、UI の中で最も再利用され、最も重要な部分である TODO リスト項目からコンポーネントを作成してみましょう。

+ +

<Todo />の作成

+ +

コンポーネントを作る前に、そのための新しいファイルを作らなければなりません。実は、コンポーネント用の新しいディレクトリの作成が必要です。次のコマンドは、components ディレクトリを作成し、その中に Todo.js というファイルを作成します。これらを実行する前に、アプリのルートにいることを確認してください!

+ +
mkdir src/components
+touch src/components/Todo.js
+ +

新しい Todo.js ファイルは今は空です。ファイルを開いて最初の行に次を入力してください。

+ +
import React from "react";
+ +

今回は Todo というコンポーネントを作る予定なので、以下のように Todo.js にもそのためのコードを追加していきます。このコードでは、関数の定義とエクスポートを一行で定義しています。

+ +
export default function Todo() {
+  return (
+
+  );
+}
+ +

ここまでは問題ありませんが、このコンポーネントは何かを返さなければなりません!src/App.js に戻って、最初の <li> をコピーし、Todo.js に貼り付けて、以下のように読み込みます。

+ +
export default function Todo() {
+  return (
+    <li className="todo stack-small">
+      <div className="c-cb">
+        <input id="todo-0" type="checkbox" defaultChecked={true} />
+        <label className="todo-label" htmlFor="todo-0">
+          Eat
+        </label>
+      </div>
+      <div className="btn-group">
+        <button type="button" className="btn">
+          Edit <span className="visually-hidden">Eat</span>
+        </button>
+        <button type="button" className="btn btn__danger">
+          Delete <span className="visually-hidden">Eat</span>
+        </button>
+      </div>
+    </li>
+  );
+}
+ +
+

注意: コンポーネントは常に何かを返さなければなりません。もし今後あなたが何も返さないコンポーネントをレンダリングしようとしたら、React はブラウザにエラーを表示するでしょう。

+
+ +

これで Todo コンポーネントは完成しました。App.js で、ファイルの先頭付近に次の行を追加して Todo をインポートします。

+ +
import Todo from "./components/Todo";
+ +

このコンポーネントをインポートすると、App.js<li> 要素をすべて <Todo /> コンポーネント呼び出しに置き換えることができます。<ul> は以下のようになるはずです。

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+  <Todo />
+  <Todo />
+  <Todo />
+</ul>
+ +

ブラウザに戻ってみると、何か不幸なことに気づくでしょう: あなたのリストは、最初のタスクを3回繰り返すようになりました!

+ +

Our todo list app, with todo components repeating because the label is hardcoded into the component

+ +

私たちは食べたいだけではなく、他にもやるべきこと — そう、TODO があります。次に、異なるコンポーネント呼び出しで別々のコンテンツをレンダリングする方法を見てみましょう。

+ +

「一意の」 <Todo /> を作成

+ +

コンポーネントが強力なのは、UI の一部を再利用し、その UI のソースを 1 か所で参照できるからです。問題は、通常、各コンポーネントのすべてを再利用するのではなく、ほとんどの部分を再利用しつつ小さな部分を変更したいということです。そこでプロップ( props )の出番です。

+ +

name に何が入るでしょう?

+ +

完了させたいタスクの名前を追跡するために、それぞれの <Todo /> コンポーネントが一意の名前を表示するようにしなければなりません。

+ +

App.jsでは、それぞれの <Todo /> に名前のプロップを与えます。先ほどのタスクの名前を使ってみましょう。

+ +
<Todo name="Eat" />
+<Todo name="Sleep" />
+<Todo name="Repeat" />
+ +

ブラウザを更新すると...以前と全く同じものが表示されます。<Todo /> にプロップを与えましたが、まだ使っていません。Todo.js に戻って解決しましょう。

+ +

最初に Todo() 関数の定義を変更して、props をパラメータとして受け取るようにします。props がコンポーネントによって正しく受信されているかどうかを確認したい場合は、先ほどと同様に console.log()props を取得することができます。

+ +

コンポーネントが props を取得していることを確認したら、Eatname のプロップで置き換えることができます。覚えておいてください: JSX の式の途中では、中括弧を使って変数の値を注入します。

+ +

これらをまとめると、Todo() 関数は次のようになるはずです。

+ +
export default function Todo(props) {
+  return (
+    <li className="todo stack-small">
+      <div className="c-cb">
+        <input id="todo-0" type="checkbox" defaultChecked={true} />
+        <label className="todo-label" htmlFor="todo-0">
+          {props.name}
+        </label>
+      </div>
+      <div className="btn-group">
+        <button type="button" className="btn">
+          Edit <span className="visually-hidden">{props.name}</span>
+        </button>
+        <button type="button" className="btn btn__danger">
+          Delete <span className="visually-hidden">{props.name}</span>
+        </button>
+      </div>
+    </li>
+  );
+}
+ +

これで、ブラウザには3つの一意のタスクが表示されるようになりました。しかし、もう一つの問題が残っています: これらはすべてデフォルトでチェックされています。

+ +

Our todo list, with different todo labels now they are passed into the components as props

+ +

それは completed ですか?

+ +

元の静的リストでは、Eat だけがチェックされていました。もう一度言いますが、<Todo />コンポーネントを構成するUIのほとんどを再利用しつつ、一つだけ変更したいのです。これは別のプロップが良い仕事をしてくれます!App.js での各 <Todo /> の呼び出しには、完了したことを示す新しいプロップを与えます。最初の (Eat) は true の値を持ち、残りは false にします。

+ +
<Todo name="Eat" completed={true} />
+<Todo name="Sleep" completed={false} />
+<Todo name="Repeat" completed={false} />
+ +

先ほどと同様に、これらのプロップを実際に使用するためには Todo.js に戻る必要があります。<input />defaultChecked 属性の値が completed したプロップと同じになるように変更します。これで、Todo コンポーネントの <input /> 要素は次のようになります。

+ +
<input id="todo-0" type="checkbox" defaultChecked={props.completed} />
+ +

そして、ブラウザを更新すると、Eat だけがチェックされていることが表示されるようになるはずです。

+ +

Our todo list app, now with differing checked states - some checkboxes are checked, others not

+ +

<Todo /> コンポーネントのconpleted プロップを変更すると、ブラウザはそれに応じてレンダリングされた同等のチェックボックスをチェックしたり、チェックを外したりします。

+ +

id をください

+ +

現在、<Todo /> コンポーネントはすべてのタスクに todo-0 という id 属性を与えています。これは悪い HTML です、なぜなら id 属性は一意でなければならないからです (CSS や JavaScript などでドキュメントフラグメントの一意な識別子として使用されます)。つまり、各 Todo に対して一意の値を取る id プロップをコンポーネントに与えるべきです。

+ +

最初と同じパターンに従うために、<Todo /> コンポーネントの各インスタンスに todo-i の形式で ID を与えてみましょう。i は毎回1つずつ大きくなっていきます。

+ +
<Todo name="Eat" completed={true} id="todo-0" />
+<Todo name="Sleep" completed={false} id="todo-1" />
+<Todo name="Repeat" completed={false} id="todo-2" />
+ +

ここで Todo.js に戻り、id プロップを使うようにします。これは <input /> 要素の id 属性の値とラベルの htmlFor 属性の値を置き換える必要があります。

+ +
<div className="c-cb">
+  <input id={props.id} type="checkbox" defaultChecked={props.completed} />
+  <label className="todo-label" htmlFor={props.id}>
+    {props.name}
+  </label>
+</div>
+ +

ここまでは順調ですか?

+ +

今のところ React をうまく使っていますが、もっとうまくできるかもしれません!今のコードは反復的です。<Todo /> コンポーネントをレンダリングする3つの行はほぼ同じですが、1つだけ違う点があります: それぞれのプロップの値です。

+ +

JavaScript のコアな能力の一つであるイテレーション(反復処理)を使えば、コードをクリーンアップすることができます。イテレーションを使うためには、まず自分のタスクを再考する必要があります。

+ +

データとしてのタスク

+ +

それぞれのタスクには現在、3つの情報が含まれています: 名前、チェック済みかどうか、そして一意なIDです。このデータはうまくオブジェクトに変換されます。複数のタスクがあるので、このデータを表現するにはオブジェクトの配列が有効です。

+ +

import の後 ReactDOM.render() より前の行で以下の const を作成してください。

+ +
const DATA = [
+  { id: "todo-0", name: "Eat", completed: true },
+  { id: "todo-1", name: "Sleep", completed: false },
+  { id: "todo-2", name: "Repeat", completed: false }
+];
+ +

次に、tasks という名前のプロップとして <App />DATA を渡します。src/index.js の最終行は以下のようになるはずです。

+ +
ReactDOM.render(<App tasks={DATA} />, document.getElementById("root"));
+ +

この配列は、App コンポーネントで props.tasks として利用できるようになりました。よかったら console.log() で確認してください。

+ +
+

注意: ALL_CAPS 定数名は JavaScript では特別な意味はありません; 他の開発者に「このデータはここで定義された後は変更されません」と伝えるための慣習です。

+
+ +

イテレーションによるレンダリング

+ +

オブジェクトの配列をレンダリングするには、それぞれのオブジェクトを <Todo /> コンポーネントに変換しなければなりません。JavaScript では、データを別のものに変換するための配列メソッド Array.prototype.map() を提供しています。

+ +

Above the return statement of App(), make a new const called taskList and use map() to transform it. Let's start by turning our tasks array into something simple: the name of each task:

+ +
const taskList = props.tasks.map(task => task.name);
+ +

Let’s try replacing all the children of the <ul> with taskList:

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+  {taskList}
+</ul>
+ +

This gets us some of the way towards showing all the components again, but we’ve got more work to do: the browser currently renders each task's name as unstructured text. We’re missing our HTML structure — the <li> and its checkboxes and buttons!

+ +

Our todo list app with the todo item labels just shown bunched up on one line

+ +

To fix this, we need to return a <Todo /> component from our map() function — remember that JSX allows us to mix up JavaScript and markup structures! Let's try the following instead of what we have already:

+ +
 const taskList = props.tasks.map(task => <Todo />);
+ +

Look again at your app; now our tasks look more like they used to, but they’re missing the names of the tasks themselves.  Remember that each task we map over has the id, name, and checked properties we want to pass into our <Todo /> component. If we put that knowledge together, we get code like this:

+ +
const taskList = props.tasks.map(task => (
+  <Todo id={task.id} name={task.name} completed={task.completed} />
+));
+ +

Now the app looks like it did before, and our code is less repetitive.

+ +

Unique keys

+ +

Now that React is rendering our tasks out of an array, it has to keep track of which one is which in order to render them properly. React tries to do its own guesswork to keep track of things, but we can help it out by passing a key prop to our <Todo /> components. key is a special prop that's managed by React – you cannot use the word key for any other purpose.

+ +

Because keys should be unique, we're going to re-use the id of each task object as its key. Update your taskList constant like so:

+ +
const taskList = props.tasks.map(task => (
+    <Todo
+      id={task.id}
+      name={task.name}
+      completed={task.completed}
+      key={task.id}
+    />
+  )
+);
+ +

You should always pass a unique key to anything you render with iteration. Nothing obvious will change in your browser, but if you do not use unique keys, React will log warnings to your console and your app may behave strangely!

+ +

Componentizing the rest of the app

+ +

Now that we've got our most important component sorted out, we can turn the rest of our app into components. Remembering that components are either obvious pieces of UI, or reused pieces of UI, or both, we can make two more components:

+ + + +

Since we know we need both, we can batch some of the file creation work together with a terminal command. Run this command in your terminal, taking care that you're in the root directory of your app:

+ +
touch src/components/Form.js src/components/FilterButton.js
+ +

The <Form />

+ +

Open components/Form.js and do the following:

+ + + +

Your Form.js file should read like this:

+ +
import React from "react";
+
+function Form(props) {
+  return (
+    <form>
+      <h2 className="label-wrapper">
+        <label htmlFor="new-todo-input" className="label__lg">
+          What needs to be done?
+        </label>
+      </h2>
+      <input
+        type="text"
+        id="new-todo-input"
+        className="input input__lg"
+        name="text"
+        autoComplete="off"
+      />
+      <button type="submit" className="btn btn__primary btn__lg">
+        Add
+      </button>
+    </form>
+  );
+}
+
+export default Form;
+ +

The <FilterButton />

+ +

Do the same things you did to create Form.js inside FilterButton.js, but call the component FilterButton() and copy the HTML for the first button inside the <div> element with the class of filters from App.js into the return statement.

+ +

The file should read like this:

+ +
import React from "react";
+
+function FilterButton(props) {
+  return (
+    <button type="button" className="btn toggle-btn" aria-pressed="true">
+      <span className="visually-hidden">Show </span>
+      <span>all </span>
+      <span className="visually-hidden"> tasks</span>
+    </button>
+  );
+}
+
+export default FilterButton;
+ +
+

Note: You might notice that we are making the same mistake here as we first made for the <Todo /> component, in that each button will be the same. That’s fine! We’re going to fix up this component later on, in Back to the filter buttons.

+
+ +

Importing all our components

+ +

Let's make use of our new components.

+ +

Add some more import statements to the top of App.js, to import them.

+ +

Then, update the return statement of App() so that it renders our components. When you’re done, App.js will read like this:

+ +
import React from "react";
+import Form from "./components/Form";
+import FilterButton from "./components/FilterButton";
+import Todo from "./components/Todo";
+
+function App(props) {
+  const taskList = props.tasks.map(task => (
+    <Todo
+        id={task.id}
+        name={task.name}
+        completed={task.completed}
+        key={task.id}
+      />
+    )
+  );
+  return (
+    <div className="todoapp stack-large">
+      <Form />
+      <div className="filters btn-group stack-exception">
+        <FilterButton />
+        <FilterButton />
+        <FilterButton />
+      </div>
+      <h2 id="list-heading">3 tasks remaining</h2>
+      <ul
+        role="list"
+        className="todo-list stack-large stack-exception"
+        aria-labelledby="list-heading"
+      >
+        {taskList}
+      </ul>
+    </div>
+  );
+}
+
+export default App;
+ +

With this in place, we’re almost ready to tackle some interactivity in our React app!

+ +

Summary

+ +

And that's it for this article — we've gone into some depth on how to break up your app nicely into components, end render them efficiently. Now we'll go on to look at how we handle events in React, and start adding some interactivity.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

In this module

+ + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html new file mode 100644 index 0000000000..5114539cca --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_getting_started/index.html @@ -0,0 +1,468 @@ +--- +title: Reactをはじめる +slug: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +tags: + - Beginner + - Frameworks + - JavaScript + - Learn + - React + - client-side +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

この記事では React のはじめかたを説明します。Reactの背景と使い方について説明し、ローカル環境で基本的な React ツールチェーンを設定します。また、シンプルな基本アプリを作成して、React がどのようなプロセスで機能するのかを学んでいきます。

+ + + + + + + + + + + + +
前提条件: +

HTMLCSSJavaScript に精通していること、ターミナル/コマンドラインに関する知識があること。

+ +

React は JSX (JavaScript と XML) と呼ばれる HTML-in-JavaScript を使用します。HTML と JavaScript の両方に精通していると、JSX の学習に役立ち、アプリケーションのバグが JavaScript に関連しているか、React のより具体的なドメインに関連しているかを特定するのに役立つます。

+
目的:ローカルの React 開発環境をセットアップし、開始アプリを作成して、それがどのように機能するかの基本を理解する
+ +

React の基礎

+ +

公式のキャッチフレーズにあるように、React はユーザーインターフェイスを構築するためのライブラリーです。React はフレームワークではなく、ウェブに限定されるものでもありません。他のライブラリーと共に使用して、特定の環境にレンダリングしますます。たとえば、React Native はモバイルアプリケーションの構築に使用できます。React 360 を使用して、仮想現実アプリケーションを構築できます。他にも可能性があります。

+ +

ウェブ向けに構築するには、開発者は ReactDOM と連携してリアクトを使用します。リアクトと ReactDOM は、他の本当のウェブ開発フレームワークと同じ土台で議論さんくれ、同じような問題を解決するために用いられます。しかし React を「フレームワーク」と呼ぶとき、私たちはその口語的な理解に別途でいます。

+ +

React が目指すところは、開発者がUIを構築しているときに発生するバグを最小限に抑えることです。これは、コンポーネント (ユーザーインターフェイスの一部を記述する自己完結型の論理的なコード) を使用して行われます。これらのコンポーネントを組み合わせて完全なUIを作成でき、React はレンダリング作業の大部分を抽象化して、UI デザインに集中できるようにします。

+ +

ユースケース

+ +

このモジュールで取り上げられている他のフレームワークとは異なり、React はコード規則やファイル編成に関する厳密なルールを適用しません。これにより、チームは自分に最適な規則を設定し、Reactを好きなように採用することができます。React は、単一のボタン、一部のインターフェース、またはアプリのユーザーインターフェース全体を処理できます。

+ +

React はインターフェイスの一部に適に用することが できます が、jQuery のようなライブラリーや Vue のようなフレームワークほどアプリケーションに「ドロップ」するのは簡単ではありません。React でアプリ全体を構築するのに適しています。

+ +

さらに、JSX のインターフェースの作成など、React アプリの開発者体験にはコンパイルプロセスが必要とします。Babel のようなコンパイラーをウェブサイトに追加すると、コードの実行が遅くなるため、開発者はビルドステップでそのようなツールをセットアップすることがよくあります。間違いなく React には厳しいツール要件がありますが、学習することはできます。

+ +

この記事では、Facebook 独自の create-react-app を使って、アプリケーションのインターフェイスを構築していきます。

+ +

ReactにおけるJavaScriptの書き方

+ +

Reactは、そのパターンの多くに最新の JavaScript の機能を利用しています。JavaScript からの最大の違いは、JSX 構文を使うことです。JSX は JavaScript の構文を拡張して、HTML のようにコードを書くことができます。例えば:

+ +
const heading = <h1>Mozilla Developer Network </h1>;
+ +

この定数 heading は、JSX 式と呼ばれます。React はこのように <h1> タグをレンダリングすることができます。

+ +

セマンティックの観点で、 <header> タグで、見出しを囲みたいとします。JSX では、HTML のように、要素を相互にネストできます。

+ +
const header = (
+  <header>
+    <h1>Mozilla Developer Network</h1>
+  </header>
+);
+ +
+

: このスニペットの括弧は JSX に固有のものではなく、あなたのアプリケーションに影響を与えません。それらは、あなた (またあなたのコンピューター) にとって、内部の複数行のコードが同じ式の一部であるという意味です。次のように header を定義することもできます。

+ +
const header = <header>
+    <h1>Mozilla Developer Network</h1>
+</header>
+ +

ただし、<header> 式を開始するタグが、対応する終了タグと同じ位置にインデントされていないため、これは少し読みにくいかもしれません。

+
+ +

もちろん、あなたのブラウザーはそのままでは JSX を読むことができません。(BabelParcel などのツールを使用して) コンパイルすると、ヘッダー式は次のようになります。

+ +
const header = React.createElement("header"、null、
+  React.createElement("h1"、null、 "Mozilla Developer Network")
+);
+ +

コンパイルステップとコンパイル自体をスキップし、React.createElement() を使って、独自のUIを自分で書くこと。ただし、こうするとJSXの宣言的なメリットが失われ、コードが読みにくくなってしまいます。コンパイルは開発プロセスとは別のステップですが、Reactコミュニティの多くの開発者は、JSXの読みやすさに価値があると考えています。さらに、外部ツールにより、JSX から JavaScript へのコンパイルがセットアッププロセスの一部になります。特段の必要がない限り、コンパイルを自分の手で行う必要はありません。

+ +

JSX は HTML と JavaScript がミックスされたものなので、一部の開発者にとっては直感的に使うことができます。しかしそうでない人にとってはは、そのミックスされていることで混乱させられると言います。ただし、慣れれば、ユーザーインターフェースをより迅速かつ直感的に構築できるようになり、他の人がコードを一目で理解しやすくなります。

+ +

JSX の詳細については、React チームの JSX In Depth の記事をご覧ください。

+ +

最初の React アプリをセットアップする

+ +

React を使用する方法はたくさんありますが、前述のように、コマンドラインインターフェイス (CLI) ツールの create-react-app を使用します。これにより、いくつかのパッケージをインストールしていくつかを作成することにより、React アプリケーションの開発プロセスをスムーズにします。

+ +

<script> を HTML ファイルにコピーすることで create-react-app なしでウェブサイトに React を追加することは可能ですが、create-react-app CLI は、React アプリケーションの一般的な始め方です。これを使うことで、アプリの作成に集中でき、セットアップに煩わされなくなります。

+ +

必要条件

+ +

create-react-app を使用するには、Node.js をインストールする必要があります。長期サポート (LTS) バージョンを使用することをお勧めします。ノードには、npm (ノードパッケージマネージャー) および npx (ノードパッケージランナー) が含まれます。

+ +

代わりに Yarn パッケージマネージャーを使用することもできますが、この一連のチュートリアルでは npm を使用するものとします。npm と yarn の詳細については、パッケージ管理の基本を参照してください。

+ +

Windows を使用している場合、このチュートリアルで言及されている端末コマンドを使用するには、Unix / macOS 端末と同等のソフトウェアをインストールする必要があります。Gitbash (Windows 用git ツールセットの一部として提供) または Linux 用の Windows サブシステム (WSL) の両方が適しています。これら、および一般的な端末コマンドの詳細については、コマンドラインクラッシュコースを参照してください。

+ +

また、React と ReactDOM は、かなり近代的な一連のブラウザー (IE9 以降) でのみ機能するアプリを生成することにも注意してください。これらのチュートリアルを実行するときは、Firefox、Safari、Chrome などの最新のブラウザーを使用することをお勧めします。

+ +

詳細については、以下も参照してください。

+ + + +

アプリの初期化

+ +

create-react-app は引数を 1 つ取ります。アプリに付ける名前です。create-react-app はこの名前を使用して新しいディレクトリーを作成し、その中に必要なファイルを作成します。cd でアプリのハードドライブ上の場所に移動したことを確認してから、ターミナルで次のコマンドを実行します。

+ +
npx create-react-app moz-todo-react
+ +

これは moz-todo-react ディレクトリーを作成し、その中でいくつかのことを行います:

+ + + +
+

: Yarn パッケージマネージャーがインストールされている場合、create-react-app はデフォルトで npm の代わりにそれを使用します。両方のパッケージマネージャーがインストールされていて、明示的に NPM を使用したい場合、create-react-app を実行するときに --use-npm フラグを追加できます。

+ +
npx create-react-app moz-todo-react --use-npm
+
+ +

create-react-app が機能している間、端末にいくつかのメッセージが表示されますが、正常な動作です!これには数分かかる場合がありますので、お茶でも作って待ってみましょう。

+ +

プロセスが完了したら、moz-todo-reactディレクトリーへ cd して、コマンド npm start を実行します。create-react-app によってインストールされたスクリプトは、localhost:3000 のローカルサーバーで提供され始め、新しいブラウザータブでアプリを開きます。ブラウザーには次のように表示されます。

+ +

デフォルトのcreate-react-app アプリケーションを示す、Firefox MacOS のスクリーンショット、localhost:3000を開く

+ +

アプリケーションの構造

+ +

create-react-app は、React アプリケーションの開発に必要なすべてのものを提供します。初期のファイル構造は次のようになります。

+ +
moz-todo-react
+├──README.md
+├──node_modules
+├──package.json
+├──package-lock.json
+├──.gitignore
+├──public
+│├──favicon.ico
+│├──index.html
+│└──manifest.json
+└──src
+    ├──App.css
+    ├──App.js
+    ├──App.test.js
+    ├──index.css
+    ├──index.js
+    ├──logo.svg
+    └──serviceWorker.js
+ +

src ディレクトリーはアプリケーションの実態ともいえるソースことがある場所で、私たちが触るのは主にこの部分です。

+ +

public ディレクトリーには、アプリを開発している間、ブラウザーによって読み込まれるファイルが含まれています。これらの中で最も重要なのは index.html です。React はこのファイルにコードを挿入して、ブラウザーで実行できるようにします。create-react-app 関数に役立つマークアップが他にもいくつかあるので、何をしているのかを理解していなければ、自分で編集しないように注意してください。このファイルの要素内の <title> を変更して、アプリケーション自体のタイトルを反映させる必要があります。アクセシビリティ向上のためには正しいページタイトルが重要です。

+ +

public ディレクトリーは、アプリをビルドしてデプロイするときにも公開されます。このチュートリアルではデプロイ自体については説明しませんが、アプリのデプロイチュートリアルで説明されているものと同様のソリューションを使用できるはずです。

+ +

このpackage.json ファイルには、Node.js / npm がプロジェクトを整理するために使用するプロジェクトに関する情報が含まれています。このファイルは React アプリケーションに固有のものではありません。create-react-app は単にそれを生成します。このチュートリアルを完了するためにこのファイルを理解する必要はまったくありませんが、詳しく知りたい場合は「package.json ファイルとは」を参照してください。

+ +

最初の React コンポーネント— <App/>

+ +

React における、コンポーネントとはアプリの一部をレンダリングする再利用可能なモジュールを指します。これらのパーツは大きくても小さくてもかまいませんが、通常は明確に定義され、単一責務のもとに作られます。

+ +

ブラウザーに表示されているように、src/App.js を開いて編集しましょう。このファイルには、最初のコンポーネント、App、その他の数行のコードが含まれています。

+ +
import React from 'react';
+import logo from './logo.svg';
+import './App.css';
+
+function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Edit <code>src/App.js</code> and save to reload.
+        </p>
+        <a
+          className="App-link"
+          href="https://reactjs.org"
+          target="_blank"
+          rel="noopener noreferrer"
+        >
+          Learn React
+        </a>
+      </header>
+    </div>
+  );
+}
+export default App;
+ +

この App.js ファイルは 3 つの主要な部分で構成されています。上部にいくつかの宣言されている import、中央にある App、最下部にある export。ほとんどの React コンポーネントはこのように書かれます。

+ +

ステートメントをインポートする

+ +

import はファイルの先頭に宣言され、App.js が他の場所で定義されているコードを使用するのを許可します。これらをさらに詳しく見てみましょう。

+ +
import React from 'react';
+import logo from './logo.svg';
+import './App.css';
+ +

最初のステートメントは、React ライブラリー自体をインポートします。React は、作成する JSX を React.createElement() に変換するため、すべての React コンポーネントが React モジュールをインポートする必要があります。この手順をスキップすると、アプリケーションでエラーが発生します。

+ +

2 番目のステートメントは、'./logo.svg' をインポートします。最初の ./ パスのと最後の拡張子 .svg に注意してください。これらはファイルがローカルであり、JavaScript ファイルではないことを示しています。実際、logo.svg ファイルは src/ ディレクトリーにあります。

+ +

React モジュールのインポート時にパスや拡張子は記述しません—これはローカルファイルではないからです。代わりに、package.json ファイルに依存関係としてリストされます。このレッスンでは、この違いに注意してください。

+ +

3番目のステートメントは、App コンポーネントに関連する CSS をインポートします。変数名も from ディレクティブもないことに注意してください。この特定のインポート構文は、JavaScript モジュール構文に特有のものではありません。Webpack から提供されるものです。create-react-app ツールは、すべての JavaScript ファイルをバンドルしてブラウザーに提供するために使用します。

+ +

App コンポーネント

+ +

import の次に、App という名前の関数があります。ほとんどの JavaScript コミュニティはhelloWorld のようなキャメルケース名を好みますが、React コンポーネントは HelloWorld のようなパスカルケース変数名を使用して、特定のJSX 要素が React コンポーネントであり、通常の HTML タグではないことを明確にしています。App 関数の名前を app に変更すると、ブラウザーにエラーが表示されます。

+ +

アプリをもっと詳しく見てみましょう。

+ +
function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Edit <code>src/App.js</code> and save to reload.
+        </p>
+        <a
+          className="App-link"
+          href="https://reactjs.org"
+          target="_blank"
+          rel="noopener noreferrer"
+        >
+          Learn React
+        </a>
+      </header>
+    </div>
+  );
+}
+ +

この App 関数は JSX 式を返します。この式には、ブラウザーが最終的に DOM にレンダリングするものを定義します。

+ +

HTML と同じように、attribute="value" のように属性をもつ要素があります。3 行目では、<div> 開始タグに className 属性があります。これは HTML のclass 属性と同じですが、JSX は JavaScript であるため使用できません。class が予約されているためです。つまり、JavaScript ではすでにそれを使用しており、もし同様に使うと問題が発生するということです。同じような理由で、他のいくつかの HTML 属性は、HTML とは異なる方法で JSX で記述されています。

+ +

6 行目の <p> タグを「Hello, world!」に変更して、ファイルを保存します。この変更はブラウザー http://localhost:3000 で実行されている開発サーバーですぐにレンダリングされます。次に、<a> タグを削除して保存します。すると、「Learn React」リンクはなくなります。

+ +

あなたの App コンポーネントは次のようになります。

+ +
function App() {
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, World!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

ステートメントのエクスポート

+ +

App.js ファイルの一番下にある export default App は、App コンポーネントを他のモジュールで使用できるようにしています。

+ +

index を詳しくみる

+ +

src/index.js を開きましょう。App コンポーネントを使用しているのがわかります。このファイルはアプリのエントリーポイントであり、最初は次のようになっています。

+ +
import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+import * as serviceWorker from './serviceWorker';
+
+ReactDOM.render(<App />, document.getElementById('root'));
+
+// If you want your app to work offline and load faster, you can change
+// unregister() to register() below. Note this comes with some pitfalls.
+// Learn more about service workers: https://bit.ly/CRA-PWA
+serviceWorker.unregister();
+ +

App.js と同様に、ファイルは、実行する必要のあるすべての JS モジュールとその他のアセットをインポートすることから始まります。src/index.css ではアプリ全体に適用されるグローバルスタイルを保持します。ここに、インポートされたAppコンポーネントも確認できます。下部の export により、App.js がインポートできるようになりました。

+ +

7 行目 ReactDOM.render() は 2 つの引数で React の関数を呼び出します:

+ + + +

これらはすべて、App コンポーネントを最初のコンポーネントとして React アプリケーションをレンダリングすることを React に伝えます。

+ +
+

: JSX では、React コンポーネントと HTML 要素には閉じスラッシュが必要です。そのまま <App> または <img> と書くとエラーが発生します。

+
+ +

Service Worker は、アプリケーションのパフォーマンスを向上させ、ウェブアプリケーションの機能をオフラインで動作させることができる興味深いコードですが、この記事の対象ではありません。5 行目と 9 〜 12 行目を削除します。

+ +

最終的なindex.jsファイルは次のようになります。

+ +
import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+
+ReactDOM.render(<App />, document.getElementById('root'));
+ +

変数と props

+ +

次に、JavaScript スキルのいくつかを使用して、コンポーネントの編集と React でのデータの操作をもう少し快適にします。JSX内での変数の使用方法について説明し、データをコンポーネントに渡す方法である props を紹介します (その後、変数を使用してアクセスできます)。

+ +

JSXの変数

+ +

App.js に戻り、9 行目に注目しましょう。

+ +
<img src = {logo} className = "App-logo" alt = "logo" />
+ +

ここでは、<img /> タグの src 属性値は中括弧で囲まれています。これは、JSX が変数を認識する方法です。React が {logo} を表示し、アプリの2行目のインポートを参照していることを確認してから、logo ファイルを取得してレンダリングします。

+ +

独自の変数を作ってみましょう。App の return ステートメントの前に const subject = 'React'; を追加します。すると、App コンポーネントは次のようになります。

+ +
function App() {
+  const subject = "React";
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, World!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

次のように、8 行目を変更して「world」という単語の代わりに subject 変数を使用します。

+ +
function App() {
+  const subject = "React";
+  return (
+    <div className="App">
+      <header className="App-header">
+        <img src={logo} className="App-logo" alt="logo" />
+        <p>
+          Hello, {subject}!
+        </p>
+      </header>
+    </div>
+  );
+}
+ +

保存すると、「Hello、world!」の代わりにブラウザーに「Hello、React!」と表示されます。

+ +

変数は便利ですが、設定したばかりの変数はReactの機能をあまり活用していません。そこで、propsの登場です。

+ +

コンポーネントのprops

+ +

props はコンポーネントに渡される任意のデータです。prop はコンポーネント内に記述され、HTML属性と同じ構文を使用します — prop="value"index.jsを開き、<App/> に最初の prop を渡しましょう。

+ +

<App/> コンポーネントに subject という prop を追加して、値は Clarice とします。完了すると、コードは次のようになります。

+ +
ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));
+ +

App.js に戻り、App 関数自体をもう一度見てみましょう。この関数は次のようになっています (簡潔にするために return で短くしています)。

+ +
function App() {
+  const subject = "React";
+  return (
+    // return statement
+  );
+}
+ +

App 関数の引数を変更して、props をパラメーターとして受け入れられるようにします。他のパラメーターと同様 props に、console.log() を入力して、ブラウザーのコンソールにそれを表示させます。すると、次のようになります。

+ +
function App(props) {
+  const subject = "React";
+  console.log(props);
+  return (
+    // return statement
+  );
+}
+ +

ファイルを保存し、ブラウザーの JavaScript コンソールを確認します。次のようなログが表示されるはずです。

+ +
Object { subject: "Clarice" }
+ +

オブジェクトプロパティ subject は、<App /> コンポーネント呼び出しに追加した subject プロパティに対応し、文字列 Clarice はその値に対応します。React のコンポーネントプロップは、常にこのようにオブジェクトに集約されます。

+ +

subject は props の一部です。App.js でこれを使ってみましょう。subject 定数を変更して、React という文字列として定義する代わりに props.subject の値を読み取るようにします。console.log() は必要に応じて削除することもできます。

+ +
function App(props) {
+  const subject = props.subject;
+  return (
+    // return statement
+  );
+}
+ +

保存すると、アプリは「Hello、Clarice!」と挨拶するはずです。index.js に戻り、subject の値を編集して保存すると、テキストが変更されます。

+ +

まとめ

+ +

これで、React をローカルでインストールする方法、スターターアプリを作成する方法、基本的にどのように機能するかなど、React の入門が終わりました。次の記事では、最初に適したアプリケーションである todo リストの作成を開始します。ただし、その前に、私たちが学んだことのいくつかをおさらいしましょう。

+ +

React では:

+ + + +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html new file mode 100644 index 0000000000..debc627272 --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/react_todo_list_beginning/index.html @@ -0,0 +1,599 @@ +--- +title: React ToDoリストをはじめる +slug: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning +--- +
+

{{LearnSidebar}}

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+
+ +

たとえば、Reactで概念実証を作成する必要があるとします。これは、ユーザーが作業したいタスクを追加、編集、削除したり、タスクを削除せずに完了としてマークしたりできるアプリです。この記事では、基本的なAppコンポーネントの構造とスタイルを設定し、個々のコンポーネントの定義と変更に対応できるようにします。これについては後で追加します。

+ +
+

:コードをGoogleのバージョンと照合する必要がある場合は、todo-reactリポジトリでサンプルのReactアプリコードの完成版を見つけることができます。実行中のバージョンについては、https://mdn.github .io / todo-react-build /を参照してください。

+
+ + + + + + + + + + + + +
前提条件: +

コアHTMLCSSJavaScriptの言語に精通していることターミナル/マンドコラインに関すてる知識

+
目的:todoリストのケーススタディを紹介し、基本的なApp構造とスタイルを整える。
+ +

アプリの「ユーザーストーリー」

+ +

ソフトウェア開発では、ユーザーストーリーはユーザーの観点から実行可能な目標を指します。作業を開始する前にユーザーストーリーを定義すると、作業に集中することができます。今回、私たちのアプリは以下のストーリーを実現する必要があります:

+ +

ユーザーができること

+ + + +

これらのストーリーに1つずつ取り組みます。

+ +

プロジェクトに入る前に現状整理

+ +

create-react-appは、プロジェクトでまったく使用しないファイルをいくつか作成しています。

+ + + +

次に、以下のコマンドをコピーしてターミナルに貼り付け、不要なファイルをいくつか削除します。アプリのルートディレクトリから開始していることを確認してください。

+ +
# Move into the src directory of your project
+cd src
+# Delete a few files
+rm -- App.test.js App.css logo.svg serviceWorker.js setupTests.js
+# Move back up to the root of the project
+cd ..
+ +

ノート:

+ + + +

はじめのプロジェクトコード

+ +

このプロジェクトの開始点として、次の2つを提供します。現在持っているものを置き換えるApp関数と、アプリのスタイルを設定するCSSです。

+ +

JSX

+ +

次のスニペットをクリップボードにコピーして貼り付けApp.js、既存のApp()関数を置き換えます。

+ +
function App(props) {
+  return (
+    <div className="todoapp stack-large">
+      <h1>TodoMatic</h1>
+      <form>
+        <h2 className="label-wrapper">
+          <label htmlFor="new-todo-input" className="label__lg">
+            What needs to be done?
+          </label>
+        </h2>
+        <input
+          type="text"
+          id="new-todo-input"
+          className="input input__lg"
+          name="text"
+          autoComplete="off"
+        />
+        <button type="submit" className="btn btn__primary btn__lg">
+          Add
+        </button>
+      </form>
+      <div className="filters btn-group stack-exception">
+        <button type="button" className="btn toggle-btn" aria-pressed="true">
+          <span className="visually-hidden">Show </span>
+          <span>all</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+        <button type="button" className="btn toggle-btn" aria-pressed="false">
+          <span className="visually-hidden">Show </span>
+          <span>Active</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+        <button type="button" className="btn toggle-btn" aria-pressed="false">
+          <span className="visually-hidden">Show </span>
+          <span>Completed</span>
+          <span className="visually-hidden"> tasks</span>
+        </button>
+      </div>
+      <h2 id="list-heading">
+        3 tasks remaining
+      </h2>
+      <ul
+        role="list"
+        className="todo-list stack-large stack-exception"
+        aria-labelledby="list-heading"
+      >
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-0" type="checkbox" defaultChecked={true} />
+            <label className="todo-label" htmlFor="todo-0">
+              Eat
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Eat</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Eat</span>
+            </button>
+          </div>
+        </li>
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-1" type="checkbox" />
+            <label className="todo-label" htmlFor="todo-1">
+              Sleep
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Sleep</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Sleep</span>
+            </button>
+          </div>
+        </li>
+        <li className="todo stack-small">
+          <div className="c-cb">
+            <input id="todo-2" type="checkbox" />
+            <label className="todo-label" htmlFor="todo-2">
+              Repeat
+            </label>
+          </div>
+          <div className="btn-group">
+            <button type="button" className="btn">
+              Edit <span className="visually-hidden">Repeat</span>
+            </button>
+            <button type="button" className="btn btn__danger">
+              Delete <span className="visually-hidden">Repeat</span>
+            </button>
+          </div>
+        </li>
+      </ul>
+    </div>
+  );
+}
+ +

次にpublic/index.htmlを開いて<title>要素のテキストを開いTodoMaticに変更します。こうすることでアプリ上部の<h1>と一致します。

+ +
<title>TodoMatic</title>
+ +

ブラウザが更新されると、次のように表示されます。

+ +

todo-maticアプリ、スタイルなし、乱雑なラベル、入力、ボタンの混乱を表示

+ +

まだ見た目が整っていなくて、機能もしていませんが、一旦問題はありません。すぐにスタイルを設定します。まず、このJSXと、それがユーザーストーリーにどのように対応するかを考えます。

+ + + +

このフォームによりタスクを作成できます。また、ボタンでフィルタリングもできます。見出しとリストは、それらを読むためのものです現在のところ、タスクを編集するためのUIはあまりよくありません。大丈夫です。後ほど書き足していきます。

+ +

アクセシビリティ

+ +

ここでいくつかの変わった属性に気付くかもしれません。例えば:

+ +
<button type="button" className="btn toggle-btn" aria-pressed="true">
+  <span className="visually-hidden">Show </span>
+  <span>all</span>
+  <span className="visually-hidden"> tasks</span>
+</button>
+ +

ここでは、aria-pressedボタンは2つの状態のいずれかであることができることを(スクリーンリーダーなど)技術的に伝えます(pressedunpressed)onoffの切替のように考えられます。trueの値を設定すると、デフォルトでボタンが押されます。

+ +

CSSが含まれていないため、このvisually-hiddenクラスはまだ意味がありません。ただし、スタイルを設定すると、このクラスの要素はすべて、目の見えるユーザーからは隠され、スクリーンリーダーのユーザーは引き続き使用できます。これは、目の見えるユーザーがこれらの単語を必要としないためです。それらは、ボタンを使用してスクリーンリーダーのユーザーに役立つ追加の視覚的コンテキストがないユーザーのために、ボタンの機能に関する詳細情報を提供するためにあります。

+ +

さらに下には<ul>要素があります

+ +
<ul
+  role="list"
+  className="todo-list stack-large stack-exception"
+  aria-labelledby="list-heading"
+>
+ +

role属性は、タグが表す要素の種類を説明するのに役立ちます。<ul>はデフォルトではリストのように扱われますが、これから追加するスタイルはその機能を壊します。この役割は、<ul>  要素の「リスト」の意味を復元します。これが必要な理由について詳しく知りたい場合は、Scott O'Haraの記事「Fixing Lists」チェックしてください

+ +

このaria-labelledby属性は、リストの見出しをその下にあるリストの目的を説明するラベルとして扱っていることを伝えます。この関連付けを行うと、リストの情報が豊富になり、スクリーンリーダーを通じてユーザーがリストの目的を理解しやすくなります。

+ +

最後に、リスト項目のラベルと入力には、JSXに固有のいくつかの属性があります。

+ +
<input id="todo-0" type="checkbox" defaultChecked={true} />
+<label className="todo-label" htmlFor="todo-0">
+  Eat
+</label>
+ +

<input/ >タグdefaultChecked属性は、デフォルトでこのチェックボックスをチェックするようにReactに指示します。通常のHTMLの場合と同様に、checkedを使用すると、Reactは、チェックボックスでのイベントの処理に関する警告をブラウザーコンソールに表示しますが、これは望ましくありません。とりあえず、これについてあまり心配しないでください。後でイベントを使用するときにこれについて説明します。

+ +

このhtmlFor属性は、HTMLで使用されるfor属性に対応しています。forは予約語であるため、JSXでは属性として使用できません。そのためReactはforの代わりにhtmlForを使用します。

+ +

ノート:

+ + + +

スタイルを実装する

+ +

次のCSSコードをに貼り付けて、src/index.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 > 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-group {
+  display: flex;
+  justify-content: space-between;
+}
+.btn-group > * {
+  flex: 1 1 49%;
+}
+.btn-group > * + * {
+  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"] > * {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.stack-small > * + * {
+  margin-top: 1.25rem;
+}
+.stack-large > * + * {
+  margin-top: 2.5rem;
+}
+@media screen and (min-width: 550px) {
+  .stack-small > * + * {
+    margin-top: 1.4rem;
+  }
+  .stack-large > * + * {
+    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 > * {
+  max-width: 50rem;
+  margin-left: auto;
+  margin-right: auto;
+}
+.todoapp > form {
+  max-width: 100%;
+}
+.todoapp > 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 > * {
+  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 > label::before,
+.c-cb > input[type="checkbox"] {
+  box-sizing: border-box;
+  top: -2px;
+  left: -2px;
+  width: 44px;
+  height: 44px;
+}
+.c-cb > input[type="checkbox"] {
+  -webkit-font-smoothing: antialiased;
+  cursor: pointer;
+  position: absolute;
+  z-index: 1;
+  margin: 0;
+  opacity: 0;
+}
+.c-cb > 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 > label::before {
+  content: "";
+  position: absolute;
+  border: 2px solid currentColor;
+  background: transparent;
+}
+.c-cb > input[type="checkbox"]:focus + label::before {
+  border-width: 4px;
+  outline: 3px dashed #228bec;
+}
+.c-cb > 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 > input[type="checkbox"]:checked + label::after {
+  opacity: 1;
+}
+ +

保存してブラウザーを確認すると、アプリに適切なスタイルが設定されているはずです。

+ +

まとめ

+ +

これで、todoリストアプリはまるで実際のアプリのように見えます。問題は、実際には何も動かないことです。次の章で修正を始めます!

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

In this module

+ + + + diff --git a/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html new file mode 100644 index 0000000000..4277a7ba9d --- /dev/null +++ b/files/ja/learn/tools_and_testing/client-side_javascript_frameworks/vue_getting_started/index.html @@ -0,0 +1,301 @@ +--- +title: Getting started with Vue +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +tags: + - Beginner + - Frameworks + - Installation + - JavaScript + - Learn + - client-side + - vue +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}
+ +

Now let's introduce Vue, the third of our frameworks. In this article we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.

+ + + + + + + + + + + + +
前提条件: +

Familiarity with the core HTML, CSS, and JavaScript languages, knowledge of the terminal/command line.

+ +

Vue components are written as a combination of JavaScript objects that manage the app's data and an HTML-based template syntax that maps to the underlying DOM structure. For installation, and to use some of the more advanced features of Vue (like Single File Components or render functions), you'll need a terminal with node + npm installed.

+
Objective:To setup a local Vue development environment, create a starter app, and understand the basics of how it works.
+ +

より明確な Vue

+ +

Vue is a modern JavaScript framework that provides useful facilities for progressive enhancement — unlike many other frameworks, you can use Vue to enhance existing HTML. This lets you use Vue as a drop-in replacement for a library like JQuery.

+ +

That being said, you can also use Vue to write entire Single Page Applications (SPAs). This allows you to create markup managed entirely by Vue, which can improve developer experience and performance when dealing with complex applications. It also allows you to take advantage of libraries for client-side routing and state management when you need to. Additionally, Vue takes a "middle ground" approach to tooling like client-side routing and state management. While the Vue core team maintains suggested libraries for these functions, they are not directly bundled into Vue. This allows you to select a different routing/state management library if they better fit your application.

+ +

In addition to allowing you to progressively integrate Vue into your applications, Vue also provides a progressive approach to writing markup. Like most frameworks, Vue lets you create reusable blocks of markup via components. Most of the time, Vue components are written using a special HTML template syntax. When you need more control than the HTML syntax allows, you can write JSX or plain JavaScript functions to define your  components.

+ +

As you work through this tutorial, you might want to keep the Vue guide and API documentation open in other tabs, so you can refer to them if you want more information on any sub topic.
+ For a good (but potentially biased) comparison between Vue and many of the other frameworks, see Vue Docs: Comparison with Other Frameworks.

+ +

取り付け

+ +

To use Vue in an existing site, you can drop one of the following <script> elements onto a page. This allows you to start using Vue on existing sites, which is why Vue prides itself on being a progressive framework. This is a great option when migrating an existing project using a library like JQuery to Vue. With this method, you can use a lot of the core features of Vue, such as the attributes, custom components, and data-management.

+ + + +

However, this approach has some limitations. To build more complex apps, you’ll want to use the Vue NPM package. This will let you use advanced features of Vue and take advantage of bundlers like WebPack. To make building apps with Vue easier, there is a CLI to streamline the development process. To use the npm package & the CLI you will need:

+ +
    +
  1. Node.js 8.11+ installed.
  2. +
  3. npm or yarn.
  4. +
+ +
+

Note: If you don't have the above installed, find out more about installing npm and Node.js here.

+
+ +

To install the CLI, run the following command in your terminal:

+ +
npm install --global @vue/cli
+ +

Or if you'd prefer to use yarn:

+ +
yarn global add @vue/cli
+ +

Once installed, to initialize a new project you can then open a terminal in the directory you want to create the project in, and run vue create <project-name>. The CLI will then give you a list of project configurations you can use. There are a few preset ones, and you can make your own. These options let you configure things like TypeScript, linting, vue-router, testing, and more.

+ +

We’ll look at using this below.

+ +

新規のプロジェクトを初期化する

+ +

To explore various features of Vue, we will be building up a sample todo list app. We'll begin by using the Vue CLI to create a new app framework to build our app into. Follow the steps below:

+ +
    +
  1. In terminal, cd to where you'd like to create your sample app, then run vue create moz-todo-vue.
  2. +
  3. Use the arrow keys and Enter to select the "Manually select features" option.
  4. +
  5. The first menu you’ll be presented with allows you to choose which features you want to include in your project. Make sure that "Babel" and "Linter / Formatter" are selected. If they are not, use the arrow keys and the space bar to toggle them on. Once they are selected, press Enter to proceed.
  6. +
  7. Next you’ll select a config for the linter / formatter. Navigate to "Eslint with error prevention only" and hit Enter again. This will help us catch common errors, but not be overly opinionated.
  8. +
  9. Next you are asked to configure what kind of automated linting we want. Select "Lint on save". This will check for errors when we save a file inside the project. Hit Enter to continue.
  10. +
  11. Now, you will select how we want your config files to be managed. "In dedicated config files" will put your config settings for things like ESLint into their own, dedicated files. The other option, "In package.json", will put all of your config settings into the app's package.json file. Select "In dedicated config files" and push Enter.
  12. +
  13. Finally, you are asked if you want to save this as a preset for future options. This is entirely up to you. If you like these settings over the existing presets and want to use them again, type y , otherwise type n.
  14. +
+ +

The CLI will now begin scaffolding out your project, and installing all of your dependencies.

+ +

If you've never run the Vue CLI before, you'll get one more question — you'll be asked to choose a package manager. You can use the arrow keys to select which one you prefer. The Vue CLI will default to this package manager from now on. If you need to use a different package manager after this, you can pass in a flag --packageManager=<package-manager>, when you run vue create.  So if you wanted to create the moz-todo-vue project with npm and you'd previously chosen yarn, you’d run vue create moz-todo-vue --packageManager=npm.

+ +
+

Note: We've not gone over all of the options here, but you can find more information on the CLI in the Vue docs.

+
+ +

プロジェクトの構造

+ +

If everything went successfully, the CLI should have created a series of files and directories for your project. The most significant ones are as follows:

+ + + +
+

Note: Depending on the options you select when creating a new project, there might be other directories present (for example, if you choose a router, you will also have a views directory).

+
+ +

.vue ファイル (単一ファイルコンポーネント)

+ +

Like in many front-end frameworks, components are a central part of building apps in Vue. These components let you break a large application into discrete building blocks that can be created and managed separately, and transfer data between each other as required. These small blocks can help you reason about and test your code.

+ +

While some frameworks encourage you to separate your template, logic, and styling code into separate files, Vue takes the opposite approach. Using Single File Components, Vue lets you group your templates, corresponding script, and CSS all together in a single file ending in .vue. These files are processed by a JS build tool (such as Webpack), which means you can take advantage of build-time tooling in your project. This allows you to use tools like Babel, TypeScript, SCSS and more to create more sophisticated components.

+ +

As a bonus, projects created with the Vue CLI are configured to use .vue files with Webpack out of the box. In fact, if you look inside the src folder in the project we created with the CLI, you'll see your first .vue file: App.vue.

+ +

Let's explore this now.

+ +

App.vue

+ +

Open your App.vue file — you’ll see that it has three parts: <template>, <script>, and <style>, which contain the component’s template, scripting, and styling information. All Single File Components share this same basic structure.

+ +

<template> contains all the markup structure and display logic of your component. Your template can contain any valid HTML, as well as some Vue-specific syntax that we'll cover later.

+ +
+

Note: By setting the lang attribute on the <template> tag, you can use Pug template syntax instead of standard HTML — <template lang="pug">. We'll stick to standard HTML through this tutorial, but it is worth knowing that this is possible.

+
+ +

<script> contains all of the non-display logic of your component. Most importantly, your <script> tag needs to have a default exported JS object. This object is where you locally register components, define component inputs (props), handle local state, define methods, and more. Your build step will process this object and transform it (with your template) into a Vue component with a render() function.

+ +

In the case of App.vue, our default export sets the name of the component to app and registers the HelloWorld component by adding it into the components property. When you register a component in this way, you're registering it locally. Locally registered components can only be used inside the components that register them, so you need to import and register them in every component file that uses them. This can be useful for bundle splitting/tree shaking since not every page in your app necessarily needs every component.

+ +
import HelloWorld from './components/HelloWorld.vue';
+
+export default {
+  name: 'app',
+  components: {
+    //You can register components locally here.
+    HelloWorld
+  }
+};
+ +
+

Note: If you want to use TypeScript syntax, you need to set the lang attribute on the <script> tag to signify to the compiler that you're using TypeScript — <script lang="ts">.

+
+ +

<style> is where you write your CSS for the component. If you add a scoped attribute — <style scoped> — Vue will scope the styles to the contents of your SFC. This works similar to CSS-in-JS solutions, but allows you to just write plain CSS.

+ +
+

Note: If you select a CSS pre-processor when creating the project via the CLI, you can add a lang attribute to the <style> tag so that the contents can be processed by Webpack at build time. For example, <style lang="scss"> will allow you to use SCSS syntax in your styling information.

+
+ +

アプリをローカルで実行する

+ +

The Vue CLI comes with a built-in development server. This allows you to run your app locally so you can test it easily without needing to configure a server yourself. The CLI adds a serve command to the project’s package.json file as an npm script, so you can easily run it.

+ +

In your terminal, try running npm run serve (or yarn serve if you prefer yarn). Your terminal should output something like the following:

+ +
INFO  Starting development server...
+98% after emitting CopyPlugin
+
+ DONE  Compiled successfully in 18121ms
+
+  App running at:
+  - Local:   <http://localhost:8080/>
+  - Network: <http://192.168.1.9:8080/>
+
+  Note that the development build is not optimized.
+  To create a production build, run npm run build.
+ +

If you navigate to the “local” address in a new browser tab (this should be something like http://localhost:8080 as stated above, but may vary based on your setup), you should see your app. Right now, it should contain a welcome message, a link to the Vue documentation, links to the plugins you added when you initialized the app with your CLI, and some other useful links to the Vue community and ecosystem.

+ +

default vue app render, with vue logo, welcome message, and some documentation links

+ +

いくつかの変更を加える

+ +

Let's make our first change to the app — we’ll delete the Vue logo. Open the App.vue file, and delete the <img> element from the template section:

+ +
<img alt="Vue logo" src="./assets/logo.png">
+ +

If your server is still running, you should see the logo removed from the rendered site almost instantly. Let’s also remove the HelloWorld component from our template.

+ +

First of all delete this line:

+ +
<HelloWorld msg="Welcome to Your Vue.js App"/>
+ +

If you save your App.vue file now, the rendered app will throw an error because we’ve registered the component but are not using it. We also need to remove the lines from inside the <script> element that import and register the component:

+ +

Delete these lines now:

+ +
import HelloWorld from './components/HelloWorld.vue'
+ +
components: {
+  HelloWorld
+}
+ +

Your rendered app should no longer show an error, just a blank page, as we currently have no visible content inside <template>.

+ +

Let’s add a new <h1> inside <div id="app">. Since we’re going to be creating a todo list app below, let's set our header text to "To-Do List". Add it like so:

+ +
<template>
+  <div id="app">
+    <h1>To-Do List</h1>
+  </div>
+</template>
+ +

App.vue will now show our heading, as you'd expect.

+ +

概要

+ +

Let's leave this here for now. We've learnt about some of the ideas behind Vue, created some scaffolding for our example app to live inside, inspected it, and made a few preliminary changes.

+ +

With a basic introduction out of the way, we'll now go further and build up our sample app, a basic Todo list application that allows us to store a list of items, check them off when done, and filter the list by all, complete, and incomplete todos.

+ +

In the next article we'll build our first custom component, and look at some important concepts such as passing props into it and saving its data state.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}

+ +

このモジュールでは

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html new file mode 100644 index 0000000000..26f98c400f --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/accessibility/index.html @@ -0,0 +1,624 @@ +--- +title: よくあるアクセシビリティの問題を扱う +slug: Learn/Tools_and_testing/Cross_browser_testing/Accessibility +tags: + - Accessibility + - Article + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Learn + - Testing + - Tools + - cross browser + - keyboard +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Accessibility +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/JavaScript","Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

次に、私たちはアクセシビリティに注意を向け、一般的な問題、簡単なテストの方法、そしてアクセシビリティの問題を見つけるための監査/自動化ツールの使い方を説明します。

+ + + + + + + + + + + + +
前提条件:コア HTMLCSS、および JavaScript 言語に精通していること。 高水準のクロスブラウザーテストの原則の理解。
目的:一般的なアクセシビリティの問題を診断し、それらを修正するための適切なツールとテクニックを使用できるようにすること。
+ +

アクセシビリティとは?

+ +

ウェブ技術のコンテキストでアクセシビリティと言うとき、ほとんどの人は即座にウェブサイトやアプリが障碍のある人にも使えるようにすることを考えます。 例えば、

+ + + +

しかし、アクセシビリティが単に障碍に関するものであると言うのは間違っています。 実際、アクセシビリティの目的は、高性能デスクトップコンピュータを使用しているユーザーだけでなく、できるだけ多くのコンテキストで、できるだけ多くのユーザーがウェブサイトやアプリを使用できるようにすることです。 極端な例には次のものが含まれます。

+ + + +

ある意味では、このモジュール全体がアクセシビリティについてのものです — クロスブラウザーテストは、あなたのサイトができるだけ多くの人々によって使用できることを確認します。 アクセシビリティとは?では、この記事よりも完全かつ徹底的にアクセシビリティを定義します。

+ +

とは言っても、この記事では、クロスブラウザーと障碍のある人々を取り巻く問題のテスト、そして彼らのウェブの使い方について説明します。 モジュール内の他の場所で、レスポンシブデザインパフォーマンスのような他の分野についてはすでに説明しました。

+ +
+

: ウェブ開発における多くのことと同様に、アクセシビリティは 100% 成功したかどうかではありません。 特にサイトが複雑になるにつれて、100% のアクセシビリティを全てのコンテンツに対して達成することはほとんど不可能です。 その代わりに、防御的なコーディングを介して、できるだけ多くの人があなたのコンテンツのできるだけ多くにアクセスできるようにし、ベストプラクティスに従うようにする努力をします。

+
+ +

よくあるアクセシビリティの問題

+ +

このセクションでは、従うべきベストプラクティスと共に、特定の技術と結びつけて、ウェブのアクセシビリティに関して生じる主な問題のいくつかと、サイトが正しい方向に進んでいるかどうかを確認するための簡単なテストについて、詳細を説明します。

+ +
+

: アクセシビリティは道徳的に正しいことであり、ビジネスには適していますし(多くの障碍のあるユーザー、モバイルデバイスのユーザーなどが重要な市場セグメントを提示しています)、ウェブ資産を障碍のある人々がアクセスできないようにすることは、世界の多くの地域で法律にも違反しています。 詳しくはアクセシビリティのガイドラインと法律を読んでください。

+
+ +

HTML

+ +

意味論的 HTML(要素が正しい目的のために使用されているもの)は箱から出してすぐにアクセスできます — そのようなコンテンツは晴眼者でも読めますし(CSS を使用して、テキストを小さくしすぎたり、隠したりするような愚かなことはしないでください)、スクリーンリーダー(文字通りウェブページをユーザーに読み上げるアプリ)などの支援技術でも使用可能になり、他の利点も付与されます。

+ +

意味論的構造

+ +

意味論的 HTML で最も重要なすばやい勝利は、コンテンツに見出しと段落の構造を使用することです。 これは、スクリーンリーダーのユーザーが、必要なコンテンツをすばやく見つけるために文書の見出しを道標として使用する傾向があるためです。 あなたのコンテンツが見出しを持っていない場合、彼らが得るのは、何かを見つけるための道標のないテキストの巨大な壁だけです。 悪い HTML と良いHTML の例としては、

+ +
<font size="7">私の見出し</font>
+<br><br>
+これが私の文書の最初のセクションです。
+<br><br>
+ここにも段落を追加します。
+<br><br>
+<font size="5">私の副見出し</font>
+<br><br>
+これが私の文書の最初のサブセクションです。 私は人々がこのコンテンツを見つけることができるようにしたいです!
+<br><br>
+<font size="5">私の2番目の副見出し</font>
+<br><br>
+これは私のコンテンツの2番目のサブセクションです。 私は最後のものよりも面白いと思います。
+ +
<h1>私の見出し</h1>
+
+<p>これが私の文書の最初のセクションです。</p>
+
+<p>ここにも段落を追加します。</p>
+
+<h2>私の副見出し</h2>
+
+<p>これが私の文書の最初のサブセクションです。 私は人々がこのコンテンツを見つけることができるようにしたいです!</p>
+
+<h2>私の2番目の副見出し</h2>
+
+<p>これは私のコンテンツの2番目のサブセクションです。 私は最後のものよりも面白いと思います。</p>
+ +

さらに、あなたのコンテンツはそのソース順で論理的に意味があるべきです — あなたは後で CSS を使い、いつでもそれを望んだ所に置くことができますが、最初から正しいソース順を手にするべきです。

+ +

テストとして、あなたはサイトの CSS をオフにして、CSS がなければそれがどれほど理解できるか見ることができます。 コードから CSS を取り除くだけでこれを手動で行うことができますが、最も簡単な方法はブラウザー機能を使用することです。 例えば、

+ + + +

ネイティブなキーボード・アクセシビリティを使う

+ +

特定の HTML 機能はキーボードのみを使用して選択できます — これはデフォルトの動作で、ウェブの初期の頃から使用可能です。 この機能を持つ要素は、ユーザーがウェブページと対話することを可能にする一般的なもの、すなわちリンク、{{htmlelement("button")}}、そして {{htmlelement("input")}} のようなフォーム要素です。

+ +

native-keyboard-accessibility.html の例を使ってこれを試すことができます(ソースコードを見る) — これを新しいタブで開いて、そして Tab キーを押してみてください。 数回押すと、タブフォーカスがさまざまなフォーカス可能な要素を通過し始めます。 どの要素がフォーカスされているかわかるように、フォーカスされた要素には全てのブラウザーでハイライトされたデフォルトのスタイルが与えられます(ブラウザーによって若干異なります)。

+ +

+ +

次に Enter / Return を押してフォーカスのあるリンクをたどるか、ボタンを押すか(ボタンにメッセージを知らせるための JavaScript が含まれています)、テキスト入力にテキストを入力するためにタイプし始めることができます(他のフォーム要素には異なるコントロールがあります。 例えば、{{htmlelement("select")}} 要素では、上下の矢印キーを使用してそのオプションを表示したり切り替えたりできます)。

+ +

ブラウザーが異なれば、使用可能なキーボードコントロールオプションも異なることに注意してください。 最近のほとんどのブラウザーは上記のタブパターンに従いますが(フォーカス可能な要素を逆方向に移動するために Shift + Tab を押すこともできます)、次のようにブラウザーによっては独自の特徴があります。

+ + + +
+

重要: あなたが書く新しいページのどれでも、この種のテストを実行するべきです — 機能がキーボードによってアクセスできることを確認してください。

+
+ +

この例では、正しい仕事に正しい意味論的要素を使用することの重要性を強調しています。 任意の要素を、CSS でリンクやボタンのように見せたり、JavaScript でリンクやボタンのように振る舞うようにスタイルすることは可能ですが、実際にはリンクやボタンにはならず、あなたはこれらの要素が無料で与えるアクセシビリティの多くを失うでしょう。 あなたがそれを避けることができるならばしないでください。

+ +

もう1つのヒント — 次の例に示すように、{{cssxref(":focus")}} 疑似クラスを使用して、フォーカス可能要素のフォーカス時の外観をコントロールできます。 フォーカスとホバーのスタイルを倍増するのは良い考えです。 それにより、マウスやキーボードを使用しているかどうかに関わらず、ユーザーがコントロールをアクティブにしたときに何かが行われるという視覚的な手がかりを得ることができます。

+ +
a:hover, input:hover, button:hover, select:hover,
+a:focus, input:focus, button:focus, select:focus {
+  font-weight: bold;
+}
+ +
+

: CSS を使用してデフォルトのフォーカススタイルを取り除く場合は、デザインに適した他のスタイルに置き換えてください — これは非常に有用なアクセシビリティツールであり、取り除くべきではありません。

+
+ +

キーボード・アクセシビリティを組み込む

+ +

時にはキーボード・アクセシビリティを失うことが避けられないこともあります。 意味論的にあまり良くないサイトを継承したかもしれませんし(<div> で作られたボタンを生成する恐ろしい {{glossary("CMS")}} に行き着くかもしれません)、HTML5 の {{htmlelement("video")}} 要素のようにキーボード・アクセシビリティが組み込まれていない複雑なコントロールを使用しているかもしれません(驚くべきことに、Opera は <video> 要素のデフォルトのブラウザーコントロールをタブ操作できる唯一のブラウザーです)。 次のようないくつかの選択肢があります。

+ +
    +
  1. <button> 要素(デフォルトでタブ移動可能)と JavaScript を使用してカスタムコントロールを作成し、それらの機能を関連付けます。 これについての良い例は、クロスブラウザーのビデオプレーヤーの作成を参照してください。
  2. +
  3. JavaScript でキーボードショートカットを作成すると、キーボードの特定のキーを押すことで機能をアクティブにできます。 あらゆる目的に適応できるゲーム関連の例については、デスクトップのマウスとキーボードのコントロールを参照してください。
  4. +
  5. 偽のボタンの振る舞いのために、いくつかの興味深い戦術を使ってください。 例えば、fake-div-buttons.html の例を見てください(ソースコードを見る)。 ここでは、それぞれの属性に tabindex="0" という属性を与えることで(もっと有用な詳細については WebAIM の tabindex の記事(英語)を見てください)、偽の <div> ボタンにフォーカスできるようにしました(タブを介すことも含む)。 これにより、ボタンにタブ移動することはできますが、Enter / Return キーでそれらをアクティブにすることはできません。 そのためには、次のちょっとした JavaScript トリックを追加する必要があります。 +
    document.onkeydown = function(e) {
    +  if(e.keyCode === 13) { // The Enter/Return key
    +    document.activeElement.onclick(e);
    +  }
    +};
    + ここでは、document オブジェクトにリスナーを追加して、キーボードのボタンが押されたことを検出します。 イベントオブジェクトの keyCode プロパティを使ってどのボタンが押されたかをチェックし、Return / Enter と一致するキーコードであれば、document.activeElement.onclick() を使用してボタンの onclick ハンドラに格納されている関数を実行します。 activeElement は現在ページにフォーカスしている要素を与えます。
  6. +
+ +
+

: この手法は、イベントハンドラ・プロパティ(onclick など)を使ってオリジナルのイベントハンドラを設定した場合にのみ機能します。 addEventListener は機能しません。 これは、機能を再構築するための非常に面倒な作業です。 それに他にも問題があるはずです。 そもそも正しい要素を正しい仕事に使うほうがよいでしょう。

+
+ +

代替テキスト

+ +

代替テキストは、アクセシビリティにとって非常に重要です — ある人が視覚障碍または聴覚障碍を抱えているためにコンテンツを見たり聞いたりすることができなくなると、これが問題になります。 最も単純な代替テキストは、控え目な {{htmlattrxref("alt","img")}} 属性で、関連するコンテンツを含む全ての画像に含めるべきです。 これはスクリーンリーダーが拾ってユーザーに読み上げるために、ページ上にその意味と内容をうまく伝える画像の説明を含むべきです。

+ +
+

: 詳しくは、代替テキストをお読みください。

+
+ +

欠落している代替テキストは、アクセシビリティ{{anch("Auditing tools","監査ツール")}}を使用するなど、さまざまな方法でテストできます。

+ +

代替テキストは、動画と音声のコンテンツにとってはもう少し複雑です。 テキストトラック(字幕など)を定義し、動画の再生時にそれらを {{htmlelement("track")}} 要素と WebVTT 形式の形式で表示する方法があります(詳細なチュートリアルについては、HTML5 の動画へのキャプションと字幕の追加を参照してください)。 これらの機能に対するブラウザーの互換性はかなり良いのですが、音声用の代替テキストを提供したり、古いブラウザーをサポートしたりする場合は、ページのどこかや別のページに提示した単純なテキストトランスクリプトをお勧めします。

+ +

要素の関係とコンテキスト

+ +

HTML には、他に存在しない要素間のコンテキストと関係を提供するように設計された特定の機能とベストプラクティスがあります。 最も一般的な3つの例は、リンク、フォームラベル、およびデータ表です。

+ +

アクセス可能なリンクテキストの鍵は、スクリーンリーダーを使用している人々が、ページ上の全てのリンクのリストを引き出すという共通の機能を使用することが多いということです。 この場合、リンクテキストはコンテキスト外で意味を成す必要があります。 例えば、「ここをクリック」、「ここをクリック」などのラベルが付いたリンクのリストは、アクセシビリティにとって本当に悪いものです。 リンクテキストはコンテキスト内でもコンテキスト外でも意味を成すのが得策です。

+ +

次に、フォームの {{htmlelement("label")}} 要素は、フォームをアクセス可能にすることを可能にする中心的な機能の1つです。 フォームの悩みは、各フォーム入力にどのデータを入力するべきかを示すためにラベルが必要なことです。 各ラベルを {{htmlelement("label")}} 内に含めて相方のフォーム入力に明確にリンクする必要があり(各 <label>for 属性値はフォーム要素の id 値と一致する必要があります)、ソース順が完全に論理的ではなくても(これは公平であるべきです)、それは意味があります。

+ +
+

:リンクテキストとフォームラベルの詳細については、わかりやすいテキストラベルを参照してください。

+
+ +

最後に、データ表について簡単に説明します。 基本的なデータ表は非常に簡単なマークアップで書くことができますが(bad-table.html のライブソースを見る)、問題があります — スクリーンリーダーのユーザーがデータのグループとして行や列を関連付ける方法はありません — これを行うには、ヘッダー行がどれであるか、そしてそれらが行、列などを見出ししているかどうかを知る必要があります。 これはそのような表に対しては視覚的にしかできません。

+ +

代わりに punk-bands-complete.html の例(ライブソース)を見ると、表のヘッダー({{htmlelement("th")}} と scope 属性)、{{htmlelement("caption")}} 要素など、いくつかのアクセシビリティ補助機能が働いていることがわかります。

+ +
+

: アクセス可能な表の詳細については、アクセス可能なデータ表を参照してください。

+
+ +

CSS

+ +

CSS は HTML よりもはるかに少ない基本的なアクセシビリティ機能を提供する傾向がありますが、それでも誤って使用された場合、それはアクセシビリティにちょうど同じくらい多くの損害を与えることができます。 CSS に関するアクセシビリティのヒントをいくつかすでに説明しました。

+ + + +

考慮すべき点が他にもいくつかあります。

+ +

色とカラーコントラスト

+ +

ウェブサイトの配色を選択するときは、テキスト(前景)のカラーコントラストが背景色とよく合うことを確認するべきです。 あなたのデザインはかっこいいかもしれませんが、色覚異常のような視覚障碍を持つ人々がコンテンツを読むことができないならば、それは良くありません。 配色に十分なコントラストがあるかどうかチェックするために WebAIM のカラーコントラストチェッカー(英語)のようなツールを使ってください。

+ +

もう1つのヒントは、道標や情報を色だけに頼らないようにすることです。 これは、色が見えない人には良くないでしょう。 例えば、必須のフォームフィールドを赤でマークする代わりに、赤いアスタリスクでマークします。

+ +
+

: コントラスト比が高いと、光沢のある画面を備えたスマートフォンやタブレットを使用している人は誰でも、日光のような明るい環境にいるときにページを読みやすくなります。

+
+ +

コンテンツを隠す

+ +

ビジュアルデザインでは、全てのコンテンツを一度に表示する必要がない多くの実例があります。 例えば、タブ付き情報ボックスの例ソースコードを見る)には3つの情報パネルがありますが、それらを重ねて配置し、それぞれを表示するためにクリックできるタブを提供しています(キーボードからもアクセス可能です — 代わりに TabEnter / Return を使って選択することもできます)。

+ +

+ +

スクリーンリーダーのユーザーは、このことを気にしません — コンテンツのソース順が意味を成す限り幸せで、全てに到達できます。 絶対配置(この例で使用されているような)は一般に視覚効果のためにコンテンツを隠す最も良いメカニズムの1つとして見られます、なぜならそれはスクリーンリーダーがそれに到達するのを止めないからです。

+ +

一方で、スクリーンリーダーからコンテンツを隠すので、{{cssxref("visibility")}}:hidden や {{cssxref("display")}}:none は使用しないでください。 正当な理由があるのでなければ、なぜこのコンテンツをスクリーンリーダーから隠したいのでしょうか。

+ +
+

: スクリーンリーダーのユーザーには見えないコンテンツ(英語)には、このトピックに関するもっと有用な詳細があります。

+
+ +

JavaScript

+ +

JavaScript はアクセシビリティに関して CSS と同じ種類の問題を抱えています — それが悪用されたり、乱用されたりするとアクセシビリティの災害になる可能性があります。 JavaScript に関連するアクセシビリティの問題、主に意味論的 HTML の分野についてはすでに示唆しています — 例えば、リンクやボタンを適切に使用するなど、適切な意味論的 HTML を使用して機能を実装するべきです。 可能であれば、JavaScript コードで <div> 要素を使用して機能を偽造しないでください — エラーが発生しやすく、HTML の無料機能を使用するよりも手間がかかります。

+ +

単純な機能

+ +

一般的に単純な機能は HTML だけで適切に機能するはずです — JavaScript は機能を強化するためにのみ使用されるべきであり、完全には組み込みません。 JavaScript の良い使い方には次のものが含まれます。

+ + + +
+

: WebAIM のアクセス可能な JavaScript(英語)は、アクセス可能な JavaScript の考慮事項に関する有用な詳細をいくつか提供します。

+
+ +

より複雑な JavaScript による実装はアクセシビリティに問題をもたらす可能性があります — できる限りのことをする必要があります。 例えば、WebGL を 100% を使用して書かれた複雑な 3D ゲームを視覚障碍者が利用できるようにすることは期待できませんが、マウス以外のユーザーが使用できるようにキーボードコントロールを実装し、色覚異常のある人にも使えるように配色に十分なコントラストがあるようにすることができます。

+ +

複雑な機能

+ +

アクセシビリティにとって問題となる主な分野の1つは、(日付の選択のような)複雑なフォームコントロールを含む複雑なアプリと、頻繁に増分的に更新される動的コンテンツです。

+ +

ネイティブではない複雑なフォームコントロールは、ネストされた <div> が多数含まれる傾向があり、ブラウザーがデフォルトでそれらをどう処理するかわからないため、問題があります。 自分でそれらを考案しているのなら、それらがキーボードからアクセスできることを確認する必要があります。 何らかのサードパーティ製フレームワークを使用している場合は、利用可能なオプションを慎重に検討して、飛びつく前にそれらがどれほどアクセス可能かを確認してください。 Bootstrap は、アクセシビリティにはかなり適しているように見えます。 例えば、Rhiana Heath による Bootstrap をもう少しアクセス可能にする(英語)では、その問題のいくつかを調べ(主にカラーコントラストに関連した)、いくつかの解決策を検討しています。

+ +

定期的に更新される動的コンテンツは、スクリーンリーダーのユーザーがそれを見逃す可能性があるため、特に突然更新される場合は問題になる可能性があります。 XMLHttpRequest または Fetch を使用して定期的に更新されるメインコンテンツパネルを備えた単一ページのアプリがある場合、スクリーンリーダーのユーザーはそれらの更新を見逃す可能性があります。

+ +

WAI-ARIA

+ +

そのような複雑な機能を使用する必要がありますか、それともごく普通の意味論的 HTML が代わりにやりますか? 複雑なものが必要な場合は、WAI-ARIA(Accessible Rich Internet Applications)を使用することを検討するべきです。 これは、ほとんどのブラウザーやスクリーンリーダーが理解できる複雑なフォームコントロールや更新パネルのような項目に(新しい HTML 属性の形式で)意味論を提供する仕様です。

+ +

複雑なフォームウィジェットを扱うには、さまざまな要素がウィジェット内でどのような役割を担っているか(例えば、タブなのか、タブパネルなのか)を示す role、コントロールが無効かどうかを示す aria-disabled などの ARIA 属性を使う必要があります。

+ +

定期的に更新されるコンテンツのリージョンを扱うには、更新されるリージョンを識別する aria-live 属性を使用できます。 その値は、次のようにスクリーンリーダーがどれほど緊急にそれを読み上げるべきかを示します。

+ + + +

これが一例です。

+ +
<p><span id="LiveRegion1" aria-live="polite" aria-atomic="false"></span></p>
+ +

Freedom Scientific の ARIA(Accessible Rich Internet Applications)のライブリージョン(英語)の例で実行中の例を見ることができます — 強調表示された段落はその内容を10秒ごとに更新し、スクリーンリーダーはユーザーにこれを読み上げるべきです。 ARIA のライブリージョン - Atomic(英語)は別の有用な例を提​​供しています。

+ +

ここでは WAI-ARIA を詳細にカバーするためのスペースはありません。 WAI-ARIA の基本でもっと詳しく学ぶことができます。

+ +

アクセシビリティツール

+ +

今まで(キーボードナビゲーションやカラーコントラストチェッカーのような)いくつかのテストのテクニックを含め、さまざまなウェブ技術に対するアクセシビリティの考慮事項について説明してきました。 次に、アクセシビリティのテストを実行するときに使用できる他のツールを見てみましょう。

+ +

監査ツール

+ +

あなたのウェブページを指さすことができる利用可能な監査ツールがいくつかあります。 それらはページを見て、ページに存在するアクセシビリティ問題のリストを返すでしょう。 例えば次のものが含まれます。

+ + + +

Tenon を使って例を見てみましょう。

+ +
    +
  1. Tenon のホームページ(英語)に行きます。
  2. +
  3. bad-semantics.html の例の URL(または分析したい別のウェブページの URL)をページ上部のテキスト入力に入力して [Analyze Your Webpage] を押します。
  4. +
  5. 次に示すように、error/description のセクションが見つかるまで下にスクロールします。
  6. +
+ +

+ +

また、Tenon をプログラム的に使用するための API と同様に、探索できるいくつかのオプション(ページ上部の近くにある [Show Options] リンクを参照)もあります。

+ +
+

: このようなツールは、アクセシビリティの問題を全て自分で解決するのに十分ではありません。 全体像を把握するには、これらの組み合わせ、知識と経験、ユーザーテストなどが必要です。

+
+ +

自動化ツール

+ +

Deque の aXe ツール(英語)は、前述した監査ツールよりも少しばかり進化しています。 他のものと同様に、ページをチェックしてアクセシビリティエラーを返します。 その最もすぐに役立つ形式は、おそらく次のブラウザー拡張機能です。

+ + + +

これらはブラウザー開発者ツールにアクセシビリティタブを追加します。 例えば、Firefox 用のバージョンをインストールし、それを使用して bad-table.html の例を監査すると、次の結果が得られます。

+ +

+ +

aXe は npm を使ってもインストール可能で、GruntGulp のようなタスクランナー、SeleniumCucumber のような自動化フレームワーク、Jasmin のような単体テストフレームワークなどと統合することができます(やはり、詳細についてはメインの aXe ページ(英語)を参照してください)。

+ +

スクリーンリーダー

+ +

重度の視覚障碍者がウェブをどのように使用しているかに慣れるには、スクリーンリーダーを使ってテストする価値があります。 次のように利用可能なスクリーンリーダーは多数あります。

+ + + +

一般的に、スクリーンリーダーはホストオペレーティングシステム上で動作する独立したアプリで、ウェブページだけでなく他のアプリのテキストも読むことができます。 これは必ずしもそうとは限りませんが(ChromeVox はブラウザーの拡張機能です)、通常はそうです。 スクリーンリーダーは少し異なる方法で動作し、異なるコントロールを持つ傾向があるので、全ての詳細を得るためにはあなたが選んだスクリーンリーダーのドキュメントを参照しなければなりません — と言っても、それらは全て基本的に同じような方法で機能します。

+ +

いくつかの異なるスクリーンリーダーを使っていくつかのテストを行い、それらがどのように機能するのか、またどのようにテストするのかについての一般的な考えを説明しましょう。

+ +
+

: WebAIM のスクリーンリーダーの互換性のための設計(英語)では、スクリーンリーダーの使用方法とスクリーンリーダーに最適な機能についての役立つ情報が提供されています。 いくつかの興味深いスクリーンリーダーの使用統計については、第6回スクリーンリーダーのユーザー調査の結果(英語)も参照してください。

+
+ +

VoiceOver

+ +

VoiceOver(VO)は Mac / iPhone / iPad には無料で含まれているので、あなたが Apple 製品を使っているならそれはデスクトップ/モバイルでテストするのに役に立ちます。 ここでは、MacBook Pro の Mac OS X でテストします。

+ +

オンにするには、Cmd + Fn + F5 を押します。 今までに VO を使ったことがない場合は、ようこそ画面が表示され、そこで VO を起動するかどうかを選択できます。 また、使い方を学ぶためにかなり役に立つチュートリアルを実行することもできます。 再びオフにするには、もう一度 Cmd + Fn + F5 を押します。

+ +
+

: チュートリアルは少なくとも一度は実行するべきです — これは VO を学ぶ上で非常に便利な方法です。

+
+ +

VO がオンになっていると、ディスプレイはほぼ同じに見えますが、画面の左下に、現在選択されている VO に関する情報を含む黒いボックスが表示されます。 現在の選択範囲も黒枠で強調表示されます — この強調表示は VO カーソルと呼ばれます。

+ +

+ +

VO を使用するには、「VO 修飾キー」を多用します — これは、実際の VO キーボードショートカットに加えて、それらを機能させるために押す必要があるキーまたはキーの組み合わせです。 このような修飾キーを使用するのは、スクリーンリーダーに共通で、他のコマンドとコマンドが衝突しないようにするためです。 VO の場合、修飾キーは CapsLock または Ctrl + Option のいずれかです。

+ +

VO にはたくさんのキーボードコマンドがありますので、ここではそれら全てをリストしません。 ウェブページのテストに必要な基本的なものは、次の表のとおりです。 キーボードショートカットでは、VO は「VoiceOver 修飾キー」を意味します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
最も一般的な VoiceOver のキーボードショートカット
キーボードショートカット説明
VO + 矢印キーVO カーソルを上下左右に移動します。
VO + スペースバーVO カーソルで強調表示されている項目を選択/アクティブ化します。 これには、ローター(下記参照)で選択した項目が含まれます。
VO + Shift + 下矢印(HTML の表やフォームなどの)項目のグループ内に入ります。 グループ内に入ると、通常どおり上記のコマンドを使用してそのグループ内の項目を移動して選択できます。
VO + Shift + 上矢印グループから出ます。
VO + C(表内の場合)現在の列のヘッダーを読み上げます。
VO + R(表内の場合)現在の行のヘッダーを読み上げます。
VO + C + C(2つの連続した C)(表内の場合)ヘッダーを含む現在の列全体を読み上げます。
VO + R + R(2つの連続した R)(表内の場合)各セルに対応するヘッダーを含め、現在の行全体を読み上げます。
VO + 左矢印VO + 右矢印(日付の選択や時刻の選択などの一部の水平オプション内の場合)オプション間を移動します。
VO + 上矢印VO + 下矢印(日付の選択や時刻の選択などの一部の水平オプション内の場合)現在のオプションを変更します。
VO + U簡単にナビゲーションできるように、見出し、リンク、フォームコントロールなどのリストを表示するローターを使用します。
VO + 左矢印VO + 右矢印(ローター内の場合)ローターで利用可能な異なるリスト間を移動します。
VO + 上矢印VO + 下矢印(ローター内の場合)現在のローターリスト内の異なる項目間を移動します。
Esc(ローター内の場合)ローターを終了します。
Ctrl(VO が話している場合)読み上げを一時停止/再開します。
VO + Z読み上げの最後の部分をやり直します。
VO + DMac の Dock に入るので、その中で実行するアプリを選択できます。
+ +

これはたくさんのコマンドのように思えますが、慣れればそれほど悪くはありません。 VO は、特定の場所でどのコマンドを使用するかについて定期的に注意を促します。 今は VO で遊びましょう。 その後、{{anch("Screenreader testing","スクリーンリーダーのテスト")}}のセクションで例のいくつかを試してみることができます。

+ +

NVDA

+ +

NVDA は Windows 専用で、インストールする必要があります。

+ +
    +
  1. nvaccess.org からダウンロードしてください。 寄付をするか無料でダウンロードするかを選択できます。 ダウンロードできるようになる前にあなたのメールアドレスを与える必要もあるでしょう。
  2. +
  3. ダウンロードしたら、インストールします — インストーラをダブルクリックし、ライセンスに同意して指示に従います。
  4. +
  5. NVDA を起動するには、プログラムファイル/ショートカットをダブルクリックするか、キーボードショートカットの Ctrl + Alt + N を使用します。 起動すると NVDA にようこそダイアログが表示されます。 ここでは、いくつかのオプションから選択し、次に [OK] ボタンを押して作業を進めます。
  6. +
+ +

これで NVDA はあなたのコンピュータ上でアクティブになります。

+ +

NVDA を使用するには、「NVDA 修飾キー」を多用します — これは、実際の NVDA のキーボードショートカットに加えて、それらを機能させるために押す必要があるキーです。 このような修飾キーを使用するのは、スクリーンリーダーに共通で、他のコマンドとコマンドが衝突しないようにするためです。 NVDA の場合、修飾キーは Insert(デフォルト)、または CapsLock([OK] を押す前に NVDA へようこそダイアログボックスの最初のチェックボックスをオンにして選択できます)のいずれかになります。

+ +
+

: NVDA は、VoiceOver よりも、それがどこにあるのか、また何をしているのかを強調する方法という点では微妙です。 あなたが見出しやリストなどをスクロールしているとき、あなたが選択している項目は一般的に微妙なアウトラインでハイライトされますが、これはいつも全てのことに当てはまるわけではありません。 完全に迷子になった場合は、Ctrl + F5 を押して現在のページを更新し、もう一度上から始めることができます。

+
+ +

NVDA にはたくさんのキーボードコマンドがありますので、ここではそれら全てをリストしません。 ウェブページのテストに必要な基本的なものは、次の表のとおりです。 キーボードショートカットでは、NVDA は「NVDA 修飾キー」を意味します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
最も一般的な NVDA のキーボードショートカット
キーボードショートカット説明
NVDA + Q起動している NVDA を再びオフにします。
NVDA + 上矢印現在行を読み上げます。
NVDA + 下矢印現在位置から読み上げを始めます。
上矢印下矢印、または Shift + TabTabページ内の前/次の項目に移動して、それを読み上げます。
左矢印右矢印現在の項目の前/次の文字に移動して、それを読み上げます。
Shift + HH前/次の見出しに移動して、それを読み上げます。
Shift + KK前/次のリンクに移動して、それを読み上げます。
Shift + DD前/次の文書のランドマーク(<nav> など)に移動して、それを読み上げます。
Shift + 1616前/次の見出し(レベル 1 〜 6)に移動して読み上げます。
Shift + FF前/次のフォーム入力に移動して、それにフォーカスを当てます。
Shift + TT前/次のデータ表に移動して、それにフォーカスを当てます。
Shift + BB前/次のボタンに移動して、ラベルを読み上げます。
Shift + LL前/次のリストに移動して、その最初のリスト項目を読み上げます。
Shift + II前/次のリスト項目に移動して、それを読み上げます。
Enter / Return(リンク/ボタンまたは他のアクティブ化可能項目が選択されている場合)項目をアクティブ化します。
NVDA + スペースバー(フォームが選択されている場合)個々の項目を選択できるようにフォーム内に入るか、すでにフォームに入っている場合はフォームから出ます。
Shift + TabTab(フォーム内の場合)フォーム入力間を移動します。
上矢印下矢印(フォーム内の場合)フォーム入力の値を変更します(選択ボックスなどの場合)。
スペースバー(フォーム内の場合)選択値を選択します。
Ctrl + Alt + 矢印キー(表が選択されている場合)表のセル間を移動します。
+ +

スクリーンリーダーのテスト

+ +

スクリーンリーダーを使用することに慣れてきましたが、スクリーンリーダーがどのようにウェブページの良い機能と悪い機能に対処するかを理解するために、簡単なアクセシビリティテストを行うためにスクリーンリーダーを使用したいと思います。

+ + + +

ユーザーテスト

+ +

上記のように、あなたはあなたのサイトのアクセシビリティ問題を決定するために自動化されたツールだけに頼ることはできません。 テスト計画を立てる際には、可能であればアクセシビリティユーザーグループをいくつか含めることをお勧めします(詳細については、コースの前半のユーザーテストのセクションを参照してください)。 必要に応じて、スクリーンリーダーを使用するユーザー、キーボードを使用するユーザー、聴覚を持たないユーザー、および他のグループも参加してください。

+ +

アクセシビリティテストのチェックリスト

+ +

次のリストは、プロジェクトで推奨されるアクセシビリティテストを確実に実行したことを確認するためのチェックリストです。

+ +
    +
  1. HTML が意味論的にできるだけ正しいことを確認してください。 監査ツールを使用して、それを検証することは良いスタートです。
  2. +
  3. CSS がオフになっているときにコンテンツが意味をなすことを確認してください。
  4. +
  5. 機能がキーボードからアクセス可能であることを確認してください。 TabReturn / Enter などを使ってテストします。
  6. +
  7. テキスト以外のコンテンツに代替テキストがあることを確認してください。 監査ツールはそのような問題を捉えるのに適しています。
  8. +
  9. 適切なチェックツールを使用して、サイトのカラーコントラストが許容範囲内であることを確認してください。
  10. +
  11. 隠されたコンテンツがスクリーンリーダーに見えるようにしてください。
  12. +
  13. 可能な限り JavaScript がなくても機能が使えることを確認してください。
  14. +
  15. 適切な場合は、ARIA を使用してアクセシビリティを向上させます。
  16. +
  17. 監査ツールを通してサイトを運営してください。
  18. +
  19. スクリーンリーダーでテストしてください。
  20. +
  21. あなたが行ったことを言うために、あなたのサイトのどこかに見つけることができるアクセシビリティの方針/声明を含めてください。
  22. +
+ +

助けを探す

+ +

あなたがアクセシビリティに関して遭遇するであろう他の多くの問題があります。 本当に知っておくべき最も重要なことは、オンラインで答えを見つける方法です。 HTML と CSS の記事の助けを探すのセクションを参考にしてください。

+ +

まとめ

+ +

たぶん、この記事はあなたが遭遇するかもしれない主なアクセシビリティ問題とそれらをどうやってテストして克服するかについての良い下地を与えたでしょう。

+ +

次の記事では、機能の検出について詳しく説明します。

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/JavaScript","Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール内の文書

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html new file mode 100644 index 0000000000..98bf8d9394 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/automated_testing/index.html @@ -0,0 +1,620 @@ +--- +title: 自動テストのイントロダクション +slug: Learn/Tools_and_testing/Cross_browser_testing/Automated_testing +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Automated_testing +--- +
 {{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

1日に数回、複数のブラウザやデバイスで手動でテストを実行すると、面倒で時間がかかる場合があります。これを効率的に処理するには、自動化ツールに慣れておく必要があります。この記事では、利用可能なもの、タスクランナーの使い方、そして Sauce Labs や Browser Stack などの市販のブラウザテスト自動化アプリケーションの基本的な使い方を見ていきます。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:自動テストにはどのようなものが含まれているのか、それがどのようにあなたの生活を楽にすることができるのか、そして物事を楽にするいくつかの商用製品をどのように利用するかの理解を提供する。
+ +

Automation makes things easy

+ +

Throughout this module we have detailed loads of different ways in which you can test your websites and apps, and explained the sort of scope your cross-browser testing efforts should have in terms of what browsers to test, accessibility considerations, and more. Sounds like a lot of work, doesn't it?

+ +

We agree — testing all the things we've looked at in previous articles manually can be a real pain. Fortunately, there are tools to help us automate some of this pain away. There are two main ways in which we can automate the tests we've been talking about in this module:

+ +
    +
  1. Use a task runner such as Grunt or Gulp, or npm scripts to run tests and clean up code during your build process. This is a great way to perform tasks like linting and minifying code, adding in CSS prefixes or transpiling nascent JavaScript features for maximum cross-browser reach, and so on.
  2. +
  3. Use a browser automation system like Selenium to run specific tests on installed browsers and return results, alerting you to failures in browsers as they crop up. Commercial cross-browser testing apps like Sauce Labs and Browser Stack are based on Selenium, but allow you to access their set up remotely using a simple interface, saving you the hassle of setting up your own testing system.
  4. +
+ +

We will look at how to set up your own Selenium-based testing system in the next article. In this article, we'll look at how to set up a task runner, and use the basic functionality of commercial systems like the ones mentioned above.

+ +
+

Note: the above two categories are not mutually exclusive. It is possible to set up a task runner to access a service like Sauce Labs via an API, run cross browser tests, and return results. We will look at this below as well.

+
+ +

Using a task runner to automate testing tools

+ +

As we said above, you can drastically speed up common tasks such as linting and minifying code by using a task runner to run everything you need to run automatically at a certain point in your build process. For example, this could be every time you save a file, or at some other point. Inside this section we'll look at how to automate task running with Node and Gulp, a beginner-friendly option.

+ +

Setting up Node and npm

+ +

Most tools these days are based on {{Glossary("Node.js")}}, so you'll need to install it from nodejs.org:

+ +
    +
  1. Download the installer for your system from the above site. (If you already have Node and npm installed, jump to point 4)
  2. +
  3. Install it like you would any other program. Note that Node comes with Node Package Manager (npm), which allows you to easily install packages, share your own packages with others, and run useful scripts on your projects.
  4. +
  5. Once the install completes, test that node is installed by typing the following into the terminal, which returns the installed versions of Node and npm: +
    node -v
    +npm -v
    +
  6. +
  7. If you've got Node/npm already installed, you should update them to their latest versions. To update Node, the most reliable way is to download and install an updated installer package from their website (see link above). To update npm, use the following command in your terminal: +
    npm install npm@latest -g
    +
  8. +
+ +
+

Note: If the above command fails with permissions errors, Fixing npm permissions should sort you out.

+
+ +

To start using Node/npm-based packages on your projects, you need to set up your project directories as npm projects. This is easy to do.

+ +

For example, let's first create a test directory to allow us to play without fear of breaking anything.

+ +
    +
  1. Create a new directory somewhere sensible with using your file manager UI, or by navigating to the location you want and running the following command: +
    mkdir node-test
    +
  2. +
  3. To make this directory an npm project, you just need to go inside your test directory and initialize it, with the following: +
    cd node-test
    +npm init
    +
  4. +
  5. This second command will ask you many questions to find out the information required to set up the project; you can just select the defaults for now.
  6. +
  7. Once all the questions have been asked, it will ask you if the information entered is OK. type yes and press Enter/Return and npm will generate a package.json file in your directory.
  8. +
+ +

This file is basically a config file for the project. You can customize it later, but for now it'll look something like this:

+ +
{
+  "name": "node-test",
+  "version": "1.0.0",
+  "description": "Test for npm projects",
+  "main": "index.js",
+  "scripts": {
+    "test": "test"
+  },
+  "author": "Chris Mills",
+  "license": "MIT"
+}
+ +

With this, you are ready to move on.

+ +

Setting up Gulp automation

+ +

Let's look at setting up Gulp and using it to automate some testing tools.

+ +
    +
  1. To begin with, create a test npm project using the procedure detailed at the bottom of the previous section.
  2. +
  3. Next, you'll need some sample HTML, CSS and JavaScript content to test your system on — make copies of our sample index.html, main.js, and style.css files in a subfolder with the name src inside your project folder. You can try your own test content if you like, but bear in mind that such tools won't work on internal JS/CSS — you need external files.
  4. +
  5. First, install gulp globally (meaning, it will be available across all projects) using the following command: +
    npm install --global gulp-cli
    +
  6. +
  7. Next, run the following command inside your npm project directory root to set up gulp as a dependency of your project: +
    npm install --save-dev gulp
    +
  8. +
  9. Now create a new file inside your project directory called gulpfile.js. This is the file that will run all our tasks. Inside this file, put the following: +
    var gulp = require('gulp');
    +
    +gulp.task('default', function() {
    +  console.log('Gulp running');
    +});
    + This requires the gulp module we installed earlier, and then runs a basic task that does nothing except for printing a message to the terminal — this is useful for letting us know that Gulp is working. Each gulp task is written in the same basic format — gulp's task() method is run, and given two parameters — the name of the task, and a callback function containing the actual code to run to complete the task.
  10. +
  11. You can run your gulp task with the following commands — try this now: +
    gulp
    +
    +
  12. +
+ +

Adding some real tasks to Gulp

+ +

To add some real tasks to Gulp, we need to think about what we want to do. A reasonable set of basic functionalities to run on our project is as follows:

+ + + +

See the links above for full instructions on the different gulp packages we are using.

+ +

To use each plugin, you need to first install it via npm, then require any dependencies at the top of the gulpfile.js file, then add your test(s) to the bottom of it, and finally add the name of your task inside the default task.

+ +

Before you go any further, update the default task to this:

+ +
gulp.task('default', [ ]);
+ +

Inside the array goes the names of all the tasks you want Gulp to run, once you run the gulp command on the command line.

+ +

html-tidy

+ +
    +
  1. Install using the following line: +
    npm install --save-dev gulp-htmltidy
    +
    + +
    +

    Note: --save-dev adds the package as a dependency to your project. If you look in your project's package.json file, you'll see an entry for it as, it has been added to the devDependencies property.

    +
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var htmltidy = require('gulp-htmltidy');
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('html', function() {
    +  return gulp.src('src/index.html')
    +        .pipe(htmltidy())
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'html' as an item inside the array in the default task.
  8. +
+ +

Here we are grabbing our development index.html file — gulp.src() which allows us to grab a source file to do something with.

+ +

We next use the pipe() function to pass that source to another command to do something else with. We can chain as many of these together as we want. We first run htmltidy() on the source, which goes through and fixes errors in our file. The second pipe() function writes the output HTML file to the build directory.

+ +

In the input version of the file, you may have noticed that we put an empty {{htmlelement("p")}} element; htmltidy has removed this by the time the output file has been created.

+ +

Autoprefixer and css-lint

+ +
    +
  1. Install using the following lines: +
    npm install --save-dev gulp-autoprefixer
    +npm install --save-dev gulp-csslint
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var autoprefixer = require('gulp-autoprefixer');
    +var csslint = require('gulp-csslint');
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('css', function() {
    +    return gulp.src('src/style.css')
    +        .pipe(csslint())
    +        .pipe(csslint.formatter('compact'))
    +        .pipe(autoprefixer({
    +            browsers: ['last 5 versions'],
    +            cascade: false
    +        }))
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'css' as an item inside the array in the default task.
  8. +
+ +

Here we grab our style.css file, run csslint on it (which outputs a list of any errors in your CSS to the terminal), then runs it through autoprefixer to add any prefixes needed to make nascent CSS features run in older browsers. At the end of the pipe chain, we output our modified prefixed CSS to the build directory. Note that this only works if csslint doesn't find any errors — try removing a curly brace from your CSS file and re-running gulp to see what output you get!

+ +

js-hint and babel

+ +
    +
  1. Install using the following lines: +
    npm install --save-dev gulp-babel @babel/preset-env
    +npm install --save-dev @babel/core
    +npm install jshint gulp-jshint --save-dev
    +
    +
  2. +
  3. Add the following dependencies to gulpfile.js: +
    var babel = require('gulp-babel');
    +var jshint = require('gulp-jshint');
    +
    +
  4. +
  5. Add the following test to the bottom of gulpfile.js: +
    gulp.task('js', function() {
    +    return gulp.src('src/main.js')
    +        .pipe(jshint())
    +        .pipe(jshint.reporter('default'))
    +        .pipe(babel({
    +            presets: ['@babel/env']
    +        }))
    +        .pipe(gulp.dest('build'));
    +});
    +
  6. +
  7. Add 'js' as an item inside the array in the default task.
  8. +
+ +

Here we grab our main.js file, run jshint on it and output the results to the terminal using jshint.reporter; we then pass the file to babel, which converts it to old style syntax and outputs the result into the build directory. Our original code included a fat arrow function, which babel has modified into an old style function.

+ +

Further ideas

+ +

Once all this is all set up, you can run the gulp command inside your project directory, and you should get an output like this:

+ +

+ +

You can then try out the files output by your automated tasks by looking at them inside the build directory, and loading build/index.html in your web browser.

+ +

If you get errors, check that you've added all the dependencies and the tests as shown above; also try commenting out the HTML/CSS/JavaScript code sections and then rerunning gulp to see if you can isolate what the problem is.

+ +

Gulp comes with a watch() function that you can use to watch your files and run tests whenever you save a file. For example, try adding the following to the bottom of your gulpfile.js:

+ +
gulp.task('watch', function(){
+  gulp.watch('src/*.html', ['html']);
+  gulp.watch('src/*.css', ['css']);
+  gulp.watch('src/*.js', ['js']);
+});
+ +

Now try entering the gulp watch command into your terminal. Gulp will now watch your directory, and run the appropriate tasks whenever you save a change to an HTML, CSS, or JavaScript file.

+ +
+

Note: The * character is a wildcard character — here we're saying "run these tasks when any files of these types are saved. You could also use wildcards in your main tasks, for example gulp.src('src/*.css') would grab all your CSS files and then run piped tasks on them.

+
+ +
+

Note: One problem with our watch command above is that our CSSLint/Autoprefixer combination throws full-blown errors when a CSS error is encountered, which stops the watch working. You'll have to restart the watch once a CSS error is encountered, or find another way to do this.

+
+ +

There's a lot more you can do with Gulp. The Gulp plugin directory has literally thousands of plugins to search through.

+ +

Other task runners

+ +

There are many other task runners available. We certainly aren't trying to say that Gulp is the best solution out there, but it works for us and it is fairly accessible to beginners. You could also try using other solutions:

+ + + +

Using commercial testing services to speed up browser testing

+ +

Now let's look at commercial 3rd party browser testing services and what they can do for us.

+ +

The basic premise with such applications is that the company that runs each one has a huge server farm that can run many different tests. When you use this service, you provide a URL of the page you want to test along with information, such as what browsers you want it tested in. The app then configures a new VM with the OS and browser you specified, and returns the test results in the form of screenshots, videos, logfiles, text, etc.

+ +

You can then step up a gear, using an API to access functionality programmatically, which means that such apps can be combined with task runners, such as your own local Selenium environments and others, to create automated tests.

+ +
+

Note: There are other commercial browser testing systems available but in this article, we'll focus on Sauce Labs and BrowserStack. We're not saying that these are necessarily the best tools available, but they are good ones that are simple for beginners to get up and running with.

+
+ +

Sauce Labs

+ +

Getting started with Sauce Labs

+ +

Let's get started with a Sauce Labs Trial.

+ +
    +
  1. Create a Sauce Labs trial account.
  2. +
  3. Sign in. This should happen automatically after you verify your e-mail address.
  4. +
+ +

The basics: Manual tests

+ +

The Sauce Labs dashboard has a lot of options available on it. For now, make sure you are on the Manual Tests tab.

+ +
    +
  1. Click Start a new manual session.
  2. +
  3. In the next screen, type in the URL of a page you want to test (use http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box-fixed.html, for example), then choose a browser/OS combination you want to test by using the different buttons and lists. There is a lot of choice, as you'll see!
  4. +
  5. When you click Start session, a loading screen will then appear, which spins up a virtual machine running the combination you chose.
  6. +
  7. When loading has finished, you can then start to remotely test the web site running in the chosen browser.
  8. +
  9. From here you can see the layout as it would look in the browser you are testing, move the mouse around and try clicking buttons, etc. The top menu allows you to: +
      +
    • Stop the session
    • +
    • Give someone else a URL so they can observe the test remotely.
    • +
    • Copy text/notes to a remote clipboard.
    • +
    • Take a screenshot.
    • +
    • Test in full screen mode.
    • +
    +
  10. +
+ +

Once you stop the session, you'll return to the Manual Tests tab, where you'll see an entry for each of the previous manual sessions you started. Clicking on one of these entries shows more data for the session. In here you can download any screenshots you took , watch a video of the session, and view data logs for the session for example.

+ +
+

Note: This is already very useful, and way more convenient than having to set up all these emulators and virtual machines by yourself.

+
+ +

Advanced: The Sauce Labs API

+ +

Sauce Labs has a restful API that allows you to programmatically retrieve details of your account and existing tests, and annotate tests with further details, such as their pass/fail state which isn't recordable by manual testing alone. For example, you might want to run one of your own Selenium tests remotely using Sauce Labs, to test a certain browser/OS combination, and then pass the test results back to Sauce Labs.

+ +

It has several clients available to allow you to make calls to the API using your favourite environment, be it PHP, Java, Node.js, etc.

+ +

Let's have a brief look at how we'd access the API using Node.js and node-saucelabs.

+ +
    +
  1. First, set up a new npm project to test this out, as detailed in {{anch("Setting up Node and npm")}}. Use a different directory name than before, like sauce-test for example.
  2. +
  3. Install the Node Sauce Labs wrapper using the following command: +
    npm install saucelabs
    +
  4. +
  5. Create a new file inside your project root called call_sauce.js. give it the following contents: +
    var SauceLabs = require('saucelabs');
    +
    +var myAccount = new SauceLabs({
    +  username: "your-sauce-username",
    +  password: "your-sauce-api-key"
    +});
    +
    +myAccount.getAccountDetails(function (err, res) {
    +  console.log(res);
    +  myAccount.getServiceStatus(function (err, res) {
    +    // Status of the Sauce Labs services
    +    console.log(res);
    +    myAccount.getJobs(function (err, jobs) {
    +      // Get a list of all your jobs
    +      for (var k in jobs) {
    +        if ( jobs.hasOwnProperty( k )) {
    +          myAccount.showJob(jobs[k].id, function (err, res) {
    +            var str = res.id + ": Status: " + res.status;
    +            if (res.error) {
    +              str += "\033[31m Error: " + res.error + " \033[0m";
    +            }
    +            console.log(str);
    +          });
    +        }
    +      }
    +    });
    +  });
    +});
    +
  6. +
  7. You'll need to fill in your Sauce Labs username and API key in the indicated places. These can be retrieved from your User Settings page. Fill these in now.
  8. +
  9. Make sure everything is saved, and run your file like so: +
    node call_sauce
    +
  10. +
+ +

Advanced: Automated tests

+ +

We'll cover actually running automated Sauce Lab tests in the next article.

+ +

BrowserStack

+ +

Getting started with BrowserStack

+ +

Let's get started with a BrowserStack Trial.

+ +
    +
  1. Create a BrowserStack trial account.
  2. +
  3. Sign in. This should happen automatically after you verify your e-mail address.
  4. +
  5. When you first sign in, you should be on the Live testing page; if not, click the Live link in the top nav menu.
  6. +
  7. If you are on Firefox or Chrome, you'll be prompted to Install a browser extension in a dialog titled "Enable Local Testing" — click the Install button to proceed. If you are on other browsers you'll still be able to use some of the features (generally via Flash), but you won't get the full experience.
  8. +
+ +

The basics: Manual tests

+ +

The BrowserStack Live dashboard allows you to choose what device and browser you want to test on — Platforms in the left column, devices on the right. When you mouse over or click on each device, you get a choice of browsers available on that device.

+ +

+ +

Clicking on one of those browser icons will load up your choice of platform/device/browser — choose one now, and give it a try.

+ +

+ +
+

Note: The blue device icon next to some of the mobile device choices signals that you will be testing on a real device; choices without that icon will be run on an emulator.

+
+ +

You'll find that you can enter URLs into the address bar, and use the other controls like you'd expect on a real device. You can even do things like copy and paste from the device to your clipboard, scroll up and down by dragging with the mouse, or use appropriate gestures (e.g. pinch/zoom, two fingers to scroll) on the touchpads of supporting devices (e.g. Macbook). Note that not all features are available on all devices.

+ +

You'll also see a menu that allows you to control the session.

+ +

+ +

The features here are as follows:

+ + + +
+

Note: This is already very useful, and way more convenient than having to set up all these emulators and virtual machines by yourself.

+
+ +

Other basic features

+ +

If you go back to the main BrowserStack page, you'll find a couple of other useful basic features under the More menu option:

+ + + +

Advanced: The BrowserStack API

+ +

BrowserStack also has a restful API that allows you to programmatically retrieve details of your account plan, sessions, builds, etc.

+ +

It has several clients available to allow you to make calls to the API using your favourite environment, be it PHP, Java, Node.js, etc.

+ +

Let's have a brief look at how we'd access the API using Node.js.

+ +
    +
  1. First, set up a new npm project to test this out, as detailed in {{anch("Setting up Node and npm")}}. Use a different directory name than before, like bstack-test for example.
  2. +
  3. Create a new file inside your project root called call_bstack.js. give it the following contents: +
    var request = require("request");
    +
    +var bsUser = "BROWSERSTACK_USERNAME";
    +var bsKey = "BROWSERSTACK_ACCESS_KEY";
    +var baseUrl = "https://" + bsUser + ":" + bsKey + "@www.browserstack.com/automate/";
    +
    +function getPlanDetails(){
    +    request({uri: baseUrl + "plan.json"}, function(err, res, body){
    +        console.log(JSON.parse(body));
    +    });
    +    /* Response:
    +    {
    +        automate_plan: <string>,
    +        parallel_sessions_running: <int>,
    +        team_parallel_sessions_max_allowed: <int>,
    +        parallel_sessions_max_allowed: <int>,
    +        queued_sessions: <int>,
    +        queued_sessions_max_allowed: <int>
    +    }
    +    */
    +}
    +
    +getPlanDetails();
    +
    +
  4. +
  5. You'll need to fill in your BrowserStack username and API key in the indicated places. These can be retrieved from your BrowserStack automation dashboard. Fill these in now.
  6. +
  7. Make sure everything is saved, and run your file like so: +
    node call_bstack
    +
  8. +
+ +

Below we've also provided some other ready-made functions you might find useful when working with the BrowserStack restful API.

+ +
function getBuilds(){
+	request({uri: baseUrl + "builds.json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	[
+		{
+			automation_build: {
+				name: <string>,
+				duration: <int>,
+				status: <string>,
+				hashed_id: <string>
+			}
+		},
+		{
+			automation_build: {
+				name: <string>,
+				duration: <int>,
+				status: <string>,
+				hashed_id: <string>
+			}
+		},
+		...
+	]
+	*/
+};
+
+function getSessionsInBuild(build){
+	var buildId = build.automation_build.hashed_id;
+	request({uri: baseUrl + "builds/" + buildId + "/sessions.json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	[
+		{
+			automation_session: {
+				name: <string>,
+				duration: <int>,
+				os: <string>,
+				os_version: <string>,
+				browser_version: <string>,
+				browser: <string>,
+				device: <string>,
+				status: <string>,
+				hashed_id: <string>,
+				reason: <string>,
+				build_name: <string>,
+				project_name: <string>,
+				logs: <string>,
+				browser_url: <string>,
+				public_url: <string>,
+				video_url: <string>,
+				browser_console_logs_url: <string>,
+				har_logs_url: <string>
+			}
+		},
+		{
+			automation_session: {
+				name: <string>,
+				duration: <int>,
+				os: <string>,
+				os_version: <string>,
+				browser_version: <string>,
+				browser: <string>,
+				device: <string>,
+				status: <string>,
+				hashed_id: <string>,
+				reason: <string>,
+				build_name: <string>,
+				project_name: <string>,
+				logs: <string>,
+				browser_url: <string>,
+				public_url: <string>,
+				video_url: <string>,
+				browser_console_logs_url: <string>,
+				har_logs_url: <string>
+			}
+		},
+		...
+	]
+	*/
+}
+
+function getSessionDetails(session){
+	var sessionId = session.automation_session.hashed_id;
+	request({uri: baseUrl + "sessions/" + sessionId + ".json"}, function(err, res, body){
+		console.log(JSON.parse(body));
+	});
+	/* Response:
+	{
+		automation_session: {
+			name: <string>,
+			duration: <int>,
+			os: <string>,
+			os_version: <string>,
+			browser_version: <string>,
+			browser: <string>,
+			device: <string>,
+			status: <string>,
+			hashed_id: <string>,
+			reason: <string>,
+			build_name: <string>,
+			project_name: <string>,
+			logs: <string>,
+			browser_url: <string>,
+			public_url: <string>,
+			video_url: <string>,
+			browser_console_logs_url: <string>,
+			har_logs_url: <string>
+		}
+	}
+	*/
+}
+ +

Advanced: Automated tests

+ +

We'll cover actually running automated BrowserStack tests in the next article.

+ +

Summary

+ +

This was quite a ride, but I'm sure you can start to see the benefit in having automation tools do a lot of the heavy lifting for you in terms of testing.

+ +

In the next article, we'll look at setting up our own local automation system using Selenium, and how to combine that with services such as Sauce Labs and BrowserStack

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Feature_detection", "Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html new file mode 100644 index 0000000000..1de223efa2 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/feature_detection/index.html @@ -0,0 +1,357 @@ +--- +title: 機能検出の実装 +slug: Learn/Tools_and_testing/Cross_browser_testing/Feature_detection +tags: + - Article + - Beginner + - CSS + - CodingScripting + - JavaScript + - Learn + - Modernizr + - Testing + - Tools + - cross browser + - feature detection + - 機能検出 +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Feature_detection +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Accessibility","Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

機能検出は、あるブラウザーがあるコードのブロックに対応しているかどうかを調べ、対応しているか (またはしていないか) に応じて異なるコードを実行することで、ブラウザーが常に動作し、ブラウザーによってクラッシュやエラーが発生しないようにします。この記事では、独自の単純な機能検出の書き方、実装をスピードアップするためのライブラリの使い方、 @supports などの機能検出のためのネイティブ機能について詳しく説明します。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:機能検出の概念について理解し、CSS と JavaScript で適切な解決方法を実装できるようにする。
+ +

機能検出の概念

+ +

機能検出の根底にあるアイデアは、プログラムを実行中のブラウザーがある特定の機能に対応しているかを確かめ、その結果に応じて異なるコードを実行するということで、対応ブラウザーと非対応ブラウザーのいずれでも許容できる挙動となるようにすることです。もしこの対策をしなければ、その特定の機能に対応していないブラウザーではあなたのサイトが正常に表示されなかったり、エラーを起こしてユーザーの体験を悪化させるでしょう。

+ +

それでは、私たちが Handling common JavaScript problems で触れた例を振り返ってみましょう。Geolocation API (ブラウザーを実行している端末の位置情報を返します)は、 Navigator オブジェクトに含まれる geolocation プロパティを主なエントリーポイントとして持っています。そこで、以下のようにしてブラウザーが位置情報機能に対応しているかどうかを検出できます。

+ +
if ("geolocation" in navigator) {
+  navigator.geolocation.getCurrentPosition(function(position) {
+    // Google Maps API を用いて現在位置をマップ上に表示します
+  });
+} else {
+  // 位置情報がなくてもマップを表示できるようにします
+}
+ +

しかし、機能検出のためのコードを毎回自分で書くよりも、確立された既存の機能検出ライブラリを使うほうが良いでしょう。この用途では Modernizr が一般に利用されています。Modernizr には後ほど触れます。

+ +

次に進む前にもう1つお伝えさせてください。機能検出とブラウザー検出(サイトにアクセスしているブラウザーの種類の検出)を混同しないでください。これはいかなる場合にも避けられるべき悪しき風習です。詳しくは Using bad browser sniffing code を参照してください。

+ +

Writing your own feature detection tests

+ +

In this section, we'll look at implementing your own feature detection tests, in both CSS and JavaScript.

+ +

CSS

+ +

You can write tests for CSS features by testing for the existence of element.style.property (e.g. paragraph.style.transform) in JavaScript.

+ +

A classic example might be to test for Flexbox support in a browser; for browsers that support the newest Flexbox spec, we could use a flexible and robust flex layout. For browsers that don't, we could use a floated layout that works OK, although it is slightly more brittle and hacky, and not as cool-looking.

+ +

Let's implement something that demonstrates this, although we'll keep it simple for now.

+ +
    +
  1. Start by making local copies of our css-feature-detect.html, flex-layout.css, float-layout-css, and basic-styling.css files. Save them in a new directory.
  2. +
  3. We will add the HTML5 Shiv to our example too so that the HTML5 semantic elements will style properly in older versions of IE. Download the latest version (see Manual installation), unzip the ZIP file, copy the html5shiv-printshiv.min.js and html5shiv.min.js files into your example directory, and link to one of the files by putting the following under your {{htmlelement("title")}} element: +
    <script src="html5shiv.min.js"></script>
    +
  4. +
  5. Have a look at your example CSS files — you'll see that basic-styling.css handles all the styling that we want to give to every browser, whereas the other two CSS files contain the CSS we want to selectively apply to browser depending on their support levels. You can look at the different effects these two files they have by manually changing the CSS file referred to by the second {{htmlelement("link")}} element, but let's instead implement some JavaScript to automatically swap them as needed.
  6. +
  7. First, remove the contents of the second <link> element's href attribute. We will fill this in dynamically later on.
  8. +
  9. Next, add a <script></script> element at the bottom of your body (just before the closing </body> tag).
  10. +
  11. Give it the following contents: +
    const conditional = document.querySelector('.conditional');
    +const testElem = document.createElement('div');
    +if (testElem.style.flex !== undefined && testElem.style.flexFlow !== undefined) {
    +  conditional.setAttribute('href', 'flex-layout.css');
    +} else {
    +  conditional.setAttribute('href', 'float-layout.css');
    +}
    +
  12. +
+ +

Here we are grabbing a reference to the second <link> element, and creating a <div> element as part of our test. In our conditional statement, we test that the {{cssxref("flex")}} and {{cssxref("flex-flow")}} properties exist in the browser. Note how the JavaScript representations of those properties that are stored inside the {{domxref("HTMLElement.style")}} object use lower camel case, not hyphens, to separate the words.

+ +
+

Note: If you have trouble getting this to work, you can compare it to our css-feature-detect-finished.html code (see also the live version).

+
+ +

When you save everything and try out your example, you should see the flexbox layout applied to the page if the browser supports modern flexbox, and the float layout if not.

+ +
+

Note: Often such an approach is overkill for a minor feature detection problem — you can often get away with using multiple vendor prefixes and fallback properties, as described in CSS fallback behavior and Handling CSS prefixes.

+
+ +

@supports

+ +

In recent times, CSS has had its own native feature detection mechanism introduced — the {{cssxref("@supports")}} at-rule. This works in a similar manner to media queries (see also Responsive design problems) — except that instead of selectively applying CSS depending on a media feature like a resolution, screen width or aspect ratio, it selectively applies CSS depending on whether a CSS feature is supported.

+ +

For example, we could rewrite our previous example to use @supports — see supports-feature-detect.html and supports-styling.css. If you look at the latter, you'll see a couple of @supports blocks, for example:

+ +
@supports (flex-flow: row) and (flex: 1) {
+
+  main {
+    display: flex;
+  }
+
+  main div {
+    padding-right: 4%;
+    flex: 1;
+  }
+
+  main div:last-child {
+    padding-right: 0;
+  }
+
+}
+ +

This at-rule block applies the CSS rule within only if the current browser supports both the flex-flow: row and flex: 1 declarations. For each condition to work, you need to include a complete declaration (not just a property name) and NOT include the semi-colon on the end.

+ +

@supports also has OR and NOT logic available — the other block applies the float layout if the flexbox properties are not available:

+ +
@supports not (flex-flow: row) and (flex: 1) {
+
+  /* rules in here */
+
+}
+ +

This may look a lot more convenient than the previous example — we can do all of our feature detection in CSS, no JavaScript required, and we can handle all the logic in a single CSS file, cutting down on HTTP requests. the problem here is browser support — @supports is not supported at all in IE, and only supported in very recent versions of Safari/iOS WebKit (9+/9.2+), whereas the JavaScript version should work in much older browsers (probably back to IE8 or 9, although older versions of IE will have additional problems, such as not supporting {{domxref("Document.querySelector")}}, and having a messed up box model).

+ +

JavaScript

+ +

We already saw an example of a JavaScript feature detection test earlier on. Generally, such tests are done via one of the following common patterns:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Summary of JavaScript feature detection techniques
Feature detection typeExplanationExample
If member in objectCheck whether a certain method or property (typically an entry point into using the API or other feature you are detecting for) exists in its parent Object. +

if("geolocation" in navigator) { ... }

+
Property on elementCreate an element in memory using {{domxref("Document.createElement()")}} and then check if a property exists on it. The example shown is a way of detecting HTML5 Canvas support.function supports_canvas() {
+ return !!document.createElement('canvas').getContext;
+ }
+
+ if(supports_canvas()) { ... }
Method on element return valueCreate an element in memory using {{domxref("Document.createElement()")}} and then check if a method exists on it. If it does, check what value it returns.See Dive Into HTML5 Video Formats detection test.
Property on element retains valueCreate an element in memory using {{domxref("Document.createElement()")}}, set a property to a certain value, then check to see if the value is retained.See Dive into HTML5 <input> types detection test.
+ +
+

Note: The double NOT in the above example (!!) is a way to force a return value to become a "proper" boolean value, rather than a {{glossary("Truthy")}}/{{glossary("Falsy")}} value that may skew the results.

+
+ +

The Dive into HTML5 Detecting HTML5 Features page has a lot more useful feature detection tests besides the ones listed above, and you can generally find a feature detection test for most things by searching for "detect support for YOUR-FEATURE-HERE" in your favorite search engine. Bear in mind though that some features, however, are known to be undetectable — see Modernizr's list of Undetectables.

+ +

matchMedia

+ +

We also wanted to mention the {{domxref("Window.matchMedia")}} JavaScript feature at this point too. This is a property that allows you to run media query tests inside JavaScript. It looks like this:

+ +
if (window.matchMedia("(max-width: 480px)").matches) {
+  // run JavaScript in here.
+}
+ +

As an example, our Snapshot demo makes use of it to selectively apply the Brick JavaScript library and use it to handle the UI layout, but only for the small screen layout (480px wide or less). We first use the media attribute to only apply the Brick CSS to the page if the page width is 480px or less:

+ +
<link href="dist/brick.css" type="text/css" rel="stylesheet" media="all and (max-width: 480px)">
+ +

We then use matchMedia() in the JavaScript several times, to only run Brick navigation functions if we are on the small screen layout (in wider screen layouts, everything can be seen at once, so we don't need to navigate between different views).

+ +
if (window.matchMedia("(max-width: 480px)").matches) {
+  deck.shuffleTo(1);
+}
+ +

Using Modernizr to implement feature detection

+ +

It is possible to implement your own feature detection tests using techniques like the ones detailed above. You might as well use a dedicated feature detection library however, as it makes things much easier. The mother of all feature detection libraries is Modernizr, and it can detect just about everything you'll ever need. Let's look at how to use it now.

+ +

When you are experimenting with Modernizr you might as well use the development build, which includes every possible feature detection test. Download this now by:

+ +
    +
  1. Clicking on the Development build link.
  2. +
  3. Clicking the big pink Build button on the page that comes up.
  4. +
  5. Clicking the top Download link in the dialog box that appears.
  6. +
+ +

Save it somewhere sensible, like the directory you've been creating your other examples for in this article.

+ +

When you are using Modernizr in production, you can go to the Download page you've already visited and click the plus buttons for only the features you need feature detects for. Then when you click the Build button, you'll download a custom build containing only those feature detects, making for a much smaller file size.

+ +

CSS

+ +

Let's have a look at how Modernizr works in terms of selectively applying CSS.

+ +
    +
  1. First, make a copy of supports-feature-detect.html and supports-styling.css. Save them as modernizr-css.html and modernizr-css.css.
  2. +
  3. Update your {{htmlelement("link")}} element in your HTML so it points to the correct CSS file (you should also update your {{htmlelement("title")}} element to something more suitable!): +
    <link href="modernizr-css.css" rel="stylesheet">
    +
  4. +
  5. Above this <link> element, add a {{htmlelement("script")}} element to apply the Modernizr library to the page, as shown below. This needs to be applied to the page before any CSS (or JavaScript) that might make use of it. +
    <script src="modernizr-custom.js"></script>
    +
  6. +
  7. Now edit your opening <html> tag, so that it looks like this: +
    <html class="no-js">
    +
  8. +
+ +

At this point, try loading your page, and you'll get an idea of how Modernizr works for CSS features. If you look at the DOM inspector of your browser's developer tools, you'll see that Modernizr has updated your <html> class value like so:

+ +
<html class="js no-htmlimports sizes flash transferables applicationcache blobconstructor
+blob-constructor cookies cors ...AND LOADS MORE VALUES!>
+ +

It now contains a large number of classes that indicate the support status of different technology features. As an example, if the browser didn't support flexbox at all, <html> would be given a class name of no-flexbox. If it did support modern flexbox, it would get a class name of flexbox. If you search through the class list, you'll also see others relating to flexbox, like:

+ + + +
+

Note: You can find a list of what all the class names mean — see Features detected by Modernizr.

+
+ +

Moving on, let's update our CSS to use Modernizr rather than @supports. Go into modernizr-css.css, and replace the two @supports blocks with the following:

+ +
/* Properties for browsers with modern flexbox */
+
+.flexbox main {
+  display: flex;
+}
+
+.flexbox main div {
+  padding-right: 4%;
+  flex: 1;
+}
+
+.flexbox main div:last-child {
+  padding-right: 0;
+}
+
+/* Fallbacks for browsers that don't support modern flexbox */
+
+.no-flexbox main div {
+  width: 22%;
+  float: left;
+  padding-right: 4%;
+}
+
+.no-flexbox main div:last-child {
+  padding-right: 0;
+}
+
+.no-flexbox footer {
+  clear: left;
+}
+ +

So how does this work? Because all those class names have been put on the <html> element, you can target browsers that do or don't support a feature using specific descendant selectors. So here we're applying the top set of rules only to browsers that do support flexbox, and the bottom set of rules only to browsers that don't (no-flexbox).

+ +
+

Note: Bear in mind that all of Modernizr's HTML and JavaScript feature tests are also reported in these class names, so you can quite happily apply CSS selectively based on whether the browser supports HTML or JavaScript features, if needed.

+
+ +
+

Note: If you have trouble getting this to work, check your code against our modernizr-css.html and modernizr-css.css files (see this running live also).

+
+ +

JavaScript

+ +

Modernizr is also equally well-prepared for implementing JavaScript feature detects too. It does this by making the global Modernizr object available to the page it is applied to, which contains results of the feature detects as true/false properties.

+ +

For example, load up our modernizr-css.html example in your browser, then try going to your JavaScript console and typing in Modernizr. followed by some of those class names (they are the same here too). For example:

+ +
Modernizr.flexbox
+Modernizr.websqldatabase
+Modernizr.xhr2
+Modernizr.fetch
+ +

The console will return true/false values to indicate whether your browser supports those features or not.

+ +

Let's look at an example to show how you'd use those properties.

+ +
    +
  1. First of all, make a local copy of the modernizr-js.html example file.
  2. +
  3. Attach the Modernizr library to the HTML using a <script> element, as we have done in previous demos. Put it above the existing <script> element, which is attaching the Google Maps API to the page.
  4. +
  5. Next, fill in the YOUR-API-KEY placeholder text in the second <script> element (as it is now) with a valid Google Maps API key. To get a key, sign in to a Google account, go to the Get a Key/Authentication page, then click the blue Get a Key button and follow the instructions.
  6. +
  7. Finally, add another <script> element at the bottom of the HTML body (just before the </body> tag), and put the following script inside the tags: +
    if (Modernizr.geolocation) {
    +
    +  navigator.geolocation.getCurrentPosition(function(position) {
    +
    +    let latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    +    let myOptions = {
    +      zoom: 8,
    +      center: latlng,
    +      mapTypeId: google.maps.MapTypeId.TERRAIN,
    +      disableDefaultUI: true
    +    }
    +    let map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    +  });
    +
    +} else {
    +  const para = document.createElement('p');
    +  para.textContent = 'Argh, no geolocation!';
    +  document.body.appendChild(para);
    +}
    +
  8. +
+ +

Try your example out! Here we use the Modernizr.geolocation test to check whether geolocation is supported by the current browser. If it is, we run some code that gets your device's current location, and plots it on a Google Map.

+ +

Summary

+ +

This article covered feature detection in a reasonable amount of detail, going through the main concepts and showing you how to both implement your own feature detection tests and use the Modernizr library to implement tests more easily.

+ +

Next up, we'll start looking at automated testing.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Accessibility","Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

In this module

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html new file mode 100644 index 0000000000..62e21f35a2 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/html_and_css/index.html @@ -0,0 +1,508 @@ +--- +title: 一般的な HTML と CSS の問題への対処 +slug: Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS +tags: + - CSS + - CodingScripting + - HTML + - linting + - クロスブラウザ + - セレクタ + - テスト + - 初心者 + - 学習 + - 記事 +translation_of: Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies","Learn/Tools_and_testing/Cross_browser_testing/JavaScript", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

ここでは、HTML と CSS のコードで発生する可能性のある一般的なクロスブラウザの問題、および問題の発生を防ぐため、または発生する問題を修正するために使用できるツールについて具体的に説明します。これには、コードのリンティング、CSS プレフィックスの処理、問題を追跡するためのブラウザの開発者ツールの使用、ブラウザにサポートを追加するための polyfill の使用、レスポンシブデザイン問題への取り組みなどが含まれます。

+ + + + + + + + + + + + +
前提条件:主要な HTMLCSS、および JavaScript 言語に精通していること。クロスブラウザテストの原則の高水準のアイデア。
目標:一般的な HTML と CSS のクロスブラウザの問題を診断し、それらを修正するための適切なツールとテクニックを使うことができるようにする。
+ +

HTML と CSS の問題

+ +

一部の HTML と CSS の問題は、両方の言語がかなり単純で、コードがうまく作成され、効率的であり、ページ上に「機能の目的」を意味的に記述していることを確認するという意味で開発者がそれらについて真剣に考えていないという事実にあります。最悪の場合、JavaScript を使用して Web ページのコンテンツとスタイル全体を生成するため、ページにアクセスできなくなり、パフォーマンスが低下します (DOM 要素の生成にはコストがかかります)。他のケースでは、初期の機能がブラウザ間で一貫してサポートされていないため、一部の機能やスタイルが一部のユーザには機能しないことがあります。
+ レスポンシブデザインの問題も一般的です。デスクトップブラウザで見栄えの良いサイトはモバイル端末だとひどい経験を提供するかもしれません、内容が読むには小さすぎるか、高精細なアニメーションのせいで遅いでしょう。

+ +

HTML/CSS に起因するクロスブラウザエラーを減らす方法を見てみましょう。

+ +

まず最初に:一般的な問題を解決する

+ +

このシリーズの最初の記事では、まずクロスブラウザの問題に集中する前に、デスクトップ/モバイルの最新ブラウザでいくつかテストしてコードが正常に機能するか確認することをお勧めします。

+ +

HTML のデバッグおよび CSS のデバッグの記事では、HTML/CSS のデバッグに関する基本的なガイダンスをいくつか提供しました。基本に慣れていない場合は、先に進む前に必ずこれらの記事をよく読んでください。

+ +

基本的には、HTML と CSS のコードが整形式で、構文エラーがないかどうかをチェックすることです。

+ +
+

メモ: CSS と HTML に関する一般的な問題の1つは、異なる CSS ルールが互いに矛盾が生じるときに発生します。 サードパーティのコードを使用している場合、これは特に問題になる可能性があります。たとえば、CSS フレームワークを使用して、それが使用しているクラス名の1つが別の目的ですでに使用されているものと衝突しているとします。 または、ある種のサードパーティ API (たとえば広告バナーの生成) によって生成された HTML に、すでに別の目的で使用されているクラス名または ID が含まれていることもあります。これが起こらないようにするには、最初に使用しているツールを調べて、それらを中心にコードを設計する必要があります。また、"名前空間"  CSS も価値があります。ウィジェットがある場合は、それが明確なクラスを持っていることを確認してから、このクラスでウィジェット内の要素を選択するセレクタを起動します。そうすれば競合は起こりにくくなります。例えば、 .audio-player ul a です。

+
+ +

検証

+ +

HTML の検証では、すべてのタグが適切に閉じられてネストされていること、DOCTYPE を使用していること、およびタグを正しい目的で使用していることを確認します。良い戦略はコードを定期的に検証することです。これを可能にするサービスの 1 つに、W3C マークアップ検証サービスがあります。これを使用すると、コードを指定してエラーのリストを返すことができます。

+ +

The HTML validator homepage

+ +

CSS にも同様の話があります — プロパティ名が正しくつづられていること、プロパティ値が正しくつづられていて、それらが使われているプロパティに対して有効であること、中括弧を見逃していないということです。この目的のために、W3C には CSS Validator も用意されています。

+ +

Linters

+ +

取りうるもう一つの良い選択肢は、エラーを指摘するだけでなく、CSS の悪いプラクティスについての警告、および他の点にもフラグを立てることができる、いわゆる Linter アプリケーションです。Linter は一般的に、エラー/警告の報告においてより厳格またはより緩やかになるようにカスタマイズできます。

+ +

オンラインリンターアプリケーションは多数ありますが、そのうち最良のものはおそらく Dirty Markup (HTML、CSS、JavaScript)、および CSS Lint (CSS のみ) です。これらはコードをウィンドウに貼り付けることができ、十字でどんなエラーにでもフラグを立てるでしょう、そしてそれは問題が何であるかを知らせるエラーメッセージを得るためにそれから隠されることができます。Dirty Markup では、Clean ボタンを使用してマークアップを修正することもできます。

+ +

+ +

However, it is not very convenient to have to copy and paste your code over to a web page to check its validity several times. What you really want is a linter that will fit into your standard workflow with the minimum of hassle.

+ +

Many code editors have linter plugins. Github's Atom code editor for example has a rich plugin ecosystem available, with many linting options. To show you an example of how such plugins generally work:

+ +
    +
  1. Install Atom (if you haven't got an up-to-date version already installed) — download it from the Atom page linked above.
  2. +
  3. Go to Atom's Preferences... dialog (e.g. by Choosing Atom > Preferences... on Mac, or File > Preferences... on Windows/Linux) and choose the Install option in the left hand menu.
  4. +
  5. In the Search packages text field, type "lint" and press Enter/Return to search for linting-related packages.
  6. +
  7. You should see a package called lint at the top of the list. Install this first (using the Install button), as other linters rely on it to work. After that, install the linter-csslint plugin for linting CSS, and the linter-tidy plugin for linting HTML.
  8. +
  9. After the packages have finished installing, try loading up an HTML file and a CSS file: you'll see any issues highlighted with green (for warnings) and red (for errors) circles next to the line numbers, and a separate panel at the bottom provides line numbers, error messages, and sometimes suggested values or other fixes.
  10. +
+ +

+ +

Other popular editors have similar linting packages available. For example, see:

+ + + +

Browser developer tools

+ +

The developer tools built into most browsers also feature useful tools for hunting down errors, mainly for CSS.

+ +
+

メモ: ブラウザが不正な形式のマークアップを自動的に修正しようとするため、HTML エラーは開発ツールではそれほど簡単には表示されない傾向があります。W3C バリデータは HTML エラーを取得するための最良の方法です — 上の {{anch("Validation")}} を見てください。

+
+ +

As an example, in Firefox the CSS inspector will show CSS declarations that aren't applied crossed out, with a warning triangle. Hovering the warning triangle will provide a descriptive error message:

+ +

+ +

Other browser devtools have similar features.

+ +

Common cross browser problems

+ +

Now let's move on to look at some of the most common cross browser HTML and CSS problems. The main areas we'll look at are lack of support for modern features, and layout issues.

+ +

Older browsers not supporting modern features

+ +

This is a common problem, especially when you need to support old browsers (such as old IE versions) or you are using features that are implemented using CSS prefixes. In general, most core HTML and CSS functionality (such as basic HTML elements, CSS basic colors and text styling) works across most browsers you'll want to support; more problems are uncovered when you start wanting to use newer features such as Flexbox, or HTML5 video/audio, or even more nascent, CSS Grids or -webkit-background-clip: text.

+ +

Once you've identified a list of potential problem technologies you will be using, it is a good idea to research what browsers they are supported in, and what related techniques are useful. See {{anch("Finding help")}} below.

+ +

HTML fallback behaviour

+ +

Some problems can be solved by just taking advantage of the natural way in which HTML/CSS work.

+ +

Unrecognised HTML elements are treated by the browser as anonymous inline elements (effectively inline elements with no semantic value, similar to {{htmlelement("span")}} elements). You can still refer to them by their names, and style them with CSS, for example — you just need to make sure they are behaving as you want them to, for example setting display: block; on all of the new semantic elements (such as {{htmlelement("article")}}, {{htmlelement("aside")}}, etc.), but only in old versions of IE that don't recognise them (so, IE 8 and lower). This way new browsers can just use the code as normal, but older IE versions will be able to style these elements too.

+ +
+

Note: See {{anch("IE conditional comments")}} for the best way to do this.

+
+ +

More complex elements like HTML <video>, <audio>, and <canvas> (and other features besides) have natural mechanisms for fallbacks to be added, which work on the same principle as described above. You can add fallback content in between the opening and closing tags, and non-supporting browsers will effectively ignore the outer element and run the nested content.

+ +

For example:

+ +
<video id="video" controls preload="metadata" poster="img/poster.jpg">
+  <source src="video/tears-of-steel-battle-clip-medium.mp4" type="video/mp4">
+  <source src="video/tears-of-steel-battle-clip-medium.webm" type="video/webm">
+  <source src="video/tears-of-steel-battle-clip-medium.ogg" type="video/ogg">
+  <!-- Flash fallback -->
+  <object type="application/x-shockwave-flash" data="flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" width="1024" height="576">
+     <param name="movie" value="flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" />
+     <param name="allowfullscreen" value="true" />
+     <param name="wmode" value="transparent" />
+     <param name="flashvars" value="controlbar=over&amp;image=img/poster.jpg&amp;file=flash-player.swf?videoUrl=video/tears-of-steel-battle-clip-medium.mp4" />
+      <img alt="Tears of Steel poster image" src="img/poster.jpg" width="1024" height="428" title="No video playback possible, please download the video from the link below" />
+  </object>
+  <!-- Offer download -->
+  <a href="video/tears-of-steel-battle-clip-medium.mp4">Download MP4</a>
+</video>
+ +

This example (taken from Creating a cross-browser video player) includes not only a Flash video fallback for older IE versions, but also a simple link allowing you to download the video if even the Flash player doesn't work, so at least the user can still access the video.

+ +
+

Note: 3rd party libraries like Video.js and JW Player use such fallback mechanisms to provide cross-browser support.

+
+ +

HTML5 form elements also exhibit fallback qualities — HTML5 introduced some special <input> types for inputting specific information into forms, such as times, dates, colors, numbers, etc. These are very useful, particularly on mobile platforms, where providing a pain-free way of entering data is very important for the user experience. Supporting platforms provide special UI widgets when these input types are used, such as a calendar widget for entering dates.

+ +

The following example shows date and time inputs:

+ +
<form>
+  <div>
+    <label for="date">Enter a date:</label>
+    <input id="date" type="date">
+  </div>
+  <div>
+    <label for="time">Enter a time:</label>
+    <input id="time" type="time">
+  </div>
+</form>
+ +

The output of this code is as follows:

+ + + +

 

+ +
<form>
+      <div>
+        <label for="date">Enter a date:</label>
+        <input id="date" type="date">
+      </div>
+      <div>
+        <label for="time">Enter a time:</label>
+        <input id="time" type="time">
+      </div>
+    </form>
+ + + +

{{ EmbedLiveSample('Hidden_example', '100%', 150) }}

+ +
+

Note: You can also see this running live as forms-test.html on GitHub (see the source code also).

+
+ +

If you view the example on a supporting browser like desktop/Android Chrome or iOS Safari, you'll see the special widgets/features in action as you try to input data. On a non-supporting platform such as Firefox or Internet Explorer, the inputs will just fallback to normal text inputs, so at least the user can still enter some information.

+ +

Note: Of course, this may not be a great solution for your project's needs — the difference in visual presentation is not great, plus it is harder to guarantee the data will be entered in the format you want it in. For cross browser forms, It is probably better to rely on simple form elements, or selectively using advanced form elements only in supporting browsers, or using a library that provides decent cross browser form widgets, such as jQuery UI or Bootstrap datepicker.

+ +

CSS fallback behaviour

+ +

CSS is arguably better at fallbacks than HTML. If a browser encounters a declaration or rule it doesn't understand, it just skips it completely without applying it or throwing an error. This might be frustrating for you and your users if such a mistake slips through to production code, but at least it means the whole site doesn't come crashing down because of one error, and if used cleverly you can use it to your advantage.

+ +

Let's look at an example — a simple box styled with CSS, which has some styling provided by various CSS3 features:

+ +

+ +
+

Note: You can also see this example running live on GitHub as button-with-fallback.html (also see the source code).

+
+ +

The button has a number of declarations that style, but the two we are most interested in are as follows:

+ +
button {
+  ...
+
+  background-color: #ff0000;
+  background-color: rgba(255,0,0,1);
+  box-shadow: inset 1px 1px 3px rgba(255,255,255,0.4),
+              inset -1px -1px 3px rgba(0,0,0,0.4);
+}
+
+button:hover {
+  background-color: rgba(255,0,0,0.5);
+}
+
+button:active {
+  box-shadow: inset 1px 1px 3px rgba(0,0,0,0.4),
+              inset -1px -1px 3px rgba(255,255,255,0.4);
+}
+ +

Here we are providing an RGBA {{cssxref("background-color")}} that changes opacity on hover to give the user a hint that the button is interactive, and some semi-transparent inset {{cssxref("box-shadow")}} shades to give the button a bit of texture and depth. The trouble is that RGBA colors and box shadows don't work in IE versions older than 9 — in older versions the background just wouldn't show up at all so the text would be unreadable, no good at all!

+ +

+ +

To sort this out, we have added a second background-color declaration, which just specifies a hex color — this is supported way back in really old browsers, and acts as a fallback if the modern shiny features don't work. What happens is a browser visiting this page first applies the first background-color value; when it gets to the second background-color declaration, it will override the initial value with this value if it supports RGBA colors. If not, it will just ignore the entire declaration and move on.

+ +
+

Note: The same is true for other CSS features like media queries, @font-face and @supports blocks — if they are not supported, the browser just ignores them.

+
+ +

IE conditional comments

+ +

IE conditional comments are a modified proprietary HTML comment syntax, which can be used to selectively apply HTML code to different versions of IE. This has proven to be a very effective mechanism for fixing cross browser bugs. The syntax looks like this:

+ +
<!--[if lte IE 8]>
+  <script src="ie-fix.js"></script>
+  <link href="ie-fix.css" rel="stylesheet" type="text/css">
+<![endif]-->
+ +

This block will apply the IE-specific CSS and JavaScript only if the browser viewing the page is IE 8 or older. lte means "less than or equal to", but you can also use lt, gt, gte, ! for NOT, and other logical syntax.

+ +
+

Note: Sitepoint's Internet Explorer Conditional Comments provides a useful beginner's tutorial/reference that explains the conditional comment syntax in detail.

+
+ +

As you can see, this is especially useful for applying code fixes to old versions of IE. The use case we mentioned earlier (making modern semantic elements styleable in old versions of IE) can be achieved easily using conditional comments, for example you could put something like this in your IE stylesheet:

+ +
aside, main, article, section, nav, figure, figcaption {
+  display: block;
+}
+ +

It isn't that simple, however — you also need to create a copy of each element you want to style in the DOM via JavaScript, for them to be styleable; this is a strange quirk, and we won't bore you with the details here. For example:

+ +
var asideElem = document.createElement('aside');
+ ...
+ +

This sounds like a pain to deal with, but fortunately there is a {{glossary("polyfill")}} available that does the necessary fixes for you, and more besides — see HTML5Shiv for all the details (see manual installation for the simplest usage).

+ +

Selector support

+ +

Of course, no CSS features will apply at all if you don't use the right selectors to select the element you want to style! If you just write a selector incorrectly so the styling isn't as expected in any browser, you'll just need to troubleshoot and work out what is wrong with your selector. We find that it is helpful to inspect the element you are trying to style using your browser's dev tools, then look at the DOM tree breadcrumb trail that DOM inspectors tend to provide to see if your selector makes sense compared to it.

+ +

For example, in the Firefox dev tools, you get this kind of output at the bottom of the DOM inspector:

+ +

+ +

If for example you were trying to use this selector, you'd be able to see that it wouldn't select the input element as desired:

+ +
form > #date
+ +

(The date form input isn't directly inside the <form>; you'd be better off using a general descendant selector instead of a child selector).

+ +

However, another issue that appears in versions of IE older than 9 is that none of the newer selectors (mainly pseudo-classes and pseudo-elements like :nth-of-type, :not, ::selection, etc.) work. If you want to use these in your CSS and you need to support older IE versions, a good move is to use Keith Clark's Selectivizr library — this is a small JavaScript library that works on top of an existing JavaScript library like jQuery or MooTools.

+ +
    +
  1. To try this example, make a local copy of selectivizr-example-start.html. If you look at this running live, you'll see that it contains two paragraphs, one of which is styled. We've selected the paragraph with p:first-child, which won't work in old versions of IE.
  2. +
  3. Now download MooTools and Selectivizr, and save them in the same directory as your sample HTML.
  4. +
  5. Put the following code into the head of your HTML document, just before the opening <style> tag: +
    <script type="text/javascript" src="MooTools-Core-1.6.0.js"></script>
    +    <!--[if (gte IE 6)&(lte IE 8)]>
    +      <script type="text/javascript" src="selectivizr-min.js"></script>
    +    <![endif]-->
    +
  6. +
+ +
    +
  1.  
  2. +
+ +

If you try running this in an old version of IE, it should work fine.

+ +

+ +

Handling CSS prefixes

+ +

Another set of problems comes with CSS prefixes — these are a mechanism orignally used to allow browser vendors to implement their own version of a CSS (or JavaScript) feature while the technology is in an experimental state, so they can play with it and get it right without conflicting with other browser's implementations, or the final unprefixed implementations. So for example:

+ + + +

Here's some examples:

+ +
-webkit-transform: rotate(90deg);
+
+background-image: -moz-linear-gradient(left,green,yellow);
+background-image: -webkit-gradient(linear,left center,right center,from(green),to(yellow));
+background-image: linear-gradient(to right,green,yellow);
+ +

The first line shows a {{cssxref("transform")}} property with a -webkit- prefix — this was needed to make transforms work in Chrome, etc. until the feature was finalized and such browsers added a prefix-free version of the property (at the time of writing, Chrome supported both versions).

+ +

The last three lines show three different versions of the linear-gradient() function, which is used to generate a linear gradient in the background of an element:

+ +
    +
  1. The first one has a -moz- prefix, and shows a slightly older version of the syntax (Firefox)
  2. +
  3. The second one has a -webkit- prefix, and shows an even older, proprietary version of the syntax (this is actually from a really old version of the WebKit engine).
  4. +
  5. The third one has no prefix, and shows the final version of the syntax (included in the CSS Image Values and Replaced Content Module Level 3 spec, which defines this feature).
  6. +
+ +

Prefixed features were never supposed to be used in production websites — they are subject to change or removal without warning, and cause cross browser issues. This is particularly a problem when developers decide to only use say, the -webkit- version of a property — meaning that the site won't work in other browsers. This actually happens so much that other browsers have started to implement -webkit- prefixed versions of various CSS properties, so they will work with such code. Usage of prefixes by browser vendors has declined recently precisely because of these types of problems, but there are still some that need attention.

+ +

If you insist on using prefixed features, make sure you use the right ones. You can look up what browsers require prefixes on MDN reference pages, and sites like caniuse.com. If you are unsure, you can also find out by doing some testing directly in browsers.

+ +

Try this simple example:

+ +
    +
  1. Open up google.com, or another site that has a prominent heading or other block level element.
  2. +
  3. Right/Cmd + click on the element in question and choose Inspect/Inspect element (or whatever the option is in your browser) — this should open up the dev tools in your browser, with the element highlighted in the DOM inspector.
  4. +
  5. Look for a feature you can use to select that element. For example, at the time of writing, the main Google logo had an ID of hplogo.
  6. +
  7. Store a reference to this element in a variable, for example: +
    var test = document.getElementById('hplogo');
    +
  8. +
+ + + +
    +
  1.  
  2. +
+ +

As you start to type the property name representation after the second dot (note that in JavaScript, CSS property names are written in lower camel case, not hyphenated), the JavaScript console should begin to autocomplete the names of the properties that exist in the browser and match what you've written so far. This is useful for finding out what versions of the property are implemented in that browser.

+ +

At the time of writing, both Firefox and Chrome implemented -webkit- prefixed and non-prefixed versions of {{cssxref("transform")}}!

+ +

Once you've found out which prefixes you need to support, you should write them all out in your CSS, for example:

+ +
-ms-transform: rotate(90deg);
+-webkit-transform: rotate(90deg);
+transform: rotate(90deg);
+ +

This ensures that all browsers that support any of the above forms of the property can make the feature work. It is worth putting the non-prefixed version last, because that will be the most up-to-date version, which you'll want browsers to use if possible. If for example a browser implements both the -webkit- version and the non-prefixed version,  it will first apply the -webkit- version, then override it with the non-prefixed version. You want it to happen this way round, not the other way round.

+ +

Of course, doing this for lots of different CSS rules can get really tedious. It is better to use an automation tool to do it for you. And such tools exist:

+ +

The prefix-free JavaScript library can be attached to a page, and will automatically detect what capabilities are possessed by browsers viewing the page and add prefixes as appropriate. It is really easy and convenient to use, although it does have some downsides (see the link above for details), and it is arguable that parsing every stylesheet in your site and add prefixes at run time can be a drain on the computer's processing power for a large site.

+ +

Another solution is to add prefixes automatically during development, and this (and other things besides) can be done using tools like Autoprefixer and PostCSS. These tools can be used in a variety of ways, for example Autoprefixer has an online version that allows you to enter your non-prefixed CSS on the left, and gives you a prefix-added version on the right. You can choose which browsers you want to make sure you support using the notation outlined in Autoprefixer options; also see Browserslist queries, which this is based on, for more detail. As an example, the following query will select the last 2 versions of all major browsers and versions of IE above 9.

+ +
last 2 versions, ie > 9
+ +

Autoprefixer can also be used in other, more convenient ways — see Autoprefixer usage. For example you can use it with a task runner/build tool such as Gulp or Webpack to automatically add prefixes once development has been done. (Explaining how these work is somewhat beyond the scope of this article.)

+ +

You can also use a plugin for a text editor such as Atom or Sublime text. For example, in Atom:

+ +
    +
  1. You can install it by going to Preferences > Install, searching for Autoprefixer, then hitting install.
  2. +
  3. You can set a browser query by pressing the Autoprefixer Settings button and entering the query in the text field in the Settings section on the page.
  4. +
  5. In your code, you can select sections of CSS you want to add prefixes to, open the command pallette (Cmd/Ctrl + Shift + P), then type in Autoprefixer and select the Autoprefixer result that autocompletes.
  6. +
+ +

As an example, we entered the following code:

+ +
body {
+  display: flex;
+}
+ +

We highlighted it and ran the Autoprefixer command, and it replaced it with this:

+ +
body {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+}
+ +

Layout issues

+ +

Another problem that might come up is differences in layouts between browsers. Historically this used to be much more of a problem, but recently, with modern browsers tending to support CSS more consistently, layout issues tend to be more commonly associated with:

+ + + +
+

Note: Historically web developers used to use CSS files called resets, which removed all the default browser styling applied to HTML, and then applied their own styles for everything over the top — this was done to make styling on a project more consistent, and reduce possible cross browser issues, especially for things like layout. However, it has more recently been seen as overkill. The best equivalent we have in modern times is normalize.css, a neat bit of CSS that builds slightly on the default browser styling to make things more consistent and fix some layout issues. You are advised to apply normalize.css to all your HTML pages.

+
+ +
+

Note:  When trying to track down a tricky layout issue, a good technique is to add a brightly colored {{cssxref("outline")}} to the offending element, or all the elements nearby. This makes it a lot easier to see where everything is placed. See Debug your CSS with outline visualizations for more details.

+
+ +

Support for new layout features

+ +

Much of the layout work on the web today is done using floats — this is because floats are well-supported (way back to IE4, albeit with a number of bugs that would also need to be investigated if you were to try to support IE that far back). However, they are not really meant for layout purposes — using floats the way we do is really a hack — and they do have some serious limitations (e.g. see Why Flexbox?)

+ +

More recently, dedicated layout mechanisms have appeared, like Flexbox and CSS Grids, which make common layout tasks far easier and remove such shortcomings. These however are not as well-supported in browsers:

+ + + +

Layout features aren't as easy to provide graceful fallbacks for than simple colors, shadows, or gradients. If layout properties are ignored, your entire design will likely fall to pieces. Because of this, you need to use feature detection to detect whether visiting browsers support those layout features, and selectively apply different layouts depending on the result (we will cover feature detection in detail in a later article).

+ +

For example, you could apply a flexbox layout to modern browsers, then instead apply a floated layout to older browsers that don't support flexbox.

+ +
+

Note: There is a fairly new feature in CSS called @supports, which allows you to implement native feature detection tests.

+
+ +

Responsive design problems

+ +

Responsive design is the practice of creating web layouts that change to suit different device form factors — for example different screen widths, orientations (portrait or landscape), or resolutions. A desktop layout for example will look terrible when viewed on a mobile device, so you need to provide a suitable mobile layout using media queries, and make sure it is applied correctly using viewport. You can find a detailed account of such practices in The building blocks of responsive design.

+ +

Resolution is a big issue too — for example, mobile devices are less likely to need big heavy images than desktop computers, and are more likely to have slower internet connections and possibly even expensive data plans that make wasted bandwidth more of a problem. In addition, different devices can have a range of different resolutions, meaning that smaller images could appear pixellated. There are a number of techniques that allow you to work around such problems, from simple mobile first media queries, to more complex responsive image techniques.

+ +

Another difficulty that can present problems is browser support for the features that make the above techniques possible. media queries are not supported in IE 8 or less, so if you want to use a mobile first layout and have the desktop layout then apply to old IE versions, you'll have to apply a media query {{glossary("polyfill")}} to your page, like css3-mediaqueries-js, or Respond.js.

+ +

Finding help

+ +

There are many other issues you'll encounter with HTML and CSS; the most important thing to know really is how to find answers online.

+ +

Among the best sources of support information are the Mozilla Developer Network (that's where you are now!), stackoverflow.com, and caniuse.com.

+ +

To use the Mozilla Developer Network (MDN), most people do a search engine search of the technology they are trying to find information on, plus the term "mdn", for example "mdn HTML5 video". MDN contains several useful types of content:

+ + + +

caniuse.com provides support information, along with a few useful external resource links. For example, see http://caniuse.com/#search=video (you just have to enter the feature you are searching for into the text box).

+ +

stackoverflow.com (SO) is a forum site where you can ask questions and have fellow developers share their solutions, look up previous posts, and help other developers. You are advised to look and see if there is an answer to your question already, before posting a new question. For example, we searched for "cross browser html5 video" on SO, and very quickly came up with HTML5 Video with full cross browser compatibility.

+ +

Aside from that, try searching your favourite search engine for an answer to your problem. It is often useful to search for specific error messages if you have them — other developers will be likely to have had the same problems as you.

+ +

まとめ

+ +

Now you should be familiar with the main types of cross browser HTML and CSS problems that you'll meet in web development, and how to go about fixing them.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies","Learn/Tools_and_testing/Cross_browser_testing/JavaScript", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/index.html new file mode 100644 index 0000000000..d3a0da5fa8 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/index.html @@ -0,0 +1,47 @@ +--- +title: クロスブラウザテスト +slug: Learn/Tools_and_testing/Cross_browser_testing +tags: + - Accessibility + - Automation + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - Learn + - Module + - Testing + - Tools + - cross browser +translation_of: Learn/Tools_and_testing/Cross_browser_testing +--- +
{{LearnSidebar}}
+ +

このモジュールでは、色々なウェブブラウザー間でウェブプロジェクトをテストすることに焦点を当てます。あなたのターゲット視聴者 (例 どのユーザー、ブラウザー、デバイスに一番関心があるのか?) の特定や、テストをどう動かすかや、主な問題としてさまざまな種類のコードと対面してそれらを緩和する方法や、テストを楽にして問題を解決するのに最も役立つツールが何かや、自動化を利用してテストをスピードアップする方法を見て行きます。

+ +

前提条件

+ +

ここで述べるツールを使ってみる前に、基本的な HTMLCSSJavaScript 言語をよく理解しておきます。

+ +

ガイド

+ +
+
はじめてのクロスブラウザーテスト
+
この記事ではクロスブラウザーテストの概観を提供し始めます。その過程で「ブラウザーテストとは何?」「どんな種類の問題によく出くわしますか?」「テストと、問題の特定・修正の主なアプローチは?」といった質問に答えたりします。
+
テスト実行戦略
+
次に、テスト実行について掘り下げ、ターゲット視聴者(例、どのブラウザー、デバイス、その他のセグメントでテストを確実にするのか)を特定し、ローファイテスト戦略(ある範囲のデバイスと仮装マシンにて必要ならアドホックテストを行う)、高度なテスト戦略(専用テストアプリを使った自動化)、ユーザーグループを使ったテストまで見て行きます。
+
よくあるHTML や CSS の問題を扱う
+
シーンがセットされたら、HTMLとCSSコードの中でよく出くわすクロスブラウザー問題と、問題を防いだり、問題発生を修正するのに使えるツールを詳しく見ていきます。これにはコードの lint や、CSSプレフィックスを手渡したり、問題を監視するブラウザーの開発ツールを使ったり、ブラウザーサポート追加に polyfill を使ったり、レスポンシブデザインの問題に取り組んだり、といった事が含まれます
+
よくある JavaScript の問題を扱う
+
今度はクロスブラウザー JavaScript の問題と、その修正方法を見て行きます。ここにはブラウザーの開発ツールを使って問題を突き止めて修正したり、問題を回避するのに pollyfill やライブラリーを使用したり、古いブラウザーの対応にモダン JavaScript の機能を掴んだり、といった事が含まれます。
+
よくあるアクセシビリティの問題を扱う
+
次にアクセシビリティに注意を向けて、良くある問題の情報、簡単なテスト実施の方法、アクセシビリティの問題を見つけるための監査/自動化ツールの利用方法を提供します。
+
機能検出の実装
+
機能検出はブラウザーがあるコードブロックをサポートしているか考えたり、サポートする/しないによって他のコードを実行したりして、いくつかのブラウザーでクラッシュ/エラー起こすことなく、常に動作の体験を提供できるようにすることです。この記事では簡単な機能検出を書く方法や、 @supports のようなネイティブ機能について詳しく記載します。
+
はじめての自動テスト
+
いくつかのブラウザーと端末で、一日に何度もテストを手動実行するのはつまらないし時間をつぶします。これを効率良く扱うには、自動化ツールに詳しくなるべきです。この記事では何を入手できるかや、タスクランナーの使い方や、Sauce Labs と Browser Stack のような商用ブラウザーテスト自動化ツールの使い方の基本を見て行きます。
+
テスト自動化環境をセットアップする
+
この記事では、Selenium/WebDriver や selenium-webdriver for Node のようなテストライブラリーを使って、自動化環境のインストールとテストを実行する方法を教えます。またあなたのローカルテスト環境と、以前の記事で見てきたような商用アプリとを統合する方法についても見て行きます。
+
diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html new file mode 100644 index 0000000000..3e0e2e7834 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/introduction/index.html @@ -0,0 +1,209 @@ +--- +title: はじめてのクロスブラウザテスト +slug: Learn/Tools_and_testing/Cross_browser_testing/Introduction +tags: + - Article + - Beginner + - CodingScripting + - Learn + - Testing + - concepts + - cross browser +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では (クロス) ブラウザテストのトピックの概要を説明し、「クロスブラウザテストとは何ですか?」、「発生する最も一般的な問題の種類は何ですか?」、「問題のテスト、特定、および修正のための主なアプローチは?」などの質問に答えながらモジュールを始めます。

+ + + + + + + + + + + + +
前提知識:HTML, CSS, JavaScript 言語の基礎に精通していること。
目的:クロスブラウザテストに関する高レベルのコンセプトを理解する。
+ +

クロスブラウザテストとは?

+ +

クロスブラウザテストは、作成した Web サイトと Web アプリケーションが許容できる数の Web ブラウザにわたって動作することを確認することです。Web 開発者として、自分のプロジェクトが機能するだけでなく、使用しているブラウザ、デバイス、その他の補助ツールに関係なく、すべてのユーザに対して機能することを確認するのはあなたの責任です。あなたは考える必要があります:

+ + + +

ユーザーの状況は一人ひとり異なってきます — 自分の Macbook Pro やハイエンドな Galaxy Nexus で動いても、すべてのユーザーにとって動作するとは限りません 。それを確認するには膨大な数のテストが必要になってきます。

+ +
+

: Make the web work for everyone では、人々が使っているさまざまなブラウザの種類やそれぞれのマーケットシェア、それに伴うクロスブラウザの懸念点などが説明されています。

+
+ +

ここでいくつかの用語を説明します。最初に、「クロスブラウザでの動作」と言う時、様々なブラウザ間で受け入れられるユーザー体験が提供されることを言います。サイトがすべてのブラウザでまったく同一の体験が提供していなくても、コア機能がいくつかの方法で受け入れられる限りは、潜在的にOKです。モダンブラウザではアニメーションや3Dや目立つものがあり、いっぽう古いブラウザでは平坦なグラフィックで同じ情報を表すだけのこともあるでしょう。サイト所有者が満足している限り、あなたの仕事は完了です。

+ +

その一方で、サイトが視力のあるユーザーにとって動作していても、視覚障がいのあるユーザーにとって、スクリーンリーダーアプリケーションがそこにある情報を読み取れないため完全にアクセスできない場合は、OKではありません。

+ +

2つ目に、「受け入れられる数のウェブブラウザ間で」と言った時、世界中のブラウザの 100% の意味ではありません — これは不可能です。ユーザーが使うブラウザや端末の情報を呼び出すことができます (このシリーズの2つ目の記事で見ていきましょう — Gotta test 'em all?を見てください)が、すべてを保証することはできません。ウェブ開発者としては、ある範囲のブラウザと端末にてコードが完全に動作することをサイトオーナーと同意しておく必要があります。しかしそれを超えて、その他のブラウザでコンテンツを使う機会をできるだけ与えられるよう防衛的なコードを書いておく必要があります。

+ +
+

: このモジュールの後の方でも、防衛的なコードをカバーします。

+
+ +

なぜクロスブラウザ問題が起きるのか?

+ +

クロスブラウザ問題が生じる原因はたくさんあります。そして、本記事ではブラウザ・端末・ブラウザの設定によって生じる問題について述べます。クロスブラウザの問題に取り組む前に、ソース中のバグを解決するべきです(必要に応じて前述のDebugging HTML, Debugging CSS, and What went wrong? Troubleshooting JavaScriptの記事を見て記憶を呼び覚ましてください)。

+ +

クロスブラウザ問題が発生する原因は主に以下になります。

+ + + +

上記の他にも理由はあります。

+ +

後述の記事では、クロスブラウザ問題についてよくある問題について掘り下げ、解決策を提示します。

+ +

クロスブラウザテストの作業手順

+ +

All of this cross browser testing business may sound time consuming and scary, but it needn't be — you just need to plan carefully for it, and make sure you do enough testing in the right places to make sure you don't run into unexpected problems. If you are working on a large project, you should be testing it regularly, to make sure that new features work for your target audience, and that new additions to the code don't break old features that were previously working.

+ +

If you leave all the testing to the end of a project, any bugs you uncover will be a lot more expensive and time consuming to fix than if you uncover them and fix them as you go along.

+ +

The workflow for testing and bug fixes on a project can be broken down into roughly the following four phases (this is only very rough — different people may do things quite differently to this):

+ +

Initial planning > Development > Testing/discovery > Fixes/iteration

+ +

Steps 2–4 will tend to be repeated as many times as necessary to get all of the implementation done. We will look at the different parts of the testing process in much greater detail in subsequent articles, but for now let's just summarize what may occur in each step.

+ +

初期計画

+ +

In the initial planning phase, you will probably have several planning meetings with the site owner/client (this might be your boss, or someone from an external company you are building a web site for), in which you determine exactly what the web site should be — what content and functionality should it have, what should it look like, etc. At this point you'll also want to know how much time you have to develop the site — what is their deadline, and how much are they going to pay you for your work? We won't go into much detail about this, but cross-browser issues can have a serious effect on such planning.

+ +

Once you've got an idea of the required featureset, and what technologies you will likely build these features with, you should start exploring the target audience — what browsers, devices, etc. will the target audience for this site be using? The client might already have data about this from previous research they've done, e.g. from other web sites they own, or from previous versions of the web site you are now working on. If not, you will be able to get a good idea by looking at other sources, such as usage stats for competitors, or countries the site will be serving. You can also use a bit of intuition.

+ +

So for example, you might be building an e-commerce site that serves customers in North America. the site should work entirely in the last few versions of the most popular desktop and mobile (iOS, Android, Windows phone) browsers — this should include Chrome (and Opera as it is based on the same rendering engine as Chrome), Firefox, IE/Edge, and Safari. It should also provide an acceptable experience on IE 8 and 9, and be accessible with WCAG AA compliance.

+ +

Now you know your target testing platforms, you should go back and review the required featureset and what technologies you are going to use. For example, if the e-commerce site owner wants a WebGL-powered 3D tour of each product built into the product pages, they will need to accept that this just won't work in IE versions before 11. You'd have to agree to provide a version of the site without this feature to users of older IE versions.

+ +

You should compile a list of the potential problem areas.

+ +
+

: You can find browser support information for technologies by looking up the different features on MDN — the site you're on! You should also consult caniuse.com, for some further useful details.

+
+ +

Once you've agreed on these details, you can go ahead and start developing the site.

+ +

開発

+ +

Now on to the development of the site. You should split the different parts of the development into modules, for example you might split the different site areas up — home page, product page, shopping cart, payment workflow, etc. You might then further subdivide these — implement common site header and footer, implement product page detail view, implement persistent shopping cart widget, etc.

+ +

There are multiple general strategies to cross browser development, for example:

+ + + +

Normally your development will involve a combination of the above three approaches. The most important thing is that you test each small part before committing it — don't leave all the testing till the end!

+ +

テスト/発見

+ +

After each implementation phase, you will need to test the new functionality. To start with, you should make sure there are no general issues with your code that are stopping your feature from working:

+ +
    +
  1. Test it in a couple of stable browsers on your system, like Firefox, Safari, Chrome, or IE/Edge.
  2. +
  3. Do some low fi accessibility testing, such as trying to use your site with only the keyboard, or using your site via a screen reader to see if it is navigable.
  4. +
  5. Test on a mobile platform, such as Android or iOS.
  6. +
+ +

At this point, fix any problems you find with your new code.

+ +

Next, you should try expanding your list of test browsers to a full list of target audience browsers and start concentrating on weeding out cross browser issues (see the next article for more information on determining your target browsers). For example:

+ + + +

The most low fi option is to just do all the testing you can by yourself (pulling in team mates to help out if you are working in a  team). You should try to test it on real physical devices where possible.

+ +

If you haven't got the means to test all those different browser, operating system, and device combinations on physical hardware, you can also make use of emulators (emulate a device using software on your desktop computer) and virtual machines (software that allows you to emulate multiple operating system/software combinations on your desktop computer). This is a very popular choice, especially in some circumstances — for example, Windows doesn't let you have multiple versions of Windows installed simulataneously on the same machine, so using multiple virtual machines is often the only option here.

+ +

Another option is user groups — using a group of people outside your development team to test your site. This could be a group of friends or family, a group of other employees, a class at a local university, or a professional user testing setup, where people are paid to test out your site and provide results.

+ +

Finally, you can get smarter with your testing using auditing or automation tools; this is a sensible choice as your projects get bigger, as doing all this testing by hand can start to take a really long time. You can set up your own testing automation system (Selenium being the popular app of choice) that could for example load your site in a number of different browsers, and:

+ + + +

You can also go further than this, if wished. There are commercial tools available such as Sauce Labs, Browser StackLambdaTest, TestingBot, and CrossBrowserTesting that do this kind of thing for you, without you having to worry about the setup, if you wish to invest some money in your testing. It is also possible to set up an environment that automatically runs tests for you, and then only lets you check in your changes to the central code repository if the tests still pass.

+ +

Testing on prerelease browsers

+ +

It is often a good idea to test on prerelease versions of browsers; see the following links:

+ + + +

This is especially prevalent if you are using very new technologies in your site, and you want to test against the latest implementations, or if you are coming across a bug in the latest release version of a browser, and you want to see if the browser's developers have fixed the bug in a newer version.

+ +

修正/繰り返し

+ +

Once you've discovered a bug, you need to try to fix it.

+ +

The first thing to do is to narrow down where the bug occurs as much as possible. Get as much information as you can from the person reporting the bug — what platform(s), device(s), browser version(s), etc. Try it on similar configurations (e.g. the same browser version on different desktop platforms, or a few different versions of the same browser on the same platform) to see how widely the bug persists.

+ +

It might not be your fault — if a bug exists in a browser, then hopefully the vendor will rapidly fix it. It might have already been fixed — for example if a bug is present in Firefox release 49, but it is no longer there in Firefox Nightly (version 52), then they have fixed it. If it is not fixed, then you may want to file a bug (see {{anch("Reporting bugs")}}, below).

+ +

If it is your fault, you need to fix it! Finding out the cause of the bug involves the same strategy as any web development bug (again, see Debugging HTML, Debugging CSS, and What went wrong? Troubleshooting JavaScript). Once you've discovered what is causing your bug, you need to decide how to work around it in the particular browser it is causing problems in — you can't just change the problem code outright, as this may break the code in other browsers. The general approach is usually to fork the code in some way, for example use JavaScript feature detection code to detect situations in which a problem feature doesn't work, and run some different code in those cases that does work.

+ +

Once a fix has been made, you'll want to repeat your testing process to make sure your fix is working OK, and hasn't caused the site to break in other places or in other browsers.

+ +

バグを報告する

+ +

ブラウザでバグを発見した場合は、上記で述べたことを繰り返しますが、それらを報告する必要があります。

+ + + +

要約

+ +

この記事では、クロスブラウザテストに関して知っておくべき最も大事な概念について、高位の理解を与えてきました。この知識を備えたことで、クロスブラウザテストの戦略について学び始める準備ができています。

+ +

{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html new file mode 100644 index 0000000000..12c8f274d6 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/javascript/index.html @@ -0,0 +1,521 @@ +--- +title: JavaScript のよくある問題を扱う +slug: Learn/Tools_and_testing/Cross_browser_testing/JavaScript +tags: + - Article + - Beginner + - CodingScripting + - JavaScript + - Learn + - Libraries + - Testing + - cross browser + - feature detection + - linting + - polyfills +translation_of: Learn/Tools_and_testing/Cross_browser_testing/JavaScript +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS","Learn/Tools_and_testing/Cross_browser_testing/Accessibility", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

ここではよくあるクロスブラウザー JavaScript 問題と、その直し方を見てみます。これにはブラウザーの開発ツールを使って問題をつきとめて修正したり、問題の回避に Polyfills やライブラリーを使ったりモダンな JavaScript 機能を古いブラウザーで使ったりなどです。

+ + + + + + + + + + + + +
前提知識:Familiarity with the core HTML, CSS, and JavaScript languages; an idea of the high-level principles of cross browser testing.
狙い:To be able to diagnose common JavaScript cross-browser problems, and use appropriate tools and techniques to fix them.
+ +

JavaScript のトラブル

+ +

Historically, JavaScript was plagued with cross-browser compatibility problems — back in the 1990s, the main browser choices back then (Internet Explorer and Netscape) had scripting implemented in different language flavours (Netscape had JavaScript, IE had JScript and also offered VBScript as an option), and while at least JavaScript and JScript were compatible to some degree (both based on the {{glossary("ECMAScript")}} specification), things were often implemented in conflicting, incompatible ways, causing developers many nightmares.

+ +

Such incompatibility problems persisted well into the early 2000s, as old browsers were still being used and still needed supporting. This is one of the main reasons why libraries like jQuery came into existence — to abstract away differences in browser implementations (e.g. see the code snippet in How to make an HTTP request) so developers only have to write one simple bit of code (see jQuery.ajax()). jQuery (or whatever library you are using) will then handle the differences in the background, so you don't have to.

+ +

Things have got much better since then; modern browsers do a good job of supporting "classic JavaScript features", and the requirement to use such code has diminished as the requirement to support older browsers has lessened (although bear in mind that they have not gone away altogether).

+ +

These days, most cross-browser JavaScript problems are seen:

+ + + +

We'll explore all these problems and more below.

+ +

一般的な JavaScript の問題を修正する

+ +

As we said in the previous article on HTML/CSS, you should make sure your code is working generally, before going on to concentrate on the cross-browser issues. If you are not already familiar with the basics of Troubleshooting JavaScript, you should study that article before moving on. There are a number of common JavaScript problems that you will want to be mindful of, such as:

+ + + +
+

Buggy JavaScript Code: The 10 Most Common Mistakes JavaScript Developers Make has some nice discussions of these common mistakes and more.

+
+ +

Linters

+ +

HTML や CSSと同じく、良い品質を保つことができて、エラーを示して悪いやり方の警告をつけ、エラー/警告の報告を厳しくもゆるくも変えられる Linterを使ってエラーがちな JavaScript コードを減らすことが確実にできます。我々が勧める JavaScript/ECMAScript linters は JSHintESLint; これらは色々な方法で使用でき、そのいくつかを以下で紹介します。

+ +

オンライン

+ +

The JSHint homepage provides an online linter, which allows you to enter your JavaScript code on the left and provides an output on the right, including metrics, warnings, and errors.

+ +

+ +

コードエディターのプラグイン

+ +

It is not very convenient to have to copy and paste your code over to a web page to check its validity several times. What you really want is a linter that will fit into your standard workflow with the minimum of hassle. Many code editors have linter plugins, for example Github's Atom code editor has a JSHint plugin available.

+ +

To install it:

+ +
    +
  1. Install Atom (if you haven't got an up-to-date version already installed) — download it from the Atom page linked above.
  2. +
  3. Go to Atom's Preferences... dialog (e.g. by Choosing Atom > Preferences... on Mac, or File > Preferences... on Windows/Linux) and choose the Install option in the left-hand menu.
  4. +
  5. In the Search packages text field, type "jslint" and press Enter/Return to search for linting-related packages.
  6. +
  7. You should see a package called lint at the top of the list. Install this first (using the Install button), as other linters rely on it to work. After that, install the linter-jshint plugin.
  8. +
  9. After the packages have finished installing, try loading up a JavaScript file: you'll see any issues highlighted with green (for warnings) and red (for errors) circles next to the line numbers, and a separate panel at the bottom provides line numbers, error messages, and sometimes suggested values or other fixes.
  10. +
+ +

Other popular editors have similar linting packages available. For example, see the "Plugins for text editors and IDEs"  section of the JSHint install page.

+ +

その他

+ +

There are other ways to use such linters; you can read about them on the JSHint and ESLint install pages.

+ +

It is worth mentioning command line uses — you can install these tools as command line utilities (available via the CLI — command line interface) using npm (Node Package Manager — you'll have to install NodeJS first). For example, the following command installs JSHint:

+ +
npm install -g jshint
+
+ +

You can then point these tools at JavaScript files you want to lint, for example:

+ +

You can also use these tools with a task runner/build tool such as Gulp or Webpack to automatically lint your JavaScript during development. (see Using a task runner to automate testing tools in a later article.) See ESLint integrations for ESLint options; JSHint is supported out of the box by Grunt, and also has other integrations available, e.g. JSHint loader for Webpack.

+ +
+

: ESLint takes a bit more setup and configuration than JSHint, but it is more powerful too.

+
+ +

ブラウザーの開発ツール

+ +

Browser developer tools have many useful features for helping to debug JavaScript. For a start, the JavaScript console will report errors in your code.

+ +

Make a local copy of our broken-ajax.html example (see the source code also). If you look at the console, you'll see the following output:

+ +

+ +

The error message reads "TypeError: jsonObj is null", and the line number signified is line 37. If we look at the source code, the relevant code section is this:

+ +
function populateHeader(jsonObj) {
+  var myH1 = document.createElement('h1');
+  myH1.textContent = jsonObj['squadName'];
+  header.appendChild(myH1);
+
+  ...
+ +

So the code falls over as soon as we try to access jsonObj (which as you might expect, is supposed to be a JSON object). This is supposed to be fetched from an external .json file using the following XMLHttpRequest call:

+ +
var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
+var request = new XMLHttpRequest();
+request.open('GET', requestURL);
+request.send();
+
+var superHeroes = request.response;
+populateHeader(superHeroes);
+showHeroes(superHeroes);
+ +

But this fails.

+ +

コンソール API

+ +

You may already know what is wrong with this code, but let's explore it some more to show how you could investigate this. For a start, there is a Console API that allows JavaScript code to interact with the browser's JavaScript console. It has a number of features available, but the main one you'll use often is console.log(), which prints a custom message to the console.

+ +

Try inserting the following line just below line 31 (bolded above):

+ +
console.log('Response value: ' + superHeroes);
+ +

Refresh the page in the browser, and you will get an output in the console like so:

+ +

+ +

The console.log() output shows that the superHeroes object doesn't appear to contain anything, although note that the error message has now changed, to "TypeError: heroes is undefined". This shows that the error is intermittent, giving further evidence that this is some kind of asynchronous error. Let's fix the current error and move on — remove the console.log() line, and update this code block:

+ +
var superHeroes = request.response;
+populateHeader(superHeroes);
+showHeroes(superHeroes);
+ +

to the following:

+ +
request.onload = function() {
+  var superHeroes = request.response;
+  populateHeader(superHeroes);
+  showHeroes(superHeroes);
+}
+ +

This solves the asynchronous issue, by ensuring that the functions are not run and passed the superHeroes object until the response has finished loading and is available.

+ +

So to summarize, anytime something is not working and a value does not appear to be what it is meant to be at some point in your code, you can use console.log() to print it out and see what is happening.

+ +

JavaScript デバッガーを使う

+ +

We have solved one problem, but we are still stuck with the error message "TypeError: heroes is undefined", reported on line 51. Let's investigate this now, using a more sophisticated feature of browser developer tools: the JavaScript debugger as it is called in Firefox.

+ +
+

: Similar tools are available in other browsers; the Sources tab in Chrome, Debugger in Safari (see Safari Web Development Tools), etc.

+
+ +

In Firefox, the Debugger tab looks as follows:

+ +

+ + + +

The main feature of such tools is the ability to add breakpoints to code — these are points where the execution of the code stops, and at that point you can examine the environment in its current state and see what is going on.

+ +

Let's get to work. First of all, we know that the error is being thrown at line 51. Click on line number 51 in the center panel to add a breakpoint to it (you'll see a blue arrow appear over the top of it). Now refresh the page (Cmd/Ctrl + R) — the browser will pause execution of the code at line 51. At this point, the right-hand side will update to show some very useful information.

+ +

+ + + +

We can find out some very useful information in here.

+ +
    +
  1. Expand the showHeroes scope — you can see from this that the heroes variable is undefined, indicating that accessing the members property of jsonObj (first line of the function) didn't work.
  2. +
  3. You can also see that the jsonObj variable is storing a text string, not a JSON object.
  4. +
  5. Exploring further down the call stack, click request.onload in the Call Stack section. The view will update to show the request.onload function in the center panel, and its scopes in the Scopes section.
  6. +
  7. Now if you expand the request.onload scope, you'll see that the superHeroes variable is a text string too, not an object. This settles it — our XMLHttpRequest call is returning the JSON as text, not JSON.
  8. +
+ +
+

: We'd like you to try fixing this problem yourself. To give you a clue, you can either tell the XMLHttpRequest object explicitly to return JSON format, or convert the returned text to JSON after the response arrives. If you get stuck, consult our fixed-ajax.html example.

+
+ +
+

: The debugger tab has many other useful features that we've not discussed here, for example conditional breakpoints and watch expressions. For a lot more information, see the Debugger page.

+
+ +

パフォーマンスの問題

+ +

As your apps get more complex and you start to use more JavaScript, you may start to run into performance problems, especially when viewing apps on slower devices. Performance is a big topic, and we don't have time to cover it in detail here. Some quick tips are as follows:

+ + + +
+

: Addy Osmani's Writing Fast, Memory-Efficient JavaScript contains a lot of detail and some excellent tips for boosting JavaScript performance.

+
+ +

クロスブラウザー JavaScript の問題

+ +

In this section, we'll look at some of the more common cross-browser JavaScript problems. We'll break this down into:

+ + + +

モダン JavaScript/API 機能を使う

+ +

In the previous article we described some of the ways in which HTML and CSS errors and unrecognized features can be handled due to the nature of the languages. JavaScript is not as permissive as HTML and CSS however — if the JavaScript engine encounters mistakes or unrecognized syntax, more often than not it will throw errors.

+ +

There are a number of modern JavaScript language features defined in recent versions of the specs (ECMAScript 6 / ECMAScript Next) that simply won't work in older browsers. Some of these are syntactic sugar (basically an easier, nicer way of writing what you can already do using existing features), and some offer interesting new possibilities.

+ +

For example:

+ + + +

There are also many new APIs appearing in recent browsers, which don't work in older browsers, for example:

+ + + +

There are a few strategies for handling incompatibilities between browsers relating to feature support; let's explore the most common ones.

+ +
+

: These strategies do not exist in separate silos — you can, of course combine them as needed. For example, you could use feature detection to determine whether a feature is supported; if it isn't, you could then run code to load a polyfill or a library to handle the lack of support.

+
+ +

機能検出

+ +

The idea behind feature detection is that you can run a test to determine whether a JavaScript feature is supported in the current browser, and then conditionally run code to provide an acceptable experience both in browsers that do and don't support the feature. As a quick example, the Geolocation API  (which exposes available location data for the device the web browser is running on) has a main entry point for its use — a geolocation property available on the global Navigator object. Therefore, you can detect whether the browser supports geolocation or not by using something like the following:

+ +
if("geolocation" in navigator) {
+  navigator.geolocation.getCurrentPosition(function(position) {
+    // show the location on a map, perhaps using the Google Maps API
+  });
+} else {
+  // Give the user a choice of static maps instead perhaps
+}
+ +

You could also write such a test for a CSS feature, for example by testing for the existence of element.style.property (e.g. paragraph.style.transform !== undefined). But for both CSS and JavaScript, it is probably better to use an established feature detection library rather than writing your own all the time. Modernizr is the industry standard for feature detection tests.

+ +

As a last point, don't confuse feature detection with browser sniffing (detecting what specific browser is accessing the site) — this is a terrible practice that should be discouraged at all costs. See {{anch("Using bad browser sniffing code")}}, later on, for more details.

+ +
+

: Some features are known to be undetectable — see Modernizr's list of Undetectables.

+
+ +
+

: Feature detection will be covered in a lot more detail in its own dedicated article, later in the module.

+
+ +

ライブラリー

+ +

JavaScript libraries are essentially third party units of code that you can attach to your page, providing you with a wealth of ready-made functionality that can be used straight away, saving you a lot of time in the process. A lot of JavaScript libraries probably came into existence because their developer was writing a set of common utility functions to save them time when writing future projects, and decided to release them into the wild because other people might find them useful too.

+ +

JavaScript libraries tend to come in a few main varieties (some libraries will serve more than one of these purposes):

+ + + +

When choosing a library to use, make sure that it works across the set of browsers you want to support, and test your implementation thoroughly. Also make sure that the library is popular and well-supported, and isn't likely to just become obsolete next week. Talk to other developers to find out what they recommend, see how much activity and how many contributors the library has on Github (or wherever else it is stored), etc.

+ +
+

: JavaScripting.com gives you a good idea of just how many JavaScript libraries there are available, and can be useful for finding libraries for specific purposes.

+
+ +

Library usage at a basic level tends to consist of downloading the library's files (JavaScript, possibly some CSS or other dependencies too) and attaching them to your page (e.g. via a {{htmlelement("script")}} element), although there are normally many other usage options for such libraries, like installing them as Bower components, or including them as dependencies via the Webpack module bundler. You will have to read the libraries' individual install pages for more information.

+ +
+

: You will also come across JavaScript frameworks in your travels around the Web, like Ember and Angular. Whereas libraries are often usable for solving individual problems and dropping into existing sites, frameworks tend to be more along the lines of complete solutions for developing complex web applications.

+
+ +

Polyfills

+ +

Polyfills also consist of 3rd party JavaScript files that you can drop into your project, but they differ from libraries — whereas libraries tend to enhance existing functionality and make things easier, polyfills provide functionality that doesn't exist at all. Polyfills use JavaScript or other technologies entirely to build in support for a feature that a browser doesn't support natively. For example, you might use a polyfill like es6-promise to make promises work in browsers where they are not supported natively.

+ +

Modernizr's list of HTML5 Cross Browser Polyfills is a useful place to find polyfills for different purposes. Again, you should research them before you use them — make sure they work and are maintained.

+ +

Let's work through an exercise — in this example we will use a Fetch polyfill to provide support for the Fetch API in older browsers; however we also need to use the es6-promise polyfill, as Fetch makes heavy use of promises, and browsers that don't support them will still be in trouble.

+ +
    +
  1. To get started, make a local copy of our fetch-polyfill.html example and our nice image of some flowers in a new directory. We are going to write code to fetch the flowers image and display it in the page.
  2. +
  3. Next, save copies of the Fetch polyfill and the es6-promises polyfill in the same directory as the HTML.
  4. +
  5. Apply the polyfill scripts to the page using the following code — place these above the existing {{htmlelement("script")}} element so they will be available on the page already when we start trying to use Fetch: +
    <script src="es6-promise.js"></script>
    +<script src="fetch.js"></script>
    +
  6. +
  7. Inside the original {{htmlelement("script")}}, add the following code:
  8. +
  9. +
    var myImage = document.querySelector('.my-image');
    +
    +fetch('flowers.jpg').then(function(response) {
    +  response.blob().then(function(myBlob) {
    +    var objectURL = URL.createObjectURL(myBlob);
    +    myImage.src = objectURL;
    +  });
    +});
    +
  10. +
  11. Now if you load it in a browser that doesn't support Fetch (Safari and IE are obvious candidates), you should still see the flower image appear — cool! 
    +
  12. +
+ +
+

: You can find our finished version at fetch-polyfill-finished.html (see also the source code).

+
+ +
+

: Again, there are many different ways to make use of the different polyfills you will encounter — consult each polyfill's individual documentation.

+
+ +

One thing you might be thinking is "why should we always load the polyfill code, even if we don't need it?" This is a good point — as your sites get more complex and you start to use more libraries, polyfills, etc., you can start to load a lot of extra code, which can start to affect performance, especially on less-powerful devices. It makes sense to only load files as needed.

+ +

Doing this requires some extra setup in your JavaScript. You need some kind of a feature detection test that detects whether the browser supports the feature we are trying to use:

+ +
if (browserSupportsAllFeatures()) {
+  main();
+} else {
+  loadScript('polyfills.js', main);
+}
+
+function main(err) {
+  // actual app code goes in here
+}
+ +

So first we run a conditional that checks whether the function browserSupportsAllFeatures() returns true. If it does, we run the main() function, which will contain all our app's code. browserSupportsAllFeatures() looks like this:

+ +
function browserSupportsAllFeatures() {
+  return window.Promise && window.fetch;
+}
+ +

Here we are testing whether the Promise object and fetch() function exist in the browser. If both do, the function returns true. If the function returns false, then we run the code inside the second part of the conditional  — this runs a function called loadScript(), which loads the polyfills into the page, then runs main() after the loading has finished. loadScript() looks like this:

+ +
function loadScript(src, done) {
+  var js = document.createElement('script');
+  js.src = src;
+  js.onload = function() {
+    done();
+  };
+  js.onerror = function() {
+    done(new Error('Failed to load script ' + src));
+  };
+  document.head.appendChild(js);
+}
+
+ +

This function creates a new <script> element, then sets its src attribute to the path we specified as the first argument ('polyfills.js' when we called it in the code above). When it has loaded, we run the function we specified as the second argument (main()). If an error occurs in the loading of the script, we still call the function, but with a custom error that we can retrieve to help debug a problem if it occurs.

+ +

Note that polyfills.js is basically the two polyfills we are using put together into one file. We did this manually, but there are cleverer solutions that will automatically generate bundles for you — see Browserify (see Getting started with Browserify for a basic tutorial). It is a good idea to bundle JS files into one like this — reducing the number of HTTP requests you need to make improves the performance of your site.

+ +

You can see this code in action in fetch-polyfill-only-when-needed.html (see the source code also). We'd like to make it clear that we can't take credit for this code — it was originally written by Philip Walton.  Check out his article Loading Polyfills Only When Needed for the original code, plus a lot of useful explanation around the wider subject).

+ +
+

: There are some 3rd party options to consider, for example Polyfill.io — this is a meta-polyfill library that will look at each browser's capabilities and apply polyfills as needed, depending on what APIs and JS features you are using in your code.

+
+ +

JavaScript トランスパイルする

+ +

Another option that is becoming popular for people that want to use modern JavaScript features now is converting code that makes use of ECMAScript 6/ECMAScript 2015 features to a version that will work in older browsers.

+ +
+

: This is called "transpiling" — you are not compiling code into a lower level for to be run on a computer (like you would say with C code); instead, you are changing it into a syntax that exists at a similar level of abstraction so it can be used in the same way, but in slightly different circumstances (in this case, transforming one flavor of JavaScript into another).

+
+ +

So for example, we talked about arrow functions (see arrow-function.html live, and see the source code) earlier in the article, which only work in the newest browsers:

+ +
() => { ... }
+ +

We could transpile this across to a traditional old-fashioned anonymous function, so it would work in older browsers:

+ +
function() { ... }
+ +

The recommended tool for JavaScript transpiling is currently Babel. This offers transpilation capabilities for language features that are appropriate for transpilation. For features that can't just be easily transpiled into an older equivalent, Babel also offers polyfills to provide support.

+ +

The easiest way to give Babel a try is to use the online version, which allows you to enter your source code on the left, and outputs a transpiled version on the right.

+ +
+

: There are many ways to use Babel (task runners, automation tools, etc.), as you'll see on the setup page.

+
+ +

悪いブラウザーを検出するコードを使う

+ +

All browsers have a user-agent string, which identifies what the browser is (version, name, OS, etc.) In the bad only days when pretty much everyone used Netscape or Internet Explorer, developers used to use so-called browser sniffing code to detect which browser the user was using, and give them appropriate code to work on that browser.

+ +

The code used to look something like this (although this is a simplified example):

+ +
var ua = navigator.userAgent;
+
+if(ua.indexOf('Firefox') !== -1) {
+  // run Firefox-specific code
+} else if(ua.indexOf('Chrome') !== -1) {
+  // run Chrome-specific code
+}
+ +

The idea was fairly good — detect what browser is viewing the site, and run code as appropriate to make sure the browser will be able to use your site OK.

+ +
+

: Try opening up your JavaScript console now and running navigator.userAgent, to see what you get returned.

+
+ +

However, as time went on, developers started to see major problems with this approach. For a start, the code was error prone. What if you knew a feature didn't work in say, Firefox 10 and below, and implemented code to detect this, and then Firefox 11 came out — which did support that feature? Firefox 11 probably wouldn't be supported because it's not Firefox 10. You'd have to change all your sniffing code regularly.

+ +

Many developers implemented bad browser sniffing code and didn't maintain it, and browsers start getting locked out of using websites containing features that they had since implemented. This became so common that browsers started to lie about what browser they were in their user-agent strings (or claim they were all browsers), to get around sniffing code. Browsers also implemented facilities to allow users to change what user-agent string the browser reported when queried with JavaScript. This all made browser sniffing even more error prone, and ultimately pointless. 

+ +
+

: You should read History of the browser user-agent string by Aaron Andersen for a useful and amusing take on this situation.

+
+ +

The lesson to be learned here is — NEVER use browser sniffing. The only really use case for browser sniffing code in the modern day is if you are implementing a fix for a bug in a very specific version of a particular browser. But even then, most bugs get fixed pretty quickly in browser vendor rapid release cycles. It won't come up very often. {{anch("Feature detection")}} is almost always a better option — if you detect whether a feature is supported, you won't need to change your code when new browser versions come out, and the tests are much more reliable.

+ +

If you come across browser sniffing when joining an existing project, look at whether it can be replaced with something more sensible. Browser sniffing causes all kind of interesting bugs, like {{bug(1308462)}}.

+ +

JavaScript プレフィックスを扱う

+ +

In the previous article, we included quite a lot of discussion about handing CSS prefixes. Well, new JavaScript implementations sometimes use prefixes too, although JavaScript uses camel case rather than hyphenation like CSS. For example, if a prefix was being used on a new shint API object called Object:

+ + + +

Here's an example, taken from our violent-theremin demo (see source code), which uses a combination of the Canvas API and the Web Audio API to create a fun (and noisy) drawing tool:

+ +
var AudioContext = window.AudioContext || window.webkitAudioContext;
+var audioCtx = new AudioContext();
+ +

In the case of the Web Audio API, the key entry points to using the API were supported in Chrome/Opera via webkit prefixed versions (they now support the unprefixed versions). The easy way to get around this situation is to create a new version of the objects that are prefixed in some browsers, and make it equal to the non-prefixed version, OR the prefixed version (OR any other prefixed versions that need consideration) — whichever one is supported by the browser currently viewing the site will be used.

+ +

Then we use that object to manipulate the API, rather than the original one. In this case we are creating a modified AudioContext constructor, then creating a new audio context instance to use for our Web Audio coding.

+ +

This pattern can be applied to just about any prefixed JavaScript feature. JavaScript libraries/polyfills also make use of this kind of code, to abstract browser differences away from the developer as much as possible.

+ +

Again, prefixed features were never supposed to be used in production websites — they are subject to change or removal without warning, and cause cross browser issues. If you insist on using prefixed features, make sure you use the right ones. You can look up what browsers require prefixes for different JavaScript/API features on MDN reference pages, and sites like caniuse.com. If you are unsure, you can also find out by doing some testing directly in browsers.

+ +

For example, try going into your browser's developer console and start typing

+ +
window.AudioContext
+ +

If this feature is supported in your browser, it will autocomplete.

+ +

helpを見つける

+ +

There are many other issues you'll encounter with JavaScript; the most important thing to know really is how to find answers online. Consult the HTML and CSS article's Finding help section for our best advice.

+ +

まとめ

+ +

So that's JavaScript. Simple huh? Maybe not so simple, but this article should at least give you a start, and some ideas on how to tackle the JavaScript-related problems you will come across.

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS","Learn/Tools_and_testing/Cross_browser_testing/Accessibility", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ +

 

+ +

このモジュール内

+ + + +

 

diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html new file mode 100644 index 0000000000..297d46d56f --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/testing_strategies/index.html @@ -0,0 +1,372 @@ +--- +title: テスト実行のための戦略 +slug: Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies +tags: + - Article + - Automation + - Beginner + - CodingScripting + - Learn + - Testing + - concepts + - cross browser + - device lab + - user testing + - virtual machine +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Introduction","Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では「(クロス)ブラウザーテストとは何?」「最もよくある問題は何?」「問題をテスト、特定、修正する主な手法は何?」といった質問に答えることで、(クロス)ブラウザーテストの概観を与えることから始めます。

+ + + + + + + + + + + + +
前提条件:HTML, CSS, JavaScript 言語に通じていること; 高レベルのクロスブラウザーテストの原理の理解。
目的:クロスブラウザーテストに含まれる高レベルのコンセプトの理解。
+ +

全部がテスト済み?

+ +

クロスブラウザーテストを実行するとき、ブラウザーのリストを作成する必要があります。ユーザーがあなたのサイトを見る可能性のあるすべてのブラウザーとデバイスの組み合わせをテストする方法はありません — 単に多スすぎるし、新しいものが常に出てきます。

+ +

その代わりに、最も重要なターゲットブラウザー/デバイスを明確にし、それに対して最大限のサポートを広げていくよう守備的にコーディングします。

+ +

守備的にコーディングするとは、ブラウザーで機能やスタイルが動作しない場合に、フォールバックを作るようにすることで、サイトが多少面白みが薄れても受容できるユーザー体験までダウングレードできる — 例えば見た目のすばらしさが失われても、核となる情報にアクセスできることです。

+ +

このねらいは、テスト時に参照できるブラウザー/デバイスの図を作ることです。できるだけ簡単にすることも、できるだけ複雑にすることも、お好みに合わせてできます — 例えば、よくある手法はサポートレベルを次のように複数のグレードに分けることです:

+ +
    +
  1. A グレード: よくある/モダンなブラウザー — 能力のあると知られている。徹底的にテストしてフルサポートを提供する。
  2. +
  3. B グレード: 古い/機能が多くないブラウザー — 能力がないと知られている。基本的な体験をテスト/提供するが、主要な情報やサービスにはするアクセスできるようにする。
  4. +
  5. C グレード: まれな/未知のブラウザー — テストしないが、アクセスを想定する。フルサイトを提供し、少なくとも守備的なコーディングによるフォールバックは動作するようにする。
  6. +
+ +

下記のセクションを通じて、このフォーマットでサポート図を作ります。

+ +
+

: Yahoo は最初にこの手法を、Graded browser Support アプローチとして広めました。

+
+ +

経験則

+ +

これを "仮定"や"感情"と呼ぶかもしれません。これは正確な科学的手法ではありませんが、もウェブ産業の経験のある人にとっては、テストすべきブラウザーについてよくわかるでしょう。サポート図のよい基本となりえます。

+ +

例えば、西ヨーロッパや北アメリカに住んでいる場合、多くが Windows と Mac のデスクトップ/ノートPCを使っていて、主なブラウザーはChrome, Firefox, Safari, IE, Edge です。このブラウザーは定期的な更新があるため、おそらく最初の3つの最新版だけをテストしたいでしょう。Edge と IE では、いくつかの最新バージョンをテストしたくなるでしょう; これらはすべて A グレード区分にすべきでしょう.

+ +
+

: You can only have one version of IE or Edge installed on a machine at once, so you will probably have to use virtual machine, or other strategy to do the testing you need. See {{anch("Virtual machines")}} later on.

+
+ +

多くの人が iOS と Android を使っているので、iOS Safari の最新版、古い Android 内蔵ブラウザーの最新版いくつか、iOS と Android 用の Chrome と Firefox もテストしたくなるでしょう。これらをスマフォとタブレットの両方でテストし、レスポンシブデザインの動作が問題ないのを確認するのが理想でしょう。

+ +

それなりの数の人がまだ IE 9 を使っていることも知っているかもしれません。これは古くて能力もないので、B グレード区分に区分しましょう。

+ +

ここまでで以下のサポート図ができました:

+ +
    +
  1. A グレード: Windows/Mac 用の Chrome と Firefox、Mac 用の Safari、Windows 用の Edge と IE (それぞれ最新の2バージョン)、iPhone/iPad 用の iOS Safari、スマフォ/タブレット用の Android 内蔵ブラウザー (最新2バージョン)、スマフォ/タブレット用の Chrome と Firefox(最新2バージョン)。
  2. +
  3. B グレード: Windows 用 IE 9
  4. +
  5. C グレード: n/a
  6. +
+ +

どこか別の場所に住んでいる場合や、どこか別の場所向けの (例 ある国やロケール)サイトを制作している場合、テストする主なブラウザーはたぶん別のものでしょう。

+ +
+

: "The CEO of my company uses a Blackberry, so we'd better make sure it looks good on that" can also be a persuasive argument.

+
+ +

ブラウザーサポートステータス

+ +

ブラウザーテスト選択で求められる、便利な対策は、ブラウザーサポートステータスです。こんなステータスを提供するサイトはたくさんあります。例えば、:

+ + + +

これらはいずれも北米中心で、正確でないですが、幅広いトレンドの理解を得られます。

+ +

例えば、Netmarketshareを見てみましょう。Opera が少しだが、使用される数が見えるので、Cグレードとしてサポート図に追加するべきでしょう。

+ +

IE8 もある程度ありますが、古くてもはや利用できませんOpera Mini もいくらかありますが、複雑な JavaScript 実行など (詳しくは Opera Mini and JavaScript を見てください)が利用できません。これはグレード B に追加すべきでしょう。

+ +

アクセス解析を使う

+ +

A much more accurate source of data, if you can get it, comes from an analytics app like Google Analytics. This is an application that will give you accurate stats on exactly what browsers people are using to browse your site. Of course, this relies on you already having a site to use it on, so it isn't much good for completely new sites.

+ +

But an analytics history can be useful for finding support stats to influence say a new version of a company's site, or new features you are adding to an existing site. If you have these available, they are far more accurate than global browser stats like those mentioned above.

+ +

You may also consider using open source and privacy focussed analytics platforms like Open Web Analytics and Matomo. They expect you to self-host the analytics platform. 

+ +

Setting up Google analytics

+ +
    +
  1. First of all, you'll need a Google account. Use this account to sign into Google Analytics.
  2. +
  3. Choose the Google Analytics (web) option, and click the Sign Up button.
  4. +
  5. Enter your web site/app details into the signup page. This is fairly intuitive to set up; the most important field to get right is the Website URL. This needs to be your site/app's root URL.
  6. +
  7. Once you've finished filling in everything, press the Get Tracking ID button, then accept the terms of service that appear.
  8. +
  9. The next page provides you with some code snippets and other instructions. For a basic website, what you need to do is copy the Website tracking code block and paste it into all the different pages you want to track using Google Analytics on your site. You could below your closing </body> tag, or somewhere else appropriate that keeps it from getting muddled up with your application code.
  10. +
  11. Upload the changes to the development server, or wherever else you need your code.
  12. +
+ +

That's it! Your site should now be ready to start reporting analytics data.

+ +

Studying analytics data

+ +

Now you should be able to go back to the Analytics Web homepage, and start looking at the data you've collected about your site (you need to leave a little bit of time for some data to actually be collected, of course.)

+ +

既定では, you should see the reporting tab, like so:

+ +

+ +

There is a huge amount of data you could look at using Google Analytics — customized reports in different categories, etc. — and we haven't got time to discuss it all. Getting started with Analytics provides some useful guidance on reporting (and more) for beginners.

+ +

You should also be encouraged to look at the different options on the left hand side, and see what kinds of data you can find out. 例えば、you can find out what browsers and operating systems your users are using by selecting Audience > Technology > Browser & OS from the left hand menu.

+ +
+

: When using Google analytics, you need to beware of misleading bias, e.g. "We  have no Firefox Mobile users" might lead you to not bother supporting Firefox mobile. But you are not going to have any Firefox Mobile users if the site was broken on Firefox mobile in the first place.

+
+ +

その他の考慮

+ +

There are other considerations that you should probably include as well. You should definitely include accessibility as a grade A testing requirement (we'll cover exactly what you should test in our Handling common accessibility problems article)

+ +

Plus you might have other considerations. If you are creating some kind of company intranet for delivering sales figures to managers, and all the managers have been provided with Windows phones 例えば、you might want to make mobile IE support a priority.

+ +

最終的なサポート図

+ +

So, our final support chart will end up looking like so:

+ +
    +
  1. A grade: Chrome and Firefox for Windows/Mac, Safari for Mac, Edge and IE for Windows (last two versions of each), iOS Safari for iPhone/iPad, Android stock browser (last two versions) on phone/tablet, Chrome and Firefox for Android (last two versions) on phone tablet. Accessibility passing common tests.
  2. +
  3. B grade: IE 8 and 9 for Windows, Opera Mini.
  4. +
  5. C grade: Opera, other niche modern browsers.
  6. +
+ +

これから何をテストしていくのか?

+ +

When you've got a new addition to your codebase that needs testing, before you start testing you should write out a list of testing requirements that need to pass to be accepted. These requirements can be visual or functional — both combine to make a usable web site feature.

+ +

Consider the following example (see the source code, and also the example running live):

+ +

+ +

Test criteria for this feature could written like so:

+ +

A and B grade:

+ + + +

A grade:

+ + + +

You may notice from the text in the example that it won't work in IE8 — this is a problem according to our support chart, which you'll have to work on, perhaps by using a feature detection library to implement the functionality in a different way if the browser doesn't support CSS transitions (see Implementing feature detection, later on in the course).

+ +

You might also notice that the button isn't usable using only the keyboard — this also needs to be remedied. Maybe we could use some JavaScript to implement a keyboard control for the toggle, or use some other method entirely?

+ +

These test criteria are useful, because:

+ + + +

Putting together a testing lab

+ +

One option for carrying out browser tests is to do the testing yourself. To do this, you will probably use a combination of actual physical devices, and emulated environments (using either an emulator or a virtual machine).

+ +

物理デバイス

+ +

It is generally better to have a real device running the browser you want to test — this provides the greatest accuracy in terms of behaviour and overall user experience. You'll probably want something like the following, for a reasonable low level device lab:

+ + + +

The following are also good options, if you can get them:

+ + + +

Your main work machine can also be a place to install other tools for specific purposes, such as accessibility auditing tools, screen readers, and emulators/virtual machines.

+ +

Some larger companies have device labs that stock a very large selection of different devices, enabling developers to hunt down bugs on very specific browser/device combinations. Smaller companies and individuals are generally not able to afford such a sophisticated lab, so tend to make do with smaller labs, emulators, virtual machines, and commercial testing apps.

+ +

We will cover each of the other options below.

+ +
+

: Some efforts have been made to create publically accessible device labs — see Open Device Labs.

+
+ +
+

: We also need to consider accessibility — there are a number of useful tools you can install on your machine to facilitate accessibility testing, but we'll cover those in the Handling common accessibility problems article, later in the course.

+
+ +

エミュレーター

+ +

Emulators are basically programs that run inside your computer and emulate a device or particular device conditions of some kind, allowing you to do some of your testing more conveniently than having to find a particular combination of hardware/software to test.

+ +

An emulator might be as simple as testing a device condition. 例えば、if you want to do some quick and dirty testing of your width/height media queries for responsive design, you could use Firefox's Responsive Design Mode. Safari has a similar mode too, which can be enabled by going to Safari > Preferences, and checking Show Develop menu, then choosing Develop > Enter Responsive Design Mode. Chrome also has something similar: Device mode (see Simulate Mobile Devices with Device Mode). 

+ +

More often than not though, you'll have to install some kind of emulator. The most common devices/browsers you'll want to test are as follows:

+ + + +

You can often find simulators for other mobile device environments too, 例えば、:

+ + + +
+

: Many emulators actually require the use of a virtual machine (see below); when this is the case, instructions are often provided, and/or use of the virtual machine is incorporated into the installer of the emulator.

+
+ +

仮想マシン

+ +

Virtual machines are applications that run on your desktop computer and allow you to run emulations of entire operating systems, each compartmentalized in its own virtual hard drive (often represented by a single large file existing on the host machine's hard drive). There are a number of popular virtual machine apps available, such as Parallels, VMWare, and Virtual Box; we personally like the latter, because it is free.

+ +
+

: You need a lot of hard disk space available to run virtual machine emulations; each operating system you emulate can take up a lot of memory. You tend to choose the hard drive space you want for each install; you could get away with probably 10GB, but some sources recommend up to 50GB or more, so the operating system will run reliably. A good option provided by most virtual machine apps is to create a dynamically allocated hard drive that grows and shrinks as the need arises.

+
+ +

To use a Virtual Box, you need to:

+ +
    +
  1. Get hold of an installer disk or image (e.g. ISO file) for the operating system you want to emulate. Virtual Box is unable to provide these; most, like Windows OSes, are commercial products that can't be freely distributed.
  2. +
  3. Download the appropriate installer for your operating system and install it.
  4. +
  5. Open the app; you'll be presented with a view like the following:
  6. +
  7. To create a new virtual machine, press the New button in the top left hand corner.
  8. +
  9. Follow the instructions and fill in the following dialog boxes as appropriate. You'll: +
      +
    1. Provide a name for the new virtual machine
    2. +
    3. Choose with operating system and version you are installing on it
    4. +
    5. Set how much RAM should be allocated (we'd recommend something like 2048MB, or 2GB)
    6. +
    7. Create a virtual hard disk (choose the default options across the three dialog boxes containing Create a virtual hard disk now, VDI (virtual disk image), and Dynamically allocated).
    8. +
    9. Choose the file location and size for the virtual hard disk (choose a sensible name and location to keep it, and for the size specify around 50GB, or as much as you are comfortable with specifying).
    10. +
    +
  10. +
+ +

Now the new virtual box should appear in the left hand menu of the main Virtual Box UI window. At this point, you can double-click to open it — it will start to boot up the virtual machine, but it won't yet have the operating system (OS) installed. At this point you need to point the dialog box at the installer image/disk, and it will run through the steps to install the OS just like on a physical machine.

+ +

+ +
+

Important: You need to make sure you have the operating system image you want to install on the virtual machine available at this point, and install it right away. If you cancel the process at this point, it can render the virtual machine unusable, and make it so you need to delete it and create it again. This is not fatal, but it is annoying.

+
+ +

After the process has completed, you should have a virtual machine running an operating system inside a window on your host computer.

+ +

+ +

You need to treat this virtual operating system installation just like you would any real installation — 例えば、as well as installing the browsers you want to test, install an anti-virus program to protect it from viruses.

+ +

Having multiple virtual machines is very useful, particularly for Windows IE/Edge testing — on Windows, you are not able to have multiple versions of the default browser installed side by side, so you might want to build up a library of virtual machines to handle different tests as required, e.g.:

+ + + +
+

: Another good thing about virtual machines is that the virtual disk images are fairly self-contained. If you are working on a team, you can create one virtual disk image, then copy it and pass it around. Just make sure you have the required licenses to run all those copies of Windows or whatever else you are running, if it is a licensed product.

+
+ +

自動化と商用アプリ

+ +

As mentioned in the last chapter, you can take a lot of the pain out of browser testing by using some kind of automation system. You can set up your own testing automation system (Selenium being the popular app of choice), which does take some setup, but can be very rewarding when you get it worked out.

+ +

There are also commercial tools available such as Sauce Labs and Browser Stack that do this kind of thing for you, without you having to worry about the setup, if you wish to invest some money in your testing.

+ +

We will look at how to use such tools later on in the module.

+ +

ユーザーテスト

+ +

Before we move on, we'll finish this article off by talking a bit about user testing — this can be a good option if you have a willing user group to test your new functionality on. Bear in mind that this can be as lo-fi or as sophisticated as you like — your user group could be a group of friends, a group of colleagues, or a group of unpaid or paid volunteers, depending on whether you have any money to spend on testing.

+ +

Generally you'll get your users to look at the page or view containing the new functionality on some kind of a development server, so you are not putting the final site or change live until it is finished. You should get them to follow some steps and report the results they get. It is useful to provide a set of steps (sometimes called a script) so that you get more reliable results pertaining to what you were trying to test. We mentioned this in the {{anch("What are you going to test")}} section above — it is easy to turn the test criteria detailed there into steps to follow. 例えば、the following would work for a sighted user:

+ + + +

When running tests, it can also be a good idea to:

+ + + +

These steps are designed to make sure that the browser you are testing in is as "pure" as possible, i.e. there is nothing installed that could affect the results of the tests.

+ +
+

: Another useful lo-fi option, if you have the hardware available, is to test your sites on low-end phones/other devices — as sites get larger and feature more effects, there is a higher chance of the site slowing down, so you need to start giving performance more consideration. Trying to get your functionality working on a low end device will make it more likely that the experience will be good on higher-end devices.

+
+ +
+

: Some server-side development environments provide useful mechanisms for rolling out site changes to only a subset of users, providing a useful mechanism for getting a feature tested by a subset of users without the need for a separate development server. An example is Django Waffle Flags.

+
+ +

まとめ

+ +

この記事を読んで、ターゲット顧客/ブラウザーの表を特定して、その表に載っているクロスブラウザーテストを効率的に実行することが良くわかったでしょう。

+ +

次には HTML と CSSから始めて、テストで見つけにくいコードの問題に注目していきましょう。

+ +

{{PreviousMenuNext("Learn/Tools_and_testing/Cross_browser_testing/Introduction","Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ + + +

このモジュール内

+ + diff --git a/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html b/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html new file mode 100644 index 0000000000..ffdd4984a0 --- /dev/null +++ b/files/ja/learn/tools_and_testing/cross_browser_testing/your_own_automation_environment/index.html @@ -0,0 +1,688 @@ +--- +title: テスト自動化環境をセットアップする +slug: Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment +tags: + - Article + - Automation + - Beginner + - Browser + - CodingScripting + - Learn + - Testing + - Tools + - cross browser + - selenium +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}
+ +

この記事では、Selenium/WebDriver や selenium-webdriver for Node のようなテストライブラリーを使って、自動化環境のインストールとテストを実行する方法を教えます。またあなたのローカルテスト環境と、以前の記事で見てきたような商用アプリとを統合する方法についても見て行きます。

+ + + + + + + + + + + + +
前提条件:HTML, CSSJavaScript のコア機能、principles of cross browser testingautomated testingなどの高レベルのアイデアに精通していること。
目的:Seleniumによるローカルテスト環境のセットアップ方法やSeleniumを使用したテストの実行方法、Sauce LabsやBrowserStackなどのツールとの統合する方法の案内。
+ +

Selenium

+ +

Selenium は最も人気のあるブラウザ自動化ツールです。他の方法もありますが、Selenium を使用する最良の方法は WebDriver を使用することで、強力な API で Selenium 上に構築し、ブラウザを呼び出して自動化し、「このWebページを開く」、「この要素をページ上に移動する」、「このリンクをクリックする」、「リンクがこのURLを開くかどうかを確認する」などといったアクションを実行します。これは、自動テストを実行するのに最適です。
+
+ WebDriverのインストール方法と使用方法は、テストの作成と実行に使用するプログラミング環境によって異なります。最も一般的な環境では、WebDriverとその言語、例えばJava、C#、Ruby、Python、JavaScript(Node)などを使用してWebDriverと通信するのに必要なバインディングをインストールするパッケージまたはフレームワークが利用可能です。異なる言語のSeleniumのセットアップの詳細については、 Setting Up a Selenium-WebDriver Project を参照してください。
+
+ 異なるブラウザでは、WebDriverと通信して制御するために異なるドライバが必要です。ブラウザのドライバの入手先などについては、 Platforms Supported by Selenium を参照してください。
+
+ Node.jsを使用したSeleniumテストの作成と実行については、始める前にすばやく簡単に行うことができ、フロントエンド開発者にはもっと使い慣れた環境を提供する予定です。

+ +
+

: 他のサーバーサイド環境でWebDriverを使用する方法を知りたい場合は、Platforms Supported by Seleniumもチェックしてください。

+
+ +

Node で Selenium のセットアップ

+ +
    +
  1. まず、最後の章の Setting up Node and npm で説明しているように、新しいnpmプロジェクトをセットアップします。selenium-testのように違うものを呼んでください。
  2. +
  3. 次に私たちはNodeの内部からSeleniumが機能するようにフレームワークをインストールする必要があります。 更新頻度が高く、よく改善されるため、私たちはselenium-webdriverを選択します。もしも他の選択をするならばwebdriver.io と nightwatch.js もいい選択です。selenium-webdriverをインストールするため, プロジェクトフォルダの下で以下のコマンドを走らせます:
  4. +
  5. +
    npm install selenium-webdriver
    +
  6. +
+ +
+

: 以前に selenium-webdriver をインストールしてブラウザドライバをダウンロードした場合でも、これらの手順を実行することをお勧めします。すべてが最新であることを確認する必要があります。

+
+ +

Next, you need to download the relevant drivers to allow WebDriver to control the browsers you want to test. You can find details of where to get them from on the selenium-webdriver page (see the table in the first section.) Obviously, some of the browsers are OS-specific, but we're going to stick with Firefox and Chrome, as they are available across all the main OSes.

+ +
    +
  1. Download the latest GeckoDriver (for Firefox) and ChromeDriver drivers.
  2. +
  3. Unpack them into somewhere fairly easy to navigate to, like the root of your home user directory.
  4. +
  5. Add the chromedriver and geckodriver driver's location to your system PATH variable. This should be an absolute path from the root of your hard disk, to the directory containing the drivers. 例えば、if we were using a Mac OS X machine, our user name was bob, and we put our drivers in the root of our home folder, the path would be /Users/bob.
  6. +
+ +
+

: Just to reiterate, the path you add to PATH needs to be the path to the directory containing the drivers, not the paths to the drivers themselves! This is a common mistake.

+
+ +

To set your PATH variable on Mac OS X/most Linux systems:

+ +
    +
  1. Open your .bash_profile (or .bashrc) file (if you can't see hidden files, you'll need to display them, see Show/Hide hidden files in Mac OS X or Show hidden folders in Ubuntu).
  2. +
  3. Paste the following into the bottom of your file (updating the path as it actually is on your machine): +
    #Add WebDriver browser drivers to PATH
    +
    +export PATH=$PATH:/Users/bob
    +
  4. +
  5. Save and close this file, then restart your Terminal/command prompt to reapply your Bash configuration.
  6. +
  7. Check that your new paths are in the PATH variable by entering the following into your terminal: +
    echo $PATH
    +
  8. +
  9. You should see it printed out in the terminal.
  10. +
+ +

To set your PATH variable on Windows, follow the instructions at How can I add a new folder to my system path?

+ +

OK, let's try a quick test to make sure everything is working.

+ +
    +
  1. Create a new file inside your project directory called google_test.js:
  2. +
  3. Give it the following contents, then save it: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +var driver = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .build();
    +
    +driver.get('http://www.google.com');
    +
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. In terminal, make sure you are inside your project folder, then enter the following command: +
    node google_test
    +
  6. +
+ +

You should see an instance of Firefox automatically open up! Google should automatically be loaded in a tab, "webdriver" should be entered in the search box, and the search button will be clicked. WebDriver will then wait for 2 seconds; the document title is then accessed, and if it is "webdriver - Google Search", we will return a message to claim the test is passed. WebDriver will then close down the Firefox instance and stop.

+ +

一度に複数ブラウザでテストする

+ +

There is also nothing to stop you running the test on multiple browsers simulataneously. Let's try this!

+ +
    +
  1. Create another new file inside your project directory called google_test_multiple.js. You can feel free to change the references to some of the other browsers we added, remove them, etc., depending on what browsers you have available to test on your operating system. You'll need to make sure you have the right browser drivers set up on your system. In terms of what string to use inside the .forBrowser() method for other browsers,  see the Browser enum reference page.
  2. +
  3. Give it the following contents, then save it: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +var driver_fx = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .build();
    +
    +var driver_chr = new webdriver.Builder()
    +    .forBrowser('chrome')
    +    .build();
    +
    +searchTest(driver_fx);
    +searchTest(driver_chr);
    +
    +function searchTest(driver) {
    +  driver.get('http://www.google.com');
    +  driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +  driver.sleep(1000).then(function() {
    +    driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +  });
    +
    +  driver.findElement(By.name('btnK')).click();
    +
    +  driver.sleep(2000).then(function() {
    +    driver.getTitle().then(function(title) {
    +      if(title === 'webdriver - Google Search') {
    +        console.log('Test passed');
    +      } else {
    +        console.log('Test failed');
    +      }
    +    });
    +  });
    +
    +  driver.quit();
    +}
    +
  4. +
  5. In terminal, make sure you are inside your project folder, then enter the following command: +
    node google_test_multiple
    +
  6. +
  7. If you are using a Mac and do decide to test Safari, you might get an error message along the lines of "Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver." If you get this, follow the given instruction and try again.
  8. +
+ +

So here we've done the test as before, except that this time we've wrapped it inside a function, searchTest(). We've created new browser instances for multiple browsers, then passed each one to the function so the test is performed on all three browsers!

+ +

Fun huh? Let's move on, look at the basics of WebDriver syntax, in a bit more detail.

+ +

WebDriver 構文クラッシュコース

+ +

Let's have a look at a few key features of the webdriver syntax. For more complete details, you should consult the selenium-webdriver JavaScript API reference for a detailed reference, and the Selenium main documentation's Selenium WebDriver and WebDriver: Advanced Usage pages, which contain multiple examples to learn from written in different languages.

+ +

新しいテストを始める

+ +

To start up a new test, you need to include the selenium-webdriver module like this:

+ +
var webdriver = require('selenium-webdriver'),
+    By = webdriver.By,
+    until = webdriver.until;
+ +

Next, you need to create a new instance of a driver, using the new webdriver.Builder() constructor. This needs to have the forBrowser() method chained onto it to specify what browser you want to test with this builder, and the build() method to actually build it (see the Builder class reference for detailed information on these features).

+ +
var driver = new webdriver.Builder()
+    .forBrowser('firefox')
+    .build();
+ +

Note that it is possible to set specific configuration options for browsers to be tested, 例えば、you can set a specific version and OS to test in the forBrowser() method:

+ +
var driver = new webdriver.Builder()
+    .forBrowser('firefox', '46', 'MAC')
+    .build();
+ +

You could also set these options using an environment variable, 例えば、:

+ +
SELENIUM_BROWSER=firefox:46:MAC
+ +

Let's create a new test to allow us to explore this code as we talk about it. Inside your selenium test project directory, create a new file called quick_test.js, and add the following code to it:

+ +
var webdriver = require('selenium-webdriver'),
+    By = webdriver.By,
+    until = webdriver.until;
+
+var driver = new webdriver.Builder()
+    .forBrowser('firefox')
+    .build();
+ +

テストするドキュメントの取得

+ +

To load the page you actually want to test, you use the get() method of the driver instance you created earlier, 例えば、:

+ +
driver.get('http://www.google.com');
+ +
+

: See the WebDriver class reference for details of the features in this section and the ones below it.

+
+ +

You can use any URL to point to your resource, including a file:// URL to test a local document:

+ +
driver.get('file:///Users/chrismills/git/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html');
+ +

or

+ +
driver.get('http://localhost:8888/fake-div-buttons.html');
+ +

But it is better to use a remote server location so the code is more flexible — when you start using a remote server to run your tests (see later on), your code will break if you try to use local paths. 

+ +

Add this line to the bottom of quick_test.js now:

+ +
driver.get('http://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html');
+ +

文書とのやりとり

+ +

Now we've got a document to test, we need to interact with it in some way, which usually involves first selecting a specific element to test something about. You can select UI elements in many ways in WebDriver, including by ID, class, element name, etc. The actual selection is done by the findElement() method, which accepts as a parameter a selection method. 例えば、to select an element by ID:

+ +
var element = driver.findElement(By.id('myElementId'));
+ +

One of the most useful ways to find an element by CSS — the  By.css method allows you to select an element using a CSS selector

+ +

Enter the following at the bottom of your quick_test.js code now:

+ +
var button = driver.findElement(By.css('button:nth-of-type(1)'));
+ +

要素のテスト

+ +

There are many ways to interact with your web documents and elements on them. You can see useful common examples starting at Getting text values on the WebDriver docs.

+ +

If we wanted to get the text inside our button, we could do this:

+ +
button.getText().then(function(text) {
+  console.log('Button text is \'' + text + '\'');
+});
+ +

Add this to quick_test.js now.

+ +

Making sure you are inside your project directory, try running the test:

+ +
node quick_test.js
+ +

You should see the button's text label reported inside the console.

+ +

let's do something a bit more useful. delete the previous code entry, then add this line at the bottom instead:

+ +
button.click();
+ +

Try running your test again; the button will be clicked, and the alert() popup should appear. At least we know the button is working!

+ +

You can interact with the popup too. Add the following to the bottom of the code, and try testing it again:

+ +
var alert = driver.switchTo().alert();
+
+alert.getText().then(function(text) {
+  console.log('Alert text is \'' + text + '\'');
+});
+
+alert.accept();
+ +

Next, let's try entering some text into one of the form elements. Add the following code and try running your test again:

+ +
var input = driver.findElement(By.id('input1'));
+input.sendKeys('Filling in my form');
+ +

You can submit key presses that can't be represented by normal characters using properties of the webdriver.Key object. 例えば、above we used this construct to tab out of the form input before submitting it:

+ +
driver.sleep(1000).then(function() {
+  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
+});
+
+ +

何かが完了するのを待つ

+ +

There are times where you'll want to make WebDriver wait for something to complete before carrying on. 例えば、if you load a new page, you'll want to wait for the page's DOM to finish loading before you try to interact with any of its elements, otherwise the test will likely fail.

+ +

In our google_test.js test 例えば、we included this block:

+ +
driver.sleep(2000).then(function() {
+  driver.getTitle().then(function(title) {
+    if(title === 'webdriver - Google Search') {
+      console.log('Test passed');
+    } else {
+      console.log('Test failed');
+    }
+  });
+});
+ +

The sleep() method accepts a value that specifies the time to wait in milliseconds — the method returns a promise that resolves at the end of that time, at which point the code inside the then() executes. In this case we get the title of the current page with the getTitle() method, then return a pass or fail message depending on what its value is.

+ +

We could add a sleep() method to our quick_test.js test too — try wrapping your last line of code in a block like this:

+ +
driver.sleep(2000).then(function() {
+  input.sendKeys('Filling in my form');
+  input.getAttribute("value").then(function(value) {
+    if(value !== '') {
+      console.log('Form input editable');
+    }
+  });
+});
+ +

WebDriver will now wait for 2 seconds before filling in the form field. We then test whether its value got filled in (i.e. is not empty) by using getAttribute() to retrieve it's value attribute value, and print a message to the console if it is not empty.

+ +
+

: There is also a method called wait(), which repeatedly tests a condition for a certain length of time, and then carries on executing the code. This also makes use of the util library, which defines common conditions to use along with wait().

+
+ +

使用後のドライバのシャットダウン

+ +

After you've finished running a test, you should shut down any dirver instances you've opened, to make sure that you don't end up with loads of rogue browser instances open on your machine! This is done using the quit() method. Simply call this on your driver instance when you are finished with it. Add this line to the bottom of your quick_test.js test now:

+ +
driver.quit();
+ +

When you run it, you should now see the test execute and the browser instance shut down again after the text is complete. This is useful for not cluttering up your computer with loads of browser instances, especially if you have so many that it is causing the computer to slow down.

+ +

テストのベストプラクティス

+ +

There has been a lot written about best practices for writing tests. You can find some good background information at Test Design Considerations. In general, you should make sure that your tests are:

+ +
    +
  1. Using good locator strategies: When you are {{anch("Interacting with the document")}}, make sure that you use locators and page objects that are unlikely to change — if you have a testable element that you want to perform a test on, make sure that it has a stable ID, or position on the page that can be selected using a CSS selector, which isn't going to just change with the next site iteration. You want to make your tests as non-brittle as possible, i.e. they won't just break when something changes.
  2. +
  3. Write atomic tests: Each test should test one thing only, making it easy to keep track of what test file is testing which criterion. As an example, the google_test.js test we looked at above is pretty good, as it just tests a single thing — whether the title of a search results page is set correctly. We could work on giving it a better name so it is easier to work out what it does if we add more google tests. Perhaps results_page_title_set_correctly.js would be slightly better?
  4. +
  5. Write autonomous tests: Each test should work on it's own, and not depend on other tests to work.
  6. +
+ +

In addition, we should mention test results/reporting — we've been reporting results in our above examples using simple console.log() statements, but this is all done in JavaScript, so you can use whatever test running and resorting system you want, be it Mocha/Chai/some other kind of combination.

+ +
    +
  1. 例えば、try making a local copy of our mocha_test.js example inside your project directory. Put it inside a subfolder called test. This example uses a long chain of promises to run all the steps required in our test — the promise-based methods WebDriver uses need to resolve for it to work properly.
  2. +
  3. Install the mocha test harness by running the following command inside your project directory: +
    npm install --save-dev mocha
    +
  4. +
  5. you can now run the test (and any others you put inside your test directory) using the following command: +
    mocha --no-timeouts
    +
  6. +
  7. You should include the --no-timeouts flag to make sure your tests don't end up failing because of Mocha's arbitrary timeout (which is 3 seconds).
  8. +
+ +
+

: saucelabs-sample-test-frameworks contains several useful examples showing how to set up different combinations of test/assertion tools.

+
+ +

リモートテストの実行

+ +

It turns out that running tests on remote servers isn't that much more difficult than running them locally. You just need to create your driver instance, but with a few more features specified, including the capabilities of the browser you want to test on, the address of the server, and the user credentials you need (if any) to access it.

+ +

BrowserStack

+ +

Getting Selenium tests to run remotely on BrowserStack is easy. The code you need should follow the pattern seen below.

+ +

Let's write an example:

+ +
    +
  1. Inside your project directory, create a new file called bstack_google_test.js.
  2. +
  3. Give it the following contents: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +// Input capabilities
    +var capabilities = {
    +   'browserName' : 'Firefox',
    +   'browser_version' : '56.0 beta',
    +   'os' : 'OS X',
    +   'os_version' : 'Sierra',
    +   'resolution' : '1280x1024',
    +   'browserstack.user' : 'YOUR-USER-NAME',
    +   'browserstack.key' : 'YOUR-ACCESS-KEY',
    +   'browserstack.debug' : 'true',
    +   'build' : 'First build'
    +};
    +
    +var driver = new webdriver.Builder().
    +  usingServer('http://hub-cloud.browserstack.com/wd/hub').
    +  withCapabilities(capabilities).
    +  build();
    +
    +driver.get('http://www.google.com');
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. From your BrowserStack automation dashboard, get your user name and access key (see Username and Access Keys). Replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (and make sure you keep them secure).
  6. +
  7. Run your test with the following command: +
    node bstack_google_test
    + The test will be sent to BrowserStack, and the test result will be returned to your console. This shows the importance of including some kind of result reporting mechanism!
  8. +
  9. Now if you go back to the BrowserStack automation dashboard page, you'll see your test listed:
    +
  10. +
+ +

If you click on the link for your test, you'll get to a new screen where you will be able to see a video recording of the test, and multiple detailed logs of information pertaining to it.

+ +
+

: The Resources menu option on the Browserstack automation dashboard contains a wealth of useful information on using it to run automated tests. See Node JS Documentation for writing automate test scripts in Node JS for the node-specific information. Expore the docs to find out all the useful things BrowserStack can do.

+
+ +
+

: If you don't want to write out the capabilities objects for your tests by hand, you can generate them using the generators embedded in the docs. See Run tests on mobile browsers and Run tests on desktop browsers.

+
+ +

プログラムによるBrowserStackテストの詳細の入力

+ +

You can use the BrowserStack REST API and some other capabilities to annotate your test with more details, such as whether it passed, why it passed, what project the test is part of, etc. BrowserStack doesn't know these details 既定では!

+ +

Let's update our bstack_google_test.js demo, to show how these features work:

+ +
    +
  1. First, we 'll need to import the node request module, so we can use it to send requests to the REST API. Add the following line at the very top of your code: +
    var request = require("request");
    +
  2. +
  3. Now we'll update our capabilities object to include a project name — add the following line before the closing curly brace, remembering to add a comma at the end of the previous line (you can vary the build and project names to organize the tests in different windows in the BrowserStack automation dashboard): +
    'project' : 'Google test 2'
    +
  4. +
  5. Next we need to access the sessionId of the current session, so we know where to send the request (the ID is included in the request URL, as you'll see later). Include the following lines just below the block that creates the driver object (var driver ...) : +
    var sessionId;
    +
    +driver.session_.then(function(sessionData) {
    +    sessionId = sessionData.id_;
    +});
    +
  6. +
  7. Finally, update the driver.sleep(2000) ... block near the bottom of the code to add REST API calls (again, replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values): +
    driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +      request({uri: "https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/" + sessionId + ".json", method:"PUT", form:{"status":"passed","reason":"Google results showed correct title"}});
    +    } else {
    +      console.log('Test failed');
    +      request({uri: "https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/" + sessionId + ".json", method:"PUT", form:{"status":"failed","reason":"Google results showed wrong title"}});
    +    }
    +  });
    +});
    +
  8. +
+ +

These are fairly intuitive — once the test completes, we send an API call to BrowserStack to update the test with a passed or failed status, and a reason for the result.

+ +

If you now go back to your BrowserStack automation dashboard page, you should see your test session available, as before, but with the updated data attached to it:

+ +

+ +

Sauce Labs

+ +

Getting Selenium tests to run remotely on Sauce Labs is also very simple, and very similar to BrowserStack albeit with a few syntactic differences. The code you need should follow the pattern seen below.

+ +

Let's write an example:

+ +
    +
  1. Inside your project directory, create a new file called sauce_google_test.js.
  2. +
  3. Give it the following contents: +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until,
    +    username = "YOUR-USER-NAME",
    +    accessKey = "YOUR-ACCESS-KEY";
    +
    +var driver = new webdriver.Builder()
    +    .withCapabilities({
    +      'browserName': 'chrome',
    +      'platform': 'Windows XP',
    +      'version': '43.0',
    +      'username': username,
    +      'accessKey': accessKey
    +    })
    +    .usingServer("https://" + username + ":" + accessKey +
    +          "@ondemand.saucelabs.com:443/wd/hub")
    +    .build();
    +
    +driver.get('http://www.google.com');
    +
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  4. +
  5. From your Sauce Labs user settings, get your user name and access key. Replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (and make sure you keep them secure).
  6. +
  7. Run your test with the following command: +
    node sauce_google_test
    + The test will be sent to Sauce Labs, and the test result will be returned to your console. This shows the importance of including some kind of result reporting mechanism!
  8. +
  9. Now if you go to your Sauce Labs Automated Test dashboard page, you'll see your test listed; from here you'll be able to see videos, screenshots, and other such data.
    +
  10. +
+ +
+

: Sauce Labs' Platform Configurator is a useful tool for generating capability objects to feed to your driver instances, based on what browser/OS you want to test on.

+
+ +
+

: for more useful details on testing with Sauce Labs and Selenium, check out Getting Started with Selenium for Automated Website Testing, and Instant Selenium Node.js Tests.

+
+ +

Sauce Labsテストの詳細をプログラムで書き込む

+ +

You can use the Sauce Labs API to annotate your test with more details, such as whether it passed, the name of the test, etc. Sauce Labs doesn't know these details 既定では!

+ +

To do this, you need to:

+ +
    +
  1. Install the Node Sauce Labs wrapper using the following command (if you've not already done it for this project): +
    npm install saucelabs --save-dev
    +
  2. +
  3. Require saucelabs — put this at the top of your sauce_google_test.js file, just below the previous variable declarations: +
    var SauceLabs = require('saucelabs');
    +
  4. +
  5. Create a new instance of SauceLabs, by adding the following just below that: +
    var saucelabs = new SauceLabs({
    +    username : "YOUR-USER-NAME",
    +    password : "YOUR-ACCESS-KEY"
    +});
    + Again, replace the YOUR-USER-NAME and YOUR-ACCESS-KEY placeholders in the code with your actual user name and access key values (note that the saucelabs npm package rather confusingly uses password, not accessKey). Since you are using these twice now, you may want to create a couple of helper variables to store them in.
  6. +
  7. Below the block where you define the driver variable (just below the build() line), add the following block — this gets the correct driver sessionID that we need to write data to the job (you can see it action in the next code block): +
    driver.getSession().then(function (sessionid){
    +      driver.sessionID = sessionid.id_;
    +});
    +
  8. +
  9. Finally, replace the driver.sleep(2000) ... block near the bottom of the code with the following: +
    driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +      var testPassed = true;
    +    } else {
    +      console.log('Test failed');
    +      var testPassed = false;
    +    }
    +
    +    saucelabs.updateJob(driver.sessionID, {
    +      name: 'Google search results page title test',
    +      passed: testPassed
    +    });
    +  });
    +});
    +
  10. +
+ +

Here we've set a testPassed variable to true or false depending on whether the test passed or fails, then we've used the saucelabs.updateJob() method to update the details.

+ +

If you now go back to your Sauce Labs Automated Test dashboard page, you should see your new job now has the updated data attached to it:

+ +

+ +

自身のリモートサーバ

+ +

If you don't want to use a service like Sauce Labs or BrowserStack, you can always set up your own remote testing server. Let's look at how to do this.

+ +
    +
  1. The Selenium remote server requires Java to run. Download the latest JDK for your platform from the Java SE downloads page. Install it when it is downloaded.
  2. +
  3. Next, download the latest Selenium standalone server — this acts as a proxy between your script and the browser drivers. Choose the latest stable version number (i.e. not a beta), and from the list choose a file starting with "selenium-server-standalone". When this has downloaded, put it in a sensible place, like in your home directory. If you've not already added the location to your PATH, do so now (see the {{anch("Setting up Selenium in Node")}} section).
  4. +
  5. Run the standalone server by entering the following into a terminal on your server computer +
    java -jar selenium-server-standalone-3.0.0.jar
    + (update the .jar filename) so it matches exactly what file you've got.
  6. +
  7. The server will run on http://localhost:4444/wd/hub — try going there now to see what you get.
  8. +
+ +

Now we've got the server running, let's create a demo test that will run on the remote selenium server.

+ +
    +
  1. Create a copy of your google_test.js file, and call it google_test_remote.js; put it in your project directory.
  2. +
  3. Update the second code block (which starts with var driver = ) like so +
    var driver = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .usingServer('http://localhost:4444/wd/hub')
    +    .build();
    +
  4. +
  5. Run your test, and you should see it run as expected; this time however you will be runing it on the standalone server: +
    node google_test_remote.js
    +
  6. +
+ +

So this is pretty cool. We have tested this locally, but you could set this up on just about any server along with the relevant browser drivers, and then connect your scripts to it using the URL you choose to expose it at.

+ +

selenium と CI ツールのインテグレーション

+ +

As another point, it is also possible to integrate Selenium and related tools like Sauce Labs with continuous integration (CI) tools — this is useful, as it means you can run your tests via a CI tool, and only commit new changes to your code repository if the tests pass.

+ +

It is out of scope to look at this area in detail in this article, but we'd suggest getting started with Travis CI — this is probably the easiest CI tool to get started with, and has good integration with web tools like GitHub and Node.

+ +

To get started, see 例えば、:

+ + + +

まとめ

+ +

This module should have proven fun, and should have given you enough of an insight into writing and running automated tests for you to get going with writing your own automated tests.

+ +

{{PreviousMenu("Learn/Tools_and_testing/Cross_browser_testing/Automated_testing", "Learn/Tools_and_testing/Cross_browser_testing")}}

+ + + +

このモジュール内

+ + + + + + + + + +
+ +
+

...

+
diff --git a/files/ja/learn/tools_and_testing/index.html b/files/ja/learn/tools_and_testing/index.html new file mode 100644 index 0000000000..152ebc54eb --- /dev/null +++ b/files/ja/learn/tools_and_testing/index.html @@ -0,0 +1,49 @@ +--- +title: ツールとテスト +slug: Learn/Tools_and_testing +tags: + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - TopicStub + - user testing + - アクセシビリティ + - クロスブラウザ + - ツール + - テスト + - トピック + - 初心者 + - 学習 + - 自動化 +translation_of: Learn/Tools_and_testing +--- +
{{LearnSidebar}}
+ +

ウェブ技術のコア (HTML, CSS,  JavaScript のような) での快適なプログラミングを開始して、経験を積んで、色んなリソースを読み、色んなコツや技を学習すると、JavaScript フレームワークからテスト自動化ツールやそれ以外まで、すべてのツールに出くわします。ウェブプロジェクトが大きく複雑になっていくと、こうしたツールを活用したり、コードの信頼できるテスト計画を考案したくなるでしょう。

+ +

さらに、クロスブラウザーのサポートを引き続き維持することを念頭に置き、ユーザーのウェブブラウジングに使用されているさまざまなブラウザーやデバイス間でプロジェクトを動作させるベストプラクティスに従う必要があります。そして障害を持つ人々が利用できるようにすることです。

+ +

あなたが使用すべきツールを考え出すことは難しい処理でありえるため、私たちは一連の記事を書いて、利用可能なツールの種類、あなたのためにできること、現在の業界のお気に入りを利用する方法をお伝えします。

+ +
+

メモ: このトピックでは多数のツールを参照していますが、必ずしもこれらのツールを最良または唯一の方法として推奨しているわけではなく、動作していてサポートしているためです。ほとんどの場合、他にも方法がありますが、古いものは時代遅れで、間違いなく新しいものが出てきます。

+
+ +

学習経路

+ +

ここで説明したツールを使用する前にまずベースとなる HTMLCSS、および JavaScript 言語の基本を最初に理解しておく必要があります。たとえば、複雑な Web コードで問題をデバッグしたり、JavaScript フレームワークを効果的に使用したり、テストランナーなどを使用してコードをテストして実行したりする前に、これらの言語の基礎を知る必要があります。

+ +

それに加えて、このトピックの最初のモジュールから始めて、そこでエリア全体の便利な概観を得るべきでしょう。

+ +

モジュール

+ +
+
クライアント側ウェブ開発ツールの理解
+
クライアント側のツールには脅威を感じますが、この記事シリーズではいくつかの普遍的なクライアント側のツール種類ごとに目的を例示して、一緒に連携させるツールや、パッケージマネージャーを使ったインストール方法、コマンドラインでの制御を説明します。最後にツールチェーンの例と、どのように生産的になるのかを示します。
+
Git と GitHub
+
開発者はいくつかの バージョン管理システム (VCS)を使い、このツールにてプロジェクトの他の開発者と、お互いの成果を上書きする危険なく、後に問題が見つかった場合前バージョンのコードベースにロールバックできます。最も人気のある VCS (少なくともウェブ開発では) は Git と、それで動作するリポジトリとツールをホストするサイトの GitHub です。このモジュールではその両方について知っておくべきことを教えます。
+
クロスブラウザーテスト
+
このモジュールではさまざまなブラウザー間でウェブプロジェクトをテストする領域を具体的に示しています。ここでは、ターゲットとするユーザー層 (たとえばユーザー、ブラウザー、デバイスの中で最も心配する必要があるもの)、テストの方法、さまざまな種類のコードで直面する主な問題、問題をテストして解決するのに最も有用なツールと、テストをスピードアップするために自動化する方法について説明します。
+
-- cgit v1.2.3-54-g00ecf